spine-framework 0.1.5 → 0.1.8
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.
|
@@ -31,7 +31,6 @@ import type { Command } from 'commander'
|
|
|
31
31
|
import { existsSync, mkdirSync, readFileSync, writeFileSync } from 'fs'
|
|
32
32
|
import { resolve, dirname } from 'path'
|
|
33
33
|
import { fileURLToPath } from 'url'
|
|
34
|
-
import { adminDb } from '../../functions/_shared/index.ts'
|
|
35
34
|
|
|
36
35
|
const __filename = fileURLToPath(import.meta.url)
|
|
37
36
|
const __dirname = dirname(__filename)
|
|
@@ -70,13 +69,7 @@ async function runMigration(filename: string, dryRun: boolean): Promise<boolean>
|
|
|
70
69
|
return false
|
|
71
70
|
}
|
|
72
71
|
|
|
73
|
-
//
|
|
74
|
-
const { error } = await adminDb.rpc('exec_sql', { query: sql }).single()
|
|
75
|
-
if (!error) return true
|
|
76
|
-
|
|
77
|
-
// Fallback: use the Supabase /pg/query endpoint for raw SQL execution
|
|
78
|
-
console.log(` ⚠️ exec_sql not available, using direct SQL endpoint...`)
|
|
79
|
-
|
|
72
|
+
// Use the Supabase /pg/query endpoint for raw SQL execution
|
|
80
73
|
const pgResponse = await fetch(`${supabaseUrl}/pg/query`, {
|
|
81
74
|
method: 'POST',
|
|
82
75
|
headers: {
|
|
@@ -137,13 +130,15 @@ function scaffoldCustomWorkspace(dryRun: boolean): void {
|
|
|
137
130
|
|
|
138
131
|
async function checkAlreadyInitialized(): Promise<boolean> {
|
|
139
132
|
try {
|
|
140
|
-
const
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
.
|
|
145
|
-
|
|
146
|
-
|
|
133
|
+
const supabaseUrl = process.env.SUPABASE_URL
|
|
134
|
+
const serviceKey = process.env.SUPABASE_SERVICE_ROLE_KEY
|
|
135
|
+
if (!supabaseUrl || !serviceKey) return false
|
|
136
|
+
const res = await fetch(
|
|
137
|
+
`${supabaseUrl}/rest/v1/apps?slug=eq.spine-core&select=slug&limit=1`,
|
|
138
|
+
{ headers: { apikey: serviceKey, Authorization: `Bearer ${serviceKey}` } }
|
|
139
|
+
)
|
|
140
|
+
const rows = await res.json() as any[]
|
|
141
|
+
return Array.isArray(rows) && rows.length > 0
|
|
147
142
|
} catch {
|
|
148
143
|
return false
|
|
149
144
|
}
|
|
@@ -229,12 +224,21 @@ async function initCommand(options: InitOptions): Promise<void> {
|
|
|
229
224
|
// Step 3: Record migration versions
|
|
230
225
|
if (!options.dryRun) {
|
|
231
226
|
console.log('\n📝 Step 3: Recording migration versions...')
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
227
|
+
const supabaseUrl = process.env.SUPABASE_URL!
|
|
228
|
+
const serviceKey = process.env.SUPABASE_SERVICE_ROLE_KEY!
|
|
229
|
+
await fetch(`${supabaseUrl}/rest/v1/schema_migrations`, {
|
|
230
|
+
method: 'POST',
|
|
231
|
+
headers: {
|
|
232
|
+
'Content-Type': 'application/json',
|
|
233
|
+
'apikey': serviceKey,
|
|
234
|
+
'Authorization': `Bearer ${serviceKey}`,
|
|
235
|
+
'Prefer': 'resolution=merge-duplicates',
|
|
236
|
+
},
|
|
237
|
+
body: JSON.stringify([
|
|
235
238
|
{ version: '000_foundation', applied_at: new Date().toISOString() },
|
|
236
239
|
{ version: '001_seed', applied_at: new Date().toISOString() },
|
|
237
|
-
]
|
|
240
|
+
])
|
|
241
|
+
})
|
|
238
242
|
console.log(' ✓ Migration versions recorded')
|
|
239
243
|
}
|
|
240
244
|
|
package/.framework/cli/index.ts
CHANGED
|
@@ -41,21 +41,6 @@
|
|
|
41
41
|
|
|
42
42
|
import './env-loader.ts'
|
|
43
43
|
import { Command } from 'commander'
|
|
44
|
-
import { createRequire } from 'module'
|
|
45
|
-
import { resolve, dirname } from 'path'
|
|
46
|
-
import { fileURLToPath } from 'url'
|
|
47
|
-
|
|
48
|
-
const __filename = fileURLToPath(import.meta.url)
|
|
49
|
-
const __dirname = dirname(__filename)
|
|
50
|
-
|
|
51
|
-
function printWelcome() {
|
|
52
|
-
const require = createRequire(import.meta.url)
|
|
53
|
-
try {
|
|
54
|
-
require(resolve(__dirname, '../../bin/welcome.cjs'))
|
|
55
|
-
} catch {
|
|
56
|
-
console.log('Spine Framework — run `spine-framework --help` for commands.')
|
|
57
|
-
}
|
|
58
|
-
}
|
|
59
44
|
|
|
60
45
|
const program = new Command()
|
|
61
46
|
|
|
@@ -115,12 +100,6 @@ registerInstallAppCommands(program)
|
|
|
115
100
|
registerStatusCommands(program)
|
|
116
101
|
registerUninstallAppCommands(program)
|
|
117
102
|
|
|
118
|
-
// Show welcome when run with no arguments
|
|
119
|
-
if (process.argv.length === 2) {
|
|
120
|
-
printWelcome()
|
|
121
|
-
process.exit(0)
|
|
122
|
-
}
|
|
123
|
-
|
|
124
103
|
program.parseAsync(process.argv).catch((err) => {
|
|
125
104
|
console.error('Error:', err.message)
|
|
126
105
|
process.exit(1)
|
|
@@ -18,11 +18,6 @@ import { createClient } from '@supabase/supabase-js'
|
|
|
18
18
|
|
|
19
19
|
// ─── ENVIRONMENT RESOLUTION ──────────────────────────────────────────────────
|
|
20
20
|
|
|
21
|
-
const _env = (globalThis as any).process?.env || {}
|
|
22
|
-
const supabaseUrl: string = _env.SUPABASE_URL!
|
|
23
|
-
const supabaseServiceKey: string = _env.SUPABASE_SERVICE_ROLE_KEY!
|
|
24
|
-
const supabaseAnonKey: string = _env.SUPABASE_ANON_KEY!
|
|
25
|
-
|
|
26
21
|
/**
|
|
27
22
|
* Active database schema name, read from `DB_SCHEMA` env var.
|
|
28
23
|
*
|
|
@@ -35,8 +30,22 @@ const supabaseAnonKey: string = _env.SUPABASE_ANON_KEY!
|
|
|
35
30
|
* @sideEffects none
|
|
36
31
|
* @calledBy adminDb, getUserDb (applied at client construction time)
|
|
37
32
|
*/
|
|
33
|
+
const _env = (globalThis as any).process?.env || {}
|
|
34
|
+
const supabaseUrl: string = _env.SUPABASE_URL!
|
|
35
|
+
const supabaseServiceKey: string = _env.SUPABASE_SERVICE_ROLE_KEY!
|
|
36
|
+
const supabaseAnonKey: string = _env.SUPABASE_ANON_KEY!
|
|
38
37
|
const dbSchema: string = _env.DB_SCHEMA || 'public'
|
|
39
38
|
|
|
39
|
+
function getEnv() {
|
|
40
|
+
const e = (globalThis as any).process?.env || {}
|
|
41
|
+
return {
|
|
42
|
+
supabaseUrl: e.SUPABASE_URL as string,
|
|
43
|
+
supabaseServiceKey: e.SUPABASE_SERVICE_ROLE_KEY as string,
|
|
44
|
+
supabaseAnonKey: e.SUPABASE_ANON_KEY as string,
|
|
45
|
+
dbSchema: (e.DB_SCHEMA || 'public') as string,
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
|
|
40
49
|
// ─── CLIENTS ─────────────────────────────────────────────────────────────────
|
|
41
50
|
|
|
42
51
|
/**
|
|
@@ -74,9 +83,7 @@ const dbSchema: string = _env.DB_SCHEMA || 'public'
|
|
|
74
83
|
* ```
|
|
75
84
|
*/
|
|
76
85
|
export const adminDb = createClient(supabaseUrl, supabaseServiceKey, {
|
|
77
|
-
db: {
|
|
78
|
-
schema: dbSchema
|
|
79
|
-
}
|
|
86
|
+
db: { schema: dbSchema }
|
|
80
87
|
})
|
|
81
88
|
|
|
82
89
|
// ─── CHUNK_START: SHARED_DB_GET_USER_DB ──────────────────────────────────────────────
|
|
@@ -94,6 +101,7 @@ export const adminDb = createClient(supabaseUrl, supabaseServiceKey, {
|
|
|
94
101
|
* @tags database, supabase, rls, authentication, user-scoped
|
|
95
102
|
*/
|
|
96
103
|
export function getUserDb(jwt: string) {
|
|
104
|
+
const { supabaseUrl, supabaseAnonKey, dbSchema } = getEnv()
|
|
97
105
|
return createClient(supabaseUrl, supabaseAnonKey, {
|
|
98
106
|
db: {
|
|
99
107
|
schema: dbSchema
|
package/bin/spine-framework.cjs
CHANGED
|
@@ -1,22 +1,27 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
// Thin shebang wrapper — invokes the TypeScript CLI via tsx.
|
|
3
3
|
// This file is the npm bin entry point for spine-framework.
|
|
4
|
-
const { execFileSync
|
|
4
|
+
const { execFileSync } = require('child_process')
|
|
5
5
|
const { resolve } = require('path')
|
|
6
6
|
|
|
7
|
-
// __dirname = <project>/node_modules/spine-framework/bin
|
|
8
|
-
// tsx lives at <project>/node_modules/.bin/tsx
|
|
9
7
|
const pkgRoot = resolve(__dirname, '..')
|
|
10
8
|
const projectRoot = resolve(pkgRoot, '../..')
|
|
9
|
+
|
|
10
|
+
// Handle no-args case here — before spawning tsx or loading db.ts
|
|
11
|
+
if (process.argv.length === 2) {
|
|
12
|
+
require(resolve(__dirname, 'welcome.cjs'))
|
|
13
|
+
process.exit(0)
|
|
14
|
+
}
|
|
15
|
+
|
|
11
16
|
const entry = resolve(pkgRoot, '.framework/cli/index.ts')
|
|
12
17
|
|
|
13
18
|
// Find tsx: prefer consuming project's copy, fall back to our own
|
|
19
|
+
const fs = require('fs')
|
|
14
20
|
const tsxPaths = [
|
|
15
21
|
resolve(projectRoot, 'node_modules/.bin/tsx'),
|
|
16
22
|
resolve(pkgRoot, 'node_modules/.bin/tsx'),
|
|
17
23
|
]
|
|
18
|
-
|
|
19
|
-
const tsx = tsxPaths.find(p => { try { require('fs').accessSync(p); return true } catch { return false } })
|
|
24
|
+
const tsx = tsxPaths.find(p => { try { fs.accessSync(p); return true } catch { return false } })
|
|
20
25
|
|
|
21
26
|
if (!tsx) {
|
|
22
27
|
console.error('spine-framework: tsx not found. Run: npm install tsx')
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"init.d.ts","sourceRoot":"","sources":["../../../.framework/cli/commands/init.ts"],"names":[],"mappings":"AACA;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AAEH,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAA;
|
|
1
|
+
{"version":3,"file":"init.d.ts","sourceRoot":"","sources":["../../../.framework/cli/commands/init.ts"],"names":[],"mappings":"AACA;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AAEH,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAA;AAoOxC,wBAAgB,oBAAoB,CAAC,OAAO,EAAE,OAAO,QAkBpD"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"db.d.ts","sourceRoot":"","sources":["../../../.framework/functions/_shared/db.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;
|
|
1
|
+
{"version":3,"file":"db.d.ts","sourceRoot":"","sources":["../../../.framework/functions/_shared/db.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAoCH;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAiCG;AACH,eAAO,MAAM,OAAO,iFAElB,CAAA;AAGF;;;;;;;;;;;;GAYG;AACH,wBAAgB,SAAS,CAAC,GAAG,EAAE,MAAM,mFAYpC;AAKD;;;;;;;;;;;;;;;;;;GAkBG;AACH,MAAM,MAAM,QAAQ,CAAC,CAAC,IAAI;IACxB,IAAI,EAAE,CAAC,GAAG,IAAI,CAAA;IACd,KAAK,EAAE,GAAG,CAAA;CACX,CAAA;AAID;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AACH,eAAO,MAAM,KAAK;;;;;;;;CAQjB,CAAA"}
|