spine-framework 0.3.46 → 0.3.48

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.
@@ -90,10 +90,39 @@ async function migrateCommand(options: MigrateOptions): Promise<void> {
90
90
  process.exit(1)
91
91
  }
92
92
 
93
+ // Create migration tracking table if it doesn't exist
94
+ try {
95
+ await client.query(`
96
+ CREATE TABLE IF NOT EXISTS _spine_migrations (
97
+ id SERIAL PRIMARY KEY,
98
+ filename TEXT UNIQUE NOT NULL,
99
+ applied_at TIMESTAMPTZ DEFAULT NOW()
100
+ )
101
+ `)
102
+ } catch {
103
+ // Non-fatal: proceed without tracking
104
+ }
105
+
106
+ // Load already-applied migrations
107
+ let appliedMigrations = new Set<string>()
108
+ try {
109
+ const { rows } = await client.query('SELECT filename FROM _spine_migrations')
110
+ appliedMigrations = new Set(rows.map((r: { filename: string }) => r.filename))
111
+ } catch {
112
+ // Non-fatal: proceed without tracking
113
+ }
114
+
93
115
  let applied = 0
116
+ let skipped = 0
94
117
  let failed = 0
95
118
 
96
119
  for (const { name, path } of migrationFiles) {
120
+ if (appliedMigrations.has(name)) {
121
+ console.log(` Skipping ${name} (already applied)`)
122
+ skipped++
123
+ continue
124
+ }
125
+
97
126
  const sql = readFileSync(path, 'utf8')
98
127
  process.stdout.write(` Applying ${name}... `)
99
128
 
@@ -103,6 +132,11 @@ async function migrateCommand(options: MigrateOptions): Promise<void> {
103
132
  for (const stmt of statements) {
104
133
  await client.query(stmt)
105
134
  }
135
+ // Record as applied
136
+ await client.query(
137
+ `INSERT INTO _spine_migrations (filename) VALUES ($1) ON CONFLICT (filename) DO NOTHING`,
138
+ [name]
139
+ )
106
140
  console.log('✓')
107
141
  applied++
108
142
  } catch (err: any) {
@@ -114,7 +148,7 @@ async function migrateCommand(options: MigrateOptions): Promise<void> {
114
148
 
115
149
  await client.end()
116
150
 
117
- console.log(`\n ${applied} applied, ${failed} failed`)
151
+ console.log(`\n ${applied} applied, ${skipped} skipped, ${failed} failed`)
118
152
 
119
153
  if (failed > 0) {
120
154
  console.error('\nSome migrations failed. Check errors above.')
@@ -41,7 +41,7 @@ BEGIN
41
41
  -- Look up internal person ID from auth_uid
42
42
  SELECT p.id INTO v_person_id
43
43
  FROM public.people p
44
- WHERE p.auth_uid = v_auth_id::text AND p.is_active = true
44
+ WHERE p.auth_uid = v_auth_id AND p.is_active = true
45
45
  LIMIT 1;
46
46
 
47
47
  RETURN v_person_id;
@@ -0,0 +1,21 @@
1
+ -- Patch: fix uuid = text operator error in current_actor_id()
2
+ -- The previous version cast v_auth_id to text before comparing with auth_uid (uuid),
3
+ -- which causes PostgreSQL error 42883. This re-creates the function with matching types.
4
+
5
+ CREATE OR REPLACE FUNCTION public.current_actor_id()
6
+ RETURNS uuid AS $$
7
+ DECLARE
8
+ v_auth_id UUID;
9
+ v_person_id UUID;
10
+ BEGIN
11
+ v_auth_id := auth.uid();
12
+
13
+ -- Look up internal person ID from auth_uid
14
+ SELECT p.id INTO v_person_id
15
+ FROM public.people p
16
+ WHERE p.auth_uid = v_auth_id AND p.is_active = true
17
+ LIMIT 1;
18
+
19
+ RETURN v_person_id;
20
+ END;
21
+ $$ LANGUAGE plpgsql SECURITY DEFINER STABLE;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "spine-framework",
3
- "version": "0.3.46",
3
+ "version": "0.3.48",
4
4
  "description": "Multi-tenant, modular application platform for modern SaaS systems",
5
5
  "type": "module",
6
6
  "bin": {
@@ -20,6 +20,7 @@
20
20
  ".framework/migrations/003_system_data.sql",
21
21
  ".framework/migrations/004_enhancements.sql",
22
22
  ".framework/migrations/005_auth_user_trigger.sql",
23
+ ".framework/migrations/006_fix_current_actor_id.sql",
23
24
  ".framework/public/",
24
25
  ".framework/scripts/",
25
26
  ".framework/seeds/",