spine-framework 0.3.32 → 0.3.34
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.
- package/.framework/cli/index.ts +52 -54
- package/.framework/functions/_shared/db.ts +9 -24
- package/bin/spine-framework.cjs +68 -0
- package/bin/ws-shim.ts +1 -1
- package/package.json +3 -2
package/.framework/cli/index.ts
CHANGED
|
@@ -46,59 +46,57 @@ program
|
|
|
46
46
|
.version('2.0.0')
|
|
47
47
|
.option('--account <id>', 'Override the account ID for this command')
|
|
48
48
|
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
])
|
|
49
|
+
const [
|
|
50
|
+
{ registerInitCommands },
|
|
51
|
+
{ registerMigrateCommands },
|
|
52
|
+
{ registerInstallAppCommands },
|
|
53
|
+
{ registerStatusCommands },
|
|
54
|
+
{ registerAuthCommands },
|
|
55
|
+
{ registerPipelineCommands },
|
|
56
|
+
{ registerItemCommands },
|
|
57
|
+
{ registerAgentCommands },
|
|
58
|
+
{ registerMigrationCommands },
|
|
59
|
+
{ registerDoctorCommands },
|
|
60
|
+
{ registerDevCommands },
|
|
61
|
+
{ registerTestCommands },
|
|
62
|
+
{ registerSystemCommands },
|
|
63
|
+
{ registerGenerateCommands },
|
|
64
|
+
{ registerCreateAppCommands },
|
|
65
|
+
] = await Promise.all([
|
|
66
|
+
import('./commands/init.ts'),
|
|
67
|
+
import('./commands/migrate.ts'),
|
|
68
|
+
import('./commands/install-app.ts'),
|
|
69
|
+
import('./commands/status.ts'),
|
|
70
|
+
import('./commands/auth.ts'),
|
|
71
|
+
import('./commands/pipelines.ts'),
|
|
72
|
+
import('./commands/items.ts'),
|
|
73
|
+
import('./commands/agents.ts'),
|
|
74
|
+
import('./commands/migrations.ts'),
|
|
75
|
+
import('./commands/doctor.ts'),
|
|
76
|
+
import('./commands/dev.ts'),
|
|
77
|
+
import('./commands/test.ts'),
|
|
78
|
+
import('./commands/system.ts'),
|
|
79
|
+
import('./commands/generate.ts'),
|
|
80
|
+
import('./commands/create-app.ts'),
|
|
81
|
+
])
|
|
83
82
|
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
83
|
+
registerInitCommands(program)
|
|
84
|
+
registerMigrateCommands(program)
|
|
85
|
+
registerInstallAppCommands(program)
|
|
86
|
+
registerStatusCommands(program)
|
|
87
|
+
registerAuthCommands(program)
|
|
88
|
+
registerPipelineCommands(program)
|
|
89
|
+
registerItemCommands(program)
|
|
90
|
+
registerAgentCommands(program)
|
|
91
|
+
registerMigrationCommands(program)
|
|
92
|
+
registerDoctorCommands(program)
|
|
93
|
+
registerDevCommands(program)
|
|
94
|
+
registerTestCommands(program)
|
|
95
|
+
registerSystemCommands(program)
|
|
96
|
+
registerGenerateCommands(program)
|
|
97
|
+
registerCreateAppCommands(program)
|
|
99
98
|
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
})()
|
|
99
|
+
program.parseAsync(process.argv).catch((err) => {
|
|
100
|
+
console.error('Error:', err.message)
|
|
101
|
+
process.exit(1)
|
|
102
|
+
})
|
|
@@ -18,8 +18,11 @@ import { createClient } from '@supabase/supabase-js'
|
|
|
18
18
|
|
|
19
19
|
// ─── ENVIRONMENT RESOLUTION ──────────────────────────────────────────────────
|
|
20
20
|
|
|
21
|
-
|
|
22
|
-
|
|
21
|
+
const _env = (globalThis as any).process?.env || {}
|
|
22
|
+
const supabaseUrl: string = _env.SUPABASE_URL || 'https://placeholder.supabase.co'
|
|
23
|
+
const supabaseServiceKey: string = _env.SUPABASE_SERVICE_ROLE_KEY || ''
|
|
24
|
+
const supabaseAnonKey: string = _env.SUPABASE_ANON_KEY || ''
|
|
25
|
+
const dbSchema: string = _env.DB_SCHEMA || 'public'
|
|
23
26
|
|
|
24
27
|
// ─── CLIENTS ─────────────────────────────────────────────────────────────────
|
|
25
28
|
|
|
@@ -57,23 +60,8 @@ import { createClient } from '@supabase/supabase-js'
|
|
|
57
60
|
* // Only use adminDb if your custom code runs as a system/cron principal
|
|
58
61
|
* ```
|
|
59
62
|
*/
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
const key = (globalThis as any).process?.env?.SUPABASE_SERVICE_ROLE_KEY
|
|
63
|
-
const schema = (globalThis as any).process?.env?.DB_SCHEMA || 'public'
|
|
64
|
-
if (!url || !key) {
|
|
65
|
-
throw new Error(
|
|
66
|
-
'SUPABASE_URL and SUPABASE_SERVICE_ROLE_KEY must be set.\n' +
|
|
67
|
-
'Add them to your .env file and run: npx spine-framework migrate'
|
|
68
|
-
)
|
|
69
|
-
}
|
|
70
|
-
return createClient(url, key, { db: { schema } })
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
export const adminDb = new Proxy({} as ReturnType<typeof getAdminDb>, {
|
|
74
|
-
get(_target, prop) {
|
|
75
|
-
return (getAdminDb() as any)[prop]
|
|
76
|
-
}
|
|
63
|
+
export const adminDb = createClient(supabaseUrl, supabaseServiceKey, {
|
|
64
|
+
db: { schema: dbSchema }
|
|
77
65
|
})
|
|
78
66
|
|
|
79
67
|
// ─── CHUNK_START: SHARED_DB_GET_USER_DB ──────────────────────────────────────────────
|
|
@@ -91,11 +79,8 @@ export const adminDb = new Proxy({} as ReturnType<typeof getAdminDb>, {
|
|
|
91
79
|
* @tags database, supabase, rls, authentication, user-scoped
|
|
92
80
|
*/
|
|
93
81
|
export function getUserDb(jwt: string) {
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
const schema = (globalThis as any).process?.env?.DB_SCHEMA || 'public'
|
|
97
|
-
return createClient(url, anonKey, {
|
|
98
|
-
db: { schema },
|
|
82
|
+
return createClient(supabaseUrl, supabaseAnonKey, {
|
|
83
|
+
db: { schema: dbSchema },
|
|
99
84
|
global: { headers: { Authorization: `Bearer ${jwt}` } }
|
|
100
85
|
})
|
|
101
86
|
}
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
// Thin shebang wrapper — invokes the TypeScript CLI via tsx.
|
|
3
|
+
// This file is the npm bin entry point for spine-framework.
|
|
4
|
+
const { execFileSync } = require('child_process')
|
|
5
|
+
const { resolve } = require('path')
|
|
6
|
+
const fs = require('fs')
|
|
7
|
+
|
|
8
|
+
const pkgRoot = resolve(__dirname, '..')
|
|
9
|
+
const projectRoot = resolve(pkgRoot, '../..')
|
|
10
|
+
|
|
11
|
+
// Handle no-args case — show welcome before spawning tsx
|
|
12
|
+
if (process.argv.length === 2) {
|
|
13
|
+
console.log('\nSpine Framework CLI')
|
|
14
|
+
console.log('Usage: spine-framework <command>\n')
|
|
15
|
+
console.log('Commands:')
|
|
16
|
+
console.log(' init Scaffold a new Spine Framework project')
|
|
17
|
+
console.log(' migrate Apply database migrations')
|
|
18
|
+
console.log(' install-app Install a Spine Framework app from npm')
|
|
19
|
+
console.log(' status Show installed apps and framework version')
|
|
20
|
+
console.log('\nRun spine-framework --help for full command list\n')
|
|
21
|
+
process.exit(0)
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
// Pre-load .env from the consumer project root so db.ts sees env vars at module load time.
|
|
25
|
+
// tsx evaluates imports before Commander parses args, so we must inject here.
|
|
26
|
+
const args = process.argv.slice(2)
|
|
27
|
+
const childEnv = { ...process.env }
|
|
28
|
+
|
|
29
|
+
const dotenvPath = resolve(process.cwd(), '.env')
|
|
30
|
+
if (fs.existsSync(dotenvPath)) {
|
|
31
|
+
const lines = fs.readFileSync(dotenvPath, 'utf8').split('\n')
|
|
32
|
+
for (const line of lines) {
|
|
33
|
+
const trimmed = line.trim()
|
|
34
|
+
if (!trimmed || trimmed.startsWith('#')) continue
|
|
35
|
+
const eq = trimmed.indexOf('=')
|
|
36
|
+
if (eq === -1) continue
|
|
37
|
+
const key = trimmed.slice(0, eq).trim()
|
|
38
|
+
const val = trimmed.slice(eq + 1).trim()
|
|
39
|
+
if (key && !(key in childEnv)) childEnv[key] = val
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
// CLI flags override .env values
|
|
44
|
+
for (let i = 0; i < args.length; i++) {
|
|
45
|
+
if (args[i] === '--url' && args[i + 1]) childEnv.SUPABASE_URL = args[++i]
|
|
46
|
+
if (args[i] === '--anon-key' && args[i + 1]) childEnv.SUPABASE_ANON_KEY = args[++i]
|
|
47
|
+
if (args[i] === '--service-role-key' && args[i + 1]) childEnv.SUPABASE_SERVICE_ROLE_KEY = args[++i]
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
const entry = resolve(pkgRoot, 'bin/ws-shim.mts')
|
|
51
|
+
|
|
52
|
+
// Find tsx: prefer consuming project's copy, fall back to our own
|
|
53
|
+
const tsxPaths = [
|
|
54
|
+
resolve(projectRoot, 'node_modules/.bin/tsx'),
|
|
55
|
+
resolve(pkgRoot, 'node_modules/.bin/tsx'),
|
|
56
|
+
]
|
|
57
|
+
const tsx = tsxPaths.find(p => { try { fs.accessSync(p); return true } catch { return false } })
|
|
58
|
+
|
|
59
|
+
if (!tsx) {
|
|
60
|
+
console.error('spine-framework: tsx not found. Run: npm install tsx')
|
|
61
|
+
process.exit(1)
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
try {
|
|
65
|
+
execFileSync(tsx, [entry, ...process.argv.slice(2)], { stdio: 'inherit', env: childEnv })
|
|
66
|
+
} catch (e) {
|
|
67
|
+
process.exit(e.status ?? 1)
|
|
68
|
+
}
|
package/bin/ws-shim.ts
CHANGED
package/package.json
CHANGED
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "spine-framework",
|
|
3
|
-
"version": "0.3.
|
|
3
|
+
"version": "0.3.34",
|
|
4
4
|
"description": "Multi-tenant, modular application platform for modern SaaS systems",
|
|
5
|
+
"type": "module",
|
|
5
6
|
"bin": {
|
|
6
|
-
"spine-framework": "bin/spine-framework.
|
|
7
|
+
"spine-framework": "bin/spine-framework.cjs"
|
|
7
8
|
},
|
|
8
9
|
"files": [
|
|
9
10
|
"bin/",
|