spine-framework 0.3.54 → 0.3.56

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -255,6 +255,25 @@ async function fastReassemble(projectRoot: string): Promise<void> {
255
255
  copyChangedFiles(customFuncsDir, funcsDest)
256
256
  }
257
257
  }
258
+
259
+ // Reassemble spine.config.json to public directory
260
+ const spineConfigSrc = resolve(projectRoot, 'spine.config.json')
261
+ const publicDest = resolve(srcDest, 'public')
262
+ if (existsSync(spineConfigSrc)) {
263
+ if (!existsSync(publicDest)) {
264
+ mkdirSync(publicDest, { recursive: true })
265
+ }
266
+ const spineConfigDest = resolve(publicDest, 'spine.config.json')
267
+ const srcStat = statSync(spineConfigSrc)
268
+ let needsCopy = true
269
+ if (existsSync(spineConfigDest)) {
270
+ const destStat = statSync(spineConfigDest)
271
+ needsCopy = srcStat.mtimeMs > destStat.mtimeMs
272
+ }
273
+ if (needsCopy) {
274
+ copyFileSync(spineConfigSrc, spineConfigDest)
275
+ }
276
+ }
258
277
  }
259
278
 
260
279
  /**
@@ -18,7 +18,7 @@
18
18
  */
19
19
 
20
20
  import type { Command } from 'commander'
21
- import { existsSync, readFileSync, mkdirSync, cpSync } from 'fs'
21
+ import { existsSync, readFileSync, mkdirSync, cpSync, writeFileSync } from 'fs'
22
22
  import { resolve, dirname, join, basename } from 'path'
23
23
  import { fileURLToPath } from 'url'
24
24
  import { execSync } from 'child_process'
@@ -81,6 +81,14 @@ export function registerInstallAppCommands(program: Command) {
81
81
  await seedApp(appDest, appSlug)
82
82
  }
83
83
 
84
+ // 6. Aggregate registration config from manifest into spine.config.json
85
+ const manifestPath = join(appDest, 'manifest.json')
86
+ let manifest: Record<string, any> = {}
87
+ try { manifest = JSON.parse(readFileSync(manifestPath, 'utf8')) } catch {}
88
+ if (manifest.registration?.enabled) {
89
+ updateRegistrationConfig(appSlug, manifest.registration)
90
+ }
91
+
84
92
  console.log(`\n✅ ${appSlug} installed successfully!\n`)
85
93
  console.log('Next: npm run assemble && netlify dev\n')
86
94
 
@@ -153,6 +161,14 @@ export function registerInstallAppCommands(program: Command) {
153
161
  }
154
162
  }
155
163
 
164
+ // Update registration config from manifest
165
+ const manifestPath = join(appDest, 'manifest.json')
166
+ let manifest: Record<string, any> = {}
167
+ try { manifest = JSON.parse(readFileSync(manifestPath, 'utf8')) } catch {}
168
+ if (manifest.registration?.enabled) {
169
+ updateRegistrationConfig(appSlug, manifest.registration)
170
+ }
171
+
156
172
  console.log(`\n✅ ${appSlug} updated.\n`)
157
173
  } catch (err: any) {
158
174
  console.error(`\n❌ Update failed: ${err.message}`)
@@ -278,3 +294,75 @@ async function seedApp(appDir: string, appSlug: string) {
278
294
  }
279
295
  }
280
296
  }
297
+
298
+ // ─── SPINE CONFIG HELPERS ───────────────────────────────────────────────────
299
+
300
+ interface RegistrationConfig {
301
+ enabled: boolean
302
+ default_role: string
303
+ redirect_path: string
304
+ }
305
+
306
+ interface SpineConfig {
307
+ registration?: {
308
+ default_app?: string
309
+ default_role?: string
310
+ allow_url_override?: boolean
311
+ apps?: Record<string, {
312
+ role: string
313
+ path: string
314
+ enabled: boolean
315
+ }>
316
+ }
317
+ }
318
+
319
+ const SPINE_CONFIG_PATH = join(PROJECT_ROOT, 'spine.config.json')
320
+
321
+ function loadSpineConfig(): SpineConfig {
322
+ if (!existsSync(SPINE_CONFIG_PATH)) {
323
+ return { registration: { apps: {} } }
324
+ }
325
+ try {
326
+ return JSON.parse(readFileSync(SPINE_CONFIG_PATH, 'utf8'))
327
+ } catch {
328
+ return { registration: { apps: {} } }
329
+ }
330
+ }
331
+
332
+ function saveSpineConfig(config: SpineConfig): void {
333
+ writeFileSync(SPINE_CONFIG_PATH, JSON.stringify(config, null, 2) + '\n')
334
+ }
335
+
336
+ function updateRegistrationConfig(appSlug: string, regConfig: RegistrationConfig): void {
337
+ const config = loadSpineConfig()
338
+
339
+ // Ensure registration section exists
340
+ if (!config.registration) {
341
+ config.registration = { apps: {} }
342
+ }
343
+ if (!config.registration.apps) {
344
+ config.registration.apps = {}
345
+ }
346
+
347
+ // Add/update this app's registration entry
348
+ config.registration.apps[appSlug] = {
349
+ role: regConfig.default_role,
350
+ path: regConfig.redirect_path,
351
+ enabled: regConfig.enabled,
352
+ }
353
+
354
+ // If this is the first registration-enabled app, make it the default
355
+ const enabledApps = Object.entries(config.registration.apps).filter(([, cfg]) => cfg.enabled)
356
+ if (enabledApps.length === 1 || !config.registration.default_app) {
357
+ config.registration.default_app = appSlug
358
+ config.registration.default_role = regConfig.default_role
359
+ }
360
+
361
+ // Default allow_url_override to true if not set
362
+ if (config.registration.allow_url_override === undefined) {
363
+ config.registration.allow_url_override = true
364
+ }
365
+
366
+ saveSpineConfig(config)
367
+ console.log(` ✓ Updated spine.config.json registration for ${appSlug}`)
368
+ }
@@ -77,6 +77,7 @@ export const context = createHandler(async (ctx, _body) => {
77
77
  avatar_url,
78
78
  account_id,
79
79
  role_id,
80
+ status,
80
81
  account:accounts!people_account_id_fkey(
81
82
  id,
82
83
  slug,
@@ -154,6 +155,7 @@ export const context = createHandler(async (ctx, _body) => {
154
155
  roles: [roleSlug].filter(Boolean),
155
156
  permissions: effectivePermissions,
156
157
  is_system_admin: roleSlug === 'system_admin',
158
+ status: personData.status ?? 'active',
157
159
  accessible_accounts: accessibleAccounts
158
160
  }
159
161
  })