@soulbatical/tetra-dev-toolkit 1.17.3 → 1.17.4

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.
@@ -194,15 +194,30 @@ function parseMigrations(projectRoot) {
194
194
  || content.match(/(?:TEXT\[\]|text\[\])\s*:=\s*ARRAY\s*\[\s*'([^[\]]+)'\s*\]/i)
195
195
  if (arrayMatch) {
196
196
  const loopTables = arrayMatch[1].split(/'\s*,\s*'/).map(t => t.trim())
197
- const execLines = [...content.matchAll(/EXECUTE\s+format\s*\(\s*'(CREATE\s+POLICY\s+.*?)'\s*,/gi)]
197
+ // Match EXECUTE format('CREATE POLICY ...', ...) — multi-line, with escaped quotes ('')
198
+ // PL/pgSQL escapes single quotes as '' inside strings, so we must allow '' within the match
199
+ // The format string ends with a single ' (not '') followed by , or ;
200
+ const execLines = [...content.matchAll(/EXECUTE\s+format\s*\(\s*'(CREATE\s+POLICY(?:[^']|'')*?)'\s*,/gi)]
198
201
  for (const exec of execLines) {
199
- const stmt = exec[1]
202
+ // Unescape PL/pgSQL doubled quotes back to single quotes for analysis
203
+ const stmt = exec[1].replace(/''/g, "'")
200
204
  const forOp = stmt.match(/FOR\s+(SELECT|INSERT|UPDATE|DELETE|ALL)/i)
201
205
  const operation = forOp ? forOp[1].toUpperCase() : 'ALL'
202
206
  const hasUsing = /\bUSING\b/i.test(stmt)
203
207
  const hasWithCheck = /WITH\s+CHECK/i.test(stmt)
204
- const condMatch = stmt.match(/(?:USING|WITH\s+CHECK)\s*\(\s*(.*?)\s*\)/i)
205
- const condition = condMatch ? condMatch[1] : ''
208
+
209
+ // Extract the full USING/WITH CHECK clause (may be multi-line with nested parens)
210
+ let usingCondition = ''
211
+ let withCheckCondition = ''
212
+ if (hasUsing) {
213
+ const uMatch = stmt.match(/USING\s*\(\s*([\s\S]*?)\s*\)\s*(?:WITH\s+CHECK|$)/i)
214
+ || stmt.match(/USING\s*\(\s*([\s\S]*?)\s*\)\s*$/i)
215
+ usingCondition = uMatch ? uMatch[1].trim() : ''
216
+ }
217
+ if (hasWithCheck) {
218
+ const wcMatch = stmt.match(/WITH\s+CHECK\s*\(\s*([\s\S]*?)\s*\)\s*$/i)
219
+ withCheckCondition = wcMatch ? wcMatch[1].trim() : ''
220
+ }
206
221
 
207
222
  for (const table of loopTables) {
208
223
  if (!tables.has(table)) tables.set(table, { rlsEnabled: false, policies: [], rpcFunctions: new Map() })
@@ -211,8 +226,8 @@ function parseMigrations(projectRoot) {
211
226
  tables.get(table).policies.push({
212
227
  name: policyName,
213
228
  operation,
214
- using: hasUsing ? condition : '',
215
- withCheck: hasWithCheck ? condition : '',
229
+ using: usingCondition,
230
+ withCheck: withCheckCondition,
216
231
  file: relFile
217
232
  })
218
233
  }
@@ -63,6 +63,9 @@ const ALLOWED_FILE_PATTERNS = [
63
63
  /BaseCronService/,
64
64
  // Internal service-to-service routes (API key auth, no user JWT)
65
65
  /internalRoutes/,
66
+ // Billing routers — hybrid files with both authenticated admin routes and unauthenticated webhook handlers
67
+ // systemDB is needed for Tetra BillingService config callbacks (getSystemDB, getWebhookDB)
68
+ /billingRouter/,
66
69
  ]
67
70
 
68
71
  /**
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@soulbatical/tetra-dev-toolkit",
3
- "version": "1.17.3",
3
+ "version": "1.17.4",
4
4
  "publishConfig": {
5
5
  "access": "restricted"
6
6
  },
@@ -31,7 +31,8 @@
31
31
  "tetra-dev-token": "./bin/tetra-dev-token.js",
32
32
  "tetra-check-rls": "./bin/tetra-check-rls.js",
33
33
  "tetra-migration-lint": "./bin/tetra-migration-lint.js",
34
- "tetra-db-push": "./bin/tetra-db-push.js"
34
+ "tetra-db-push": "./bin/tetra-db-push.js",
35
+ "tetra-check-peers": "./bin/tetra-check-peers.js"
35
36
  },
36
37
  "files": [
37
38
  "bin/",