spine-framework 0.1.6 → 0.1.9

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
- // Try exec_sql RPC first (works if schema already has it)
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 { data, error } = await adminDb
141
- .from('apps')
142
- .select('slug')
143
- .eq('slug', 'spine-core')
144
- .single()
145
-
146
- return !error && !!data
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
- await adminDb
233
- .from('schema_migrations')
234
- .upsert([
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
- ], { onConflict: 'version' })
240
+ ])
241
+ })
238
242
  console.log(' ✓ Migration versions recorded')
239
243
  }
240
244
 
@@ -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,6 +30,10 @@ 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
 
40
39
  // ─── CLIENTS ─────────────────────────────────────────────────────────────────
@@ -3,6 +3,7 @@
3
3
  // This file is the npm bin entry point for spine-framework.
4
4
  const { execFileSync } = require('child_process')
5
5
  const { resolve } = require('path')
6
+ const fs = require('fs')
6
7
 
7
8
  const pkgRoot = resolve(__dirname, '..')
8
9
  const projectRoot = resolve(pkgRoot, '../..')
@@ -13,10 +14,19 @@ if (process.argv.length === 2) {
13
14
  process.exit(0)
14
15
  }
15
16
 
17
+ // Pre-parse credential flags so db.ts sees them as env vars at module load time.
18
+ // tsx evaluates db.ts before Commander parses args, so we must inject here.
19
+ const args = process.argv.slice(2)
20
+ const childEnv = { ...process.env }
21
+ for (let i = 0; i < args.length; i++) {
22
+ if (args[i] === '--url' && args[i + 1]) childEnv.SUPABASE_URL = args[++i]
23
+ if (args[i] === '--anon-key' && args[i + 1]) childEnv.SUPABASE_ANON_KEY = args[++i]
24
+ if (args[i] === '--service-role-key' && args[i + 1]) childEnv.SUPABASE_SERVICE_ROLE_KEY = args[++i]
25
+ }
26
+
16
27
  const entry = resolve(pkgRoot, '.framework/cli/index.ts')
17
28
 
18
29
  // Find tsx: prefer consuming project's copy, fall back to our own
19
- const fs = require('fs')
20
30
  const tsxPaths = [
21
31
  resolve(projectRoot, 'node_modules/.bin/tsx'),
22
32
  resolve(pkgRoot, 'node_modules/.bin/tsx'),
@@ -29,7 +39,7 @@ if (!tsx) {
29
39
  }
30
40
 
31
41
  try {
32
- execFileSync(tsx, [entry, ...process.argv.slice(2)], { stdio: 'inherit' })
42
+ execFileSync(tsx, [entry, ...process.argv.slice(2)], { stdio: 'inherit', env: childEnv })
33
43
  } catch (e) {
34
44
  process.exit(e.status ?? 1)
35
45
  }
@@ -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;AAgOxC,wBAAgB,oBAAoB,CAAC,OAAO,EAAE,OAAO,QAkBpD"}
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;AA2BH;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAiCG;AACH,eAAO,MAAM,OAAO,iFAIlB,CAAA;AAGF;;;;;;;;;;;;GAYG;AACH,wBAAgB,SAAS,CAAC,GAAG,EAAE,MAAM,mFAWpC;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"}
1
+ {"version":3,"file":"db.d.ts","sourceRoot":"","sources":["../../../.framework/functions/_shared/db.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AA0BH;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAiCG;AACH,eAAO,MAAM,OAAO,iFAIlB,CAAA;AAGF;;;;;;;;;;;;GAYG;AACH,wBAAgB,SAAS,CAAC,GAAG,EAAE,MAAM,mFAWpC;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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "spine-framework",
3
- "version": "0.1.6",
3
+ "version": "0.1.9",
4
4
  "private": false,
5
5
  "description": "Spine — enterprise application framework built on Supabase + Netlify + React",
6
6
  "type": "module",