Feat v0.9.4 package adoption roles (#78)
All checks were successful
CI/CD / detect-changes (push) Successful in 3s
CI/CD / test-frontend (push) Has been skipped
CI/CD / test-runners (push) Has been skipped
CI/CD / e2e-smoke (push) Has been skipped
CI/CD / test-go-pg (push) Successful in 2m55s
CI/CD / test-sqlite (push) Successful in 3m7s
CI/CD / build-and-deploy (push) Successful in 1m19s

Co-authored-by: Jeffrey Smith <jasafpro@gmail.com>
Co-committed-by: Jeffrey Smith <jasafpro@gmail.com>
This commit was merged in pull request #78.
This commit is contained in:
2026-04-03 16:23:43 +00:00
committed by xcaliber
parent 0661e1d768
commit 6b9ce92103
19 changed files with 2268 additions and 48 deletions

View File

@@ -109,18 +109,22 @@ func (s *PackageStore) Create(ctx context.Context, pkg *store.PackageRegistratio
if pkg.Status == "" {
pkg.Status = "active"
}
adoptableInt := 0
if pkg.Adoptable {
adoptableInt = 1
}
_, err := DB.ExecContext(ctx, `
INSERT INTO packages (id, title, type, version, description, author, tier,
is_system, scope, team_id, installed_by, manifest, enabled, status,
schema_version, package_settings, source,
schema_version, package_settings, source, adoptable, adopted_from,
installed_at, updated_at)
VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)`,
VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)`,
pkg.ID, pkg.Title, pkg.Type, pkg.Version, pkg.Description, pkg.Author,
pkg.Tier, pkg.IsSystem, pkg.Scope,
nullStrPtr(pkg.TeamID), nullStrPtr(pkg.InstalledBy),
manifestJSON, pkg.Enabled, pkg.Status,
pkg.SchemaVersion, defaultJSON(pkg.PackageSettings),
pkg.Source,
pkg.Source, adoptableInt, nullStrPtr(pkg.AdoptedFrom),
now.Format(timeFmt), now.Format(timeFmt),
)
if err != nil {
@@ -184,11 +188,12 @@ func (s *PackageStore) ListForUser(ctx context.Context, userID string) ([]store.
var result []store.UserPackage
for rows.Next() {
var up store.UserPackage
var teamID, installedBy sql.NullString
var teamID, installedBy, adoptedFrom sql.NullString
var manifestJSON string
var pkgSettings string
var enabledInt int
var isSystemInt int
var adoptableInt int
var userEnabled sql.NullBool
var userSettings []byte
@@ -198,15 +203,18 @@ func (s *PackageStore) ListForUser(ctx context.Context, userID string) ([]store.
&teamID, &installedBy,
&manifestJSON, &enabledInt, &up.Status,
&up.SchemaVersion, &pkgSettings,
&up.Source, &up.InstalledAt, &up.UpdatedAt,
&up.Source, &adoptableInt, &adoptedFrom,
&up.InstalledAt, &up.UpdatedAt,
&userEnabled, &userSettings,
); err != nil {
return nil, err
}
up.IsSystem = isSystemInt != 0
up.Enabled = enabledInt != 0
up.Adoptable = adoptableInt != 0
up.TeamID = NullableStringPtr(teamID)
up.InstalledBy = NullableStringPtr(installedBy)
up.AdoptedFrom = NullableStringPtr(adoptedFrom)
json.Unmarshal([]byte(manifestJSON), &up.Manifest)
up.PackageSettings = json.RawMessage(pkgSettings)
if userEnabled.Valid {
@@ -263,22 +271,25 @@ const pkgCols = `p.id, p.title, p.type, p.version, p.description, p.author,
p.tier, p.is_system, p.scope, p.team_id, p.installed_by,
p.manifest, p.enabled, p.status,
p.schema_version, p.package_settings,
p.source, p.installed_at, p.updated_at`
p.source, p.adoptable, p.adopted_from,
p.installed_at, p.updated_at`
func (s *PackageStore) scanOne(ctx context.Context, query string, args ...interface{}) (*store.PackageRegistration, error) {
var pkg store.PackageRegistration
var teamID, installedBy sql.NullString
var teamID, installedBy, adoptedFrom sql.NullString
var manifestJSON string
var pkgSettings string
var enabledInt int
var isSystemInt int
var adoptableInt int
err := DB.QueryRowContext(ctx, query, args...).Scan(
&pkg.ID, &pkg.Title, &pkg.Type, &pkg.Version, &pkg.Description,
&pkg.Author, &pkg.Tier, &isSystemInt, &pkg.Scope,
&teamID, &installedBy,
&manifestJSON, &enabledInt, &pkg.Status,
&pkg.SchemaVersion, &pkgSettings,
&pkg.Source, &pkg.InstalledAt, &pkg.UpdatedAt,
&pkg.Source, &adoptableInt, &adoptedFrom,
&pkg.InstalledAt, &pkg.UpdatedAt,
)
if err == sql.ErrNoRows {
return nil, nil
@@ -288,8 +299,10 @@ func (s *PackageStore) scanOne(ctx context.Context, query string, args ...interf
}
pkg.IsSystem = isSystemInt != 0
pkg.Enabled = enabledInt != 0
pkg.Adoptable = adoptableInt != 0
pkg.TeamID = NullableStringPtr(teamID)
pkg.InstalledBy = NullableStringPtr(installedBy)
pkg.AdoptedFrom = NullableStringPtr(adoptedFrom)
json.Unmarshal([]byte(manifestJSON), &pkg.Manifest)
pkg.PackageSettings = json.RawMessage(pkgSettings)
return &pkg, nil
@@ -305,25 +318,29 @@ func (s *PackageStore) scanMany(ctx context.Context, query string, args ...inter
var result []store.PackageRegistration
for rows.Next() {
var pkg store.PackageRegistration
var teamID, installedBy sql.NullString
var teamID, installedBy, adoptedFrom sql.NullString
var manifestJSON string
var pkgSettings string
var enabledInt int
var isSystemInt int
var adoptableInt int
if err := rows.Scan(
&pkg.ID, &pkg.Title, &pkg.Type, &pkg.Version, &pkg.Description,
&pkg.Author, &pkg.Tier, &isSystemInt, &pkg.Scope,
&teamID, &installedBy,
&manifestJSON, &enabledInt, &pkg.Status,
&pkg.SchemaVersion, &pkgSettings,
&pkg.Source, &pkg.InstalledAt, &pkg.UpdatedAt,
&pkg.Source, &adoptableInt, &adoptedFrom,
&pkg.InstalledAt, &pkg.UpdatedAt,
); err != nil {
return nil, err
}
pkg.IsSystem = isSystemInt != 0
pkg.Enabled = enabledInt != 0
pkg.Adoptable = adoptableInt != 0
pkg.TeamID = NullableStringPtr(teamID)
pkg.InstalledBy = NullableStringPtr(installedBy)
pkg.AdoptedFrom = NullableStringPtr(adoptedFrom)
json.Unmarshal([]byte(manifestJSON), &pkg.Manifest)
pkg.PackageSettings = json.RawMessage(pkgSettings)
result = append(result, pkg)
@@ -418,6 +435,23 @@ func (s *PackageStore) DeleteTeamSettings(ctx context.Context, pkgID, teamID str
return err
}
// ── v0.9.4 — Package Adoption ───────────────
func (s *PackageStore) ListAdoptable(ctx context.Context) ([]store.PackageRegistration, error) {
return s.scanMany(ctx, `
SELECT `+pkgCols+`
FROM packages p
WHERE p.adoptable = 1 AND p.scope = 'global' AND p.enabled = 1
ORDER BY p.title`)
}
func (s *PackageStore) GetByAdoptedFrom(ctx context.Context, sourceID, teamID string) (*store.PackageRegistration, error) {
return s.scanOne(ctx, `
SELECT `+pkgCols+`
FROM packages p
WHERE p.adopted_from = ? AND p.team_id = ?`, sourceID, teamID)
}
func nullStrPtr(s *string) sql.NullString {
if s == nil {
return sql.NullString{}