@percher/core 0.4.0 → 0.4.1

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.
Files changed (245) hide show
  1. package/dist/commands/account.d.ts +24 -14
  2. package/dist/commands/account.d.ts.map +1 -1
  3. package/dist/commands/account.js +17 -4
  4. package/dist/commands/account.js.map +1 -1
  5. package/dist/commands/admin-reconcile-routes.d.ts +18 -0
  6. package/dist/commands/admin-reconcile-routes.d.ts.map +1 -0
  7. package/dist/commands/admin-reconcile-routes.js +22 -0
  8. package/dist/commands/admin-reconcile-routes.js.map +1 -0
  9. package/dist/commands/ai-files.d.ts +5 -17
  10. package/dist/commands/ai-files.d.ts.map +1 -1
  11. package/dist/commands/ai-files.js +3 -4
  12. package/dist/commands/ai-files.js.map +1 -1
  13. package/dist/commands/alerts.d.ts +69 -0
  14. package/dist/commands/alerts.d.ts.map +1 -0
  15. package/dist/commands/alerts.js +80 -0
  16. package/dist/commands/alerts.js.map +1 -0
  17. package/dist/commands/app-resources.d.ts +30 -0
  18. package/dist/commands/app-resources.d.ts.map +1 -0
  19. package/dist/commands/app-resources.js +34 -0
  20. package/dist/commands/app-resources.js.map +1 -0
  21. package/dist/commands/app-topology.d.ts +18 -0
  22. package/dist/commands/app-topology.d.ts.map +1 -0
  23. package/dist/commands/app-topology.js +25 -0
  24. package/dist/commands/app-topology.js.map +1 -0
  25. package/dist/commands/billing.d.ts +8 -8
  26. package/dist/commands/billing.d.ts.map +1 -1
  27. package/dist/commands/billing.js +1 -1
  28. package/dist/commands/billing.js.map +1 -1
  29. package/dist/commands/continue.d.ts +1 -1
  30. package/dist/commands/create.d.ts +2 -12
  31. package/dist/commands/create.d.ts.map +1 -1
  32. package/dist/commands/create.js +1 -1
  33. package/dist/commands/create.js.map +1 -1
  34. package/dist/commands/dashboard.d.ts +2 -8
  35. package/dist/commands/dashboard.d.ts.map +1 -1
  36. package/dist/commands/dashboard.js +1 -1
  37. package/dist/commands/dashboard.js.map +1 -1
  38. package/dist/commands/data-export.d.ts +2 -8
  39. package/dist/commands/data-export.d.ts.map +1 -1
  40. package/dist/commands/data-export.js +1 -1
  41. package/dist/commands/data-export.js.map +1 -1
  42. package/dist/commands/data.d.ts +2 -8
  43. package/dist/commands/data.d.ts.map +1 -1
  44. package/dist/commands/data.js +1 -1
  45. package/dist/commands/data.js.map +1 -1
  46. package/dist/commands/delete.d.ts +2 -8
  47. package/dist/commands/delete.d.ts.map +1 -1
  48. package/dist/commands/delete.js +1 -1
  49. package/dist/commands/delete.js.map +1 -1
  50. package/dist/commands/deploys.d.ts +4 -28
  51. package/dist/commands/deploys.d.ts.map +1 -1
  52. package/dist/commands/deploys.js +1 -1
  53. package/dist/commands/deploys.js.map +1 -1
  54. package/dist/commands/dev.d.ts +2 -6
  55. package/dist/commands/dev.d.ts.map +1 -1
  56. package/dist/commands/dev.js +1 -1
  57. package/dist/commands/dev.js.map +1 -1
  58. package/dist/commands/diagnose.d.ts +2 -22
  59. package/dist/commands/diagnose.d.ts.map +1 -1
  60. package/dist/commands/diagnose.js +1 -1
  61. package/dist/commands/diagnose.js.map +1 -1
  62. package/dist/commands/doctor.d.ts +10 -35
  63. package/dist/commands/doctor.d.ts.map +1 -1
  64. package/dist/commands/doctor.js +12 -4
  65. package/dist/commands/doctor.js.map +1 -1
  66. package/dist/commands/domains.d.ts +5 -27
  67. package/dist/commands/domains.d.ts.map +1 -1
  68. package/dist/commands/domains.js +1 -1
  69. package/dist/commands/domains.js.map +1 -1
  70. package/dist/commands/env-scan.js +1 -1
  71. package/dist/commands/env-scan.js.map +1 -1
  72. package/dist/commands/env.d.ts +4 -20
  73. package/dist/commands/env.d.ts.map +1 -1
  74. package/dist/commands/env.js +1 -1
  75. package/dist/commands/env.js.map +1 -1
  76. package/dist/commands/export.d.ts +1 -1
  77. package/dist/commands/forgejo.d.ts +45 -0
  78. package/dist/commands/forgejo.d.ts.map +1 -0
  79. package/dist/commands/forgejo.js +125 -0
  80. package/dist/commands/forgejo.js.map +1 -0
  81. package/dist/commands/generate.d.ts +2 -6
  82. package/dist/commands/generate.d.ts.map +1 -1
  83. package/dist/commands/generate.js +1 -1
  84. package/dist/commands/generate.js.map +1 -1
  85. package/dist/commands/github.d.ts +4 -15
  86. package/dist/commands/github.d.ts.map +1 -1
  87. package/dist/commands/github.js +17 -1
  88. package/dist/commands/github.js.map +1 -1
  89. package/dist/commands/import-project.d.ts +13 -9
  90. package/dist/commands/import-project.d.ts.map +1 -1
  91. package/dist/commands/import-project.js +73 -22
  92. package/dist/commands/import-project.js.map +1 -1
  93. package/dist/commands/init.d.ts +26 -11
  94. package/dist/commands/init.d.ts.map +1 -1
  95. package/dist/commands/init.js +103 -2
  96. package/dist/commands/init.js.map +1 -1
  97. package/dist/commands/insights.d.ts +2 -6
  98. package/dist/commands/insights.d.ts.map +1 -1
  99. package/dist/commands/insights.js +1 -1
  100. package/dist/commands/insights.js.map +1 -1
  101. package/dist/commands/login.d.ts +2 -8
  102. package/dist/commands/login.d.ts.map +1 -1
  103. package/dist/commands/login.js +22 -1
  104. package/dist/commands/login.js.map +1 -1
  105. package/dist/commands/logs.d.ts +25 -10
  106. package/dist/commands/logs.d.ts.map +1 -1
  107. package/dist/commands/logs.js +65 -5
  108. package/dist/commands/logs.js.map +1 -1
  109. package/dist/commands/mcp.d.ts +2 -2
  110. package/dist/commands/mcp.d.ts.map +1 -1
  111. package/dist/commands/mcp.js +1 -1
  112. package/dist/commands/mcp.js.map +1 -1
  113. package/dist/commands/migrate-supabase-map.d.ts +171 -0
  114. package/dist/commands/migrate-supabase-map.d.ts.map +1 -0
  115. package/dist/commands/migrate-supabase-map.js +452 -0
  116. package/dist/commands/migrate-supabase-map.js.map +1 -0
  117. package/dist/commands/migrate-supabase-schema.d.ts +67 -0
  118. package/dist/commands/migrate-supabase-schema.d.ts.map +1 -0
  119. package/dist/commands/migrate-supabase-schema.js +321 -0
  120. package/dist/commands/migrate-supabase-schema.js.map +1 -0
  121. package/dist/commands/migrate-supabase-scripts.d.ts +64 -0
  122. package/dist/commands/migrate-supabase-scripts.d.ts.map +1 -0
  123. package/dist/commands/migrate-supabase-scripts.js +564 -0
  124. package/dist/commands/migrate-supabase-scripts.js.map +1 -0
  125. package/dist/commands/migrate-supabase-sdk.d.ts +133 -0
  126. package/dist/commands/migrate-supabase-sdk.d.ts.map +1 -0
  127. package/dist/commands/migrate-supabase-sdk.js +1119 -0
  128. package/dist/commands/migrate-supabase-sdk.js.map +1 -0
  129. package/dist/commands/migrate-supabase-walker.d.ts +93 -0
  130. package/dist/commands/migrate-supabase-walker.d.ts.map +1 -0
  131. package/dist/commands/migrate-supabase-walker.js +413 -0
  132. package/dist/commands/migrate-supabase-walker.js.map +1 -0
  133. package/dist/commands/migrate-supabase.d.ts +81 -0
  134. package/dist/commands/migrate-supabase.d.ts.map +1 -0
  135. package/dist/commands/migrate-supabase.js +579 -0
  136. package/dist/commands/migrate-supabase.js.map +1 -0
  137. package/dist/commands/open.d.ts +2 -6
  138. package/dist/commands/open.d.ts.map +1 -1
  139. package/dist/commands/open.js +1 -1
  140. package/dist/commands/open.js.map +1 -1
  141. package/dist/commands/publish-api-error.d.ts +46 -0
  142. package/dist/commands/publish-api-error.d.ts.map +1 -0
  143. package/dist/commands/publish-api-error.js +307 -0
  144. package/dist/commands/publish-api-error.js.map +1 -0
  145. package/dist/commands/publish.d.ts +40 -17
  146. package/dist/commands/publish.d.ts.map +1 -1
  147. package/dist/commands/publish.js +115 -8
  148. package/dist/commands/publish.js.map +1 -1
  149. package/dist/commands/push.d.ts +2 -12
  150. package/dist/commands/push.d.ts.map +1 -1
  151. package/dist/commands/push.js +2 -2
  152. package/dist/commands/push.js.map +1 -1
  153. package/dist/commands/redeploy.d.ts +2 -8
  154. package/dist/commands/redeploy.d.ts.map +1 -1
  155. package/dist/commands/redeploy.js +2 -2
  156. package/dist/commands/redeploy.js.map +1 -1
  157. package/dist/commands/rename.d.ts +2 -8
  158. package/dist/commands/rename.d.ts.map +1 -1
  159. package/dist/commands/rename.js +1 -1
  160. package/dist/commands/rename.js.map +1 -1
  161. package/dist/commands/reproduce.d.ts +2 -8
  162. package/dist/commands/reproduce.d.ts.map +1 -1
  163. package/dist/commands/reproduce.js +1 -1
  164. package/dist/commands/reproduce.js.map +1 -1
  165. package/dist/commands/reset-superuser.d.ts +2 -16
  166. package/dist/commands/reset-superuser.d.ts.map +1 -1
  167. package/dist/commands/reset-superuser.js +1 -1
  168. package/dist/commands/reset-superuser.js.map +1 -1
  169. package/dist/commands/restore.d.ts +7 -22
  170. package/dist/commands/restore.d.ts.map +1 -1
  171. package/dist/commands/restore.js +1 -1
  172. package/dist/commands/restore.js.map +1 -1
  173. package/dist/commands/resume.d.ts +2 -6
  174. package/dist/commands/resume.d.ts.map +1 -1
  175. package/dist/commands/resume.js +1 -1
  176. package/dist/commands/resume.js.map +1 -1
  177. package/dist/commands/rollback.d.ts +2 -8
  178. package/dist/commands/rollback.d.ts.map +1 -1
  179. package/dist/commands/rollback.js +1 -1
  180. package/dist/commands/rollback.js.map +1 -1
  181. package/dist/commands/sharing.d.ts +48 -0
  182. package/dist/commands/sharing.d.ts.map +1 -0
  183. package/dist/commands/sharing.js +85 -0
  184. package/dist/commands/sharing.js.map +1 -0
  185. package/dist/commands/status.d.ts +2 -6
  186. package/dist/commands/status.d.ts.map +1 -1
  187. package/dist/commands/status.js +1 -1
  188. package/dist/commands/status.js.map +1 -1
  189. package/dist/commands/transfers.d.ts +34 -0
  190. package/dist/commands/transfers.d.ts.map +1 -0
  191. package/dist/commands/transfers.js +62 -0
  192. package/dist/commands/transfers.js.map +1 -0
  193. package/dist/commands/unsuspend.d.ts +2 -6
  194. package/dist/commands/unsuspend.d.ts.map +1 -1
  195. package/dist/commands/unsuspend.js +1 -1
  196. package/dist/commands/unsuspend.js.map +1 -1
  197. package/dist/commands/versions.d.ts +2 -6
  198. package/dist/commands/versions.d.ts.map +1 -1
  199. package/dist/commands/versions.js +1 -1
  200. package/dist/commands/versions.js.map +1 -1
  201. package/dist/commands/wait-deploy.d.ts +2 -12
  202. package/dist/commands/wait-deploy.d.ts.map +1 -1
  203. package/dist/commands/wait-deploy.js +1 -1
  204. package/dist/commands/wait-deploy.js.map +1 -1
  205. package/dist/context.d.ts +15 -0
  206. package/dist/context.d.ts.map +1 -1
  207. package/dist/detect.d.ts +11 -0
  208. package/dist/detect.d.ts.map +1 -1
  209. package/dist/detect.js +31 -8
  210. package/dist/detect.js.map +1 -1
  211. package/dist/env-scan-source.js +1 -1
  212. package/dist/env-scan-source.js.map +1 -1
  213. package/dist/error-classifier.d.ts +17 -0
  214. package/dist/error-classifier.d.ts.map +1 -1
  215. package/dist/error-classifier.js +94 -8
  216. package/dist/error-classifier.js.map +1 -1
  217. package/dist/errors.d.ts +1 -1
  218. package/dist/errors.d.ts.map +1 -1
  219. package/dist/errors.js.map +1 -1
  220. package/dist/index.d.ts +63 -49
  221. package/dist/index.d.ts.map +1 -1
  222. package/dist/index.js +56 -42
  223. package/dist/index.js.map +1 -1
  224. package/dist/plans.d.ts +61 -5
  225. package/dist/plans.d.ts.map +1 -1
  226. package/dist/plans.js +78 -18
  227. package/dist/plans.js.map +1 -1
  228. package/dist/recovery.d.ts +60 -3
  229. package/dist/recovery.d.ts.map +1 -1
  230. package/dist/recovery.js +22 -0
  231. package/dist/recovery.js.map +1 -1
  232. package/dist/static-docker.d.ts +77 -0
  233. package/dist/static-docker.d.ts.map +1 -0
  234. package/dist/static-docker.js +105 -0
  235. package/dist/static-docker.js.map +1 -0
  236. package/dist/tarball.js +1 -1
  237. package/dist/tarball.js.map +1 -1
  238. package/dist/templates/ai-files/cursor-percher-mdc.d.ts.map +1 -1
  239. package/dist/templates/ai-files/cursor-percher-mdc.js +12 -9
  240. package/dist/templates/ai-files/cursor-percher-mdc.js.map +1 -1
  241. package/dist/templates.js +11 -11
  242. package/dist/templates.js.map +1 -1
  243. package/dist/watcher.js +1 -1
  244. package/dist/watcher.js.map +1 -1
  245. package/package.json +6 -2
@@ -0,0 +1,452 @@
1
+ /**
2
+ * Map a Supabase introspection result to a PocketBase migration preview.
3
+ * Pure (no I/O). Safe to call repeatedly.
4
+ *
5
+ * The function never throws on a malformed input — every "I don't
6
+ * know how to map this" case becomes a `MigrationUnsupported` entry
7
+ * so the user gets the full picture in one pass rather than the
8
+ * mapper bailing out on the first weird column.
9
+ */
10
+ export function mapSupabaseToPocketBase(introspection, options = {}) {
11
+ const generatedAt = (options.now?.() ?? new Date()).toISOString();
12
+ const collections = [];
13
+ const rlsPolicies = [];
14
+ const unsupported = [];
15
+ // Map each introspected table → a PocketBase collection. The
16
+ // mapping is per-table local; cross-table state (FK resolution) is
17
+ // deferred to the user-supplied `collectionName` lookup which uses
18
+ // the SAME collection-name convention we apply here.
19
+ for (const table of introspection.tables) {
20
+ const collection = mapTable(table, introspection.tables, unsupported);
21
+ collections.push(collection);
22
+ for (const policy of table.rlsPolicies) {
23
+ rlsPolicies.push(mapRlsPolicy(table, policy));
24
+ }
25
+ }
26
+ const authMigration = introspection.authUsersCount !== null && introspection.authUsersCount > 0
27
+ ? {
28
+ userCount: introspection.authUsersCount,
29
+ note: "Supabase bcrypt hashes use a different cost parameter than PocketBase. Users will not be able to sign in with their existing passwords — send a password-reset email after the migration.",
30
+ }
31
+ : null;
32
+ if (authMigration) {
33
+ unsupported.push({
34
+ kind: "auth_user_passwords",
35
+ source: "auth.users",
36
+ reason: `${authMigration.userCount} auth user${authMigration.userCount === 1 ? "" : "s"} cannot keep their existing passwords.`,
37
+ suggestion: authMigration.note,
38
+ });
39
+ }
40
+ const storageMigration = introspection.storageBuckets.length > 0
41
+ ? {
42
+ buckets: introspection.storageBuckets.map((b) => b.name),
43
+ note: "Storage bucket files do not migrate automatically — Phase C will generate a separate `pb_migrate_storage.js` script that downloads and re-uploads each file via PocketBase's admin SDK.",
44
+ }
45
+ : null;
46
+ if (storageMigration) {
47
+ unsupported.push({
48
+ kind: "storage_bucket_files",
49
+ source: `storage.buckets (${storageMigration.buckets.join(", ")})`,
50
+ reason: "Bucket files are not part of the Postgres schema and need a separate import pass.",
51
+ suggestion: storageMigration.note,
52
+ });
53
+ }
54
+ const warnings = collectWarnings(collections, rlsPolicies, unsupported);
55
+ const fieldCount = collections.reduce((acc, c) => acc + c.schema.length, 0);
56
+ const relationFieldCount = collections.reduce((acc, c) => acc + c.schema.filter((f) => f.type === "relation").length, 0);
57
+ const manualRlsPolicyCount = rlsPolicies.filter((p) => p.manual).length;
58
+ return {
59
+ sourceProjectRef: introspection.projectRef,
60
+ generatedAt,
61
+ collections,
62
+ migrationNotes: {
63
+ rlsPolicies,
64
+ unsupported,
65
+ authMigration,
66
+ storageMigration,
67
+ },
68
+ warnings,
69
+ summary: {
70
+ collectionCount: collections.length,
71
+ fieldCount,
72
+ relationFieldCount,
73
+ unsupportedCount: unsupported.length,
74
+ rlsPolicyCount: rlsPolicies.length,
75
+ manualRlsPolicyCount,
76
+ },
77
+ };
78
+ }
79
+ function mapTable(table, allTables, unsupported) {
80
+ const collectionName = pbCollectionName(table);
81
+ const fqTable = `${table.schema}.${table.name}`;
82
+ const primaryKeys = table.columns.filter((c) => c.isPrimaryKey);
83
+ if (primaryKeys.length === 0) {
84
+ unsupported.push({
85
+ kind: "no_primary_key",
86
+ source: fqTable,
87
+ reason: "PocketBase requires every record to have an `id`. The source table has no primary key.",
88
+ suggestion: "PocketBase will auto-generate a 15-char id per row. Existing references from other tables (if any) will need manual remapping after import.",
89
+ });
90
+ }
91
+ else if (primaryKeys.length > 1) {
92
+ unsupported.push({
93
+ kind: "composite_primary_key",
94
+ source: fqTable,
95
+ reason: `PocketBase only supports a single \`id\` primary key. The source has a composite key over (${primaryKeys.map((c) => c.name).join(", ")}).`,
96
+ suggestion: "Pick one column as the PB id (PB ids are strings; uuid works directly) and keep the others as regular fields. Add a unique index over the original tuple if cross-row uniqueness still matters.",
97
+ });
98
+ }
99
+ const schema = [];
100
+ const droppedSourceColumns = [];
101
+ let sourcePrimaryKey = null;
102
+ for (const col of table.columns) {
103
+ // Drop EVERY single-column primary key from the PB schema —
104
+ // uuid, integer, text, citext, whatever. Three reasons:
105
+ //
106
+ // 1. PocketBase has a built-in `id` field. A user-defined
107
+ // column named `id` would collide; a non-`id`-named PK
108
+ // that we kept as a field would leave PB without a way
109
+ // to resolve foreign-key relations against it.
110
+ // 2. The import script (Phase C) derives a deterministic
111
+ // 15-char PB id from row[<sourcePrimaryKey>] via sha256.
112
+ // That id becomes the PB record's id — within PB's
113
+ // documented id shape AND stable across re-runs.
114
+ // 3. The same id-map is consulted when dependent tables'
115
+ // FK columns get rewritten before insert. Without it, an
116
+ // integer-PK source (`users.id` int → `posts.user_id`
117
+ // int) would have no map to look up against, and the FK
118
+ // rewrite would throw at import time.
119
+ //
120
+ // Multi-column PKs are flagged separately above and we emit
121
+ // each part as a regular field so the user can still see the
122
+ // data in the preview.
123
+ //
124
+ // Codex P1 review 2026-05-17 (round 3): the previous version
125
+ // gated this on `isUuidLike(...)`, leaving integer-PK
126
+ // relation targets without an id-map and forcing every
127
+ // dependent table's import to throw. Universal handling
128
+ // closes the gap.
129
+ if (col.isPrimaryKey && primaryKeys.length === 1) {
130
+ droppedSourceColumns.push(col.name);
131
+ sourcePrimaryKey = col.name;
132
+ continue;
133
+ }
134
+ // Skip PB built-in timestamp columns when they match Postgres
135
+ // conventions exactly. PB writes `created`/`updated` itself; if
136
+ // we re-emit them as user fields, PB rejects the collection
137
+ // (name collision with built-ins). Per the plan, the import path
138
+ // will overwrite incoming `created`/`updated` with PB's own
139
+ // values — that's the desired outcome for fresh records.
140
+ if ((col.name === "created_at" || col.name === "updated_at") && isDateLike(col.postgresType)) {
141
+ droppedSourceColumns.push(col.name);
142
+ continue;
143
+ }
144
+ const field = mapColumn(col, table, allTables, unsupported);
145
+ schema.push(field);
146
+ }
147
+ return {
148
+ name: collectionName,
149
+ type: "base",
150
+ sourceTable: fqTable,
151
+ schema,
152
+ droppedSourceColumns,
153
+ sourcePrimaryKey,
154
+ listRule: null,
155
+ viewRule: null,
156
+ createRule: null,
157
+ updateRule: null,
158
+ deleteRule: null,
159
+ indexes: [],
160
+ };
161
+ }
162
+ function mapColumn(col, ownerTable, allTables, unsupported) {
163
+ const fqColumn = `${ownerTable.schema}.${ownerTable.name}.${col.name}`;
164
+ // Foreign keys take precedence over the type mapping — even when the
165
+ // underlying column is a uuid we want it as a `relation`, not a `text`.
166
+ if (col.foreignKey) {
167
+ // Detect self-referential FKs (PB supports them but cascade semantics
168
+ // differ); flag for review but still emit the relation.
169
+ if (col.foreignKey.table === ownerTable.name) {
170
+ unsupported.push({
171
+ kind: "self_referential_fk",
172
+ source: fqColumn,
173
+ reason: "Self-referential foreign key — PocketBase supports this but cascade-delete semantics differ from Postgres.",
174
+ suggestion: "Verify cascade behavior after import: PB defaults to no cascade unless `cascadeDelete: true` is set explicitly.",
175
+ });
176
+ }
177
+ // Detect auth.users references — these need to land on PB's
178
+ // built-in `users` collection, NOT a generated one.
179
+ const isAuthUsersRef = col.foreignKey.table === "users" &&
180
+ // We don't see the FK's schema in Phase A introspection — only
181
+ // the table name. The common Supabase pattern is FK → auth.users
182
+ // exposed as `references auth.users(id)`. If no user-schema
183
+ // `users` table exists, treat it as the auth ref.
184
+ !allTables.some((t) => t.name === "users" && t.schema === "public");
185
+ const targetCollection = isAuthUsersRef
186
+ ? "users"
187
+ : pbCollectionNameFromRef(col.foreignKey.table, allTables);
188
+ if (isAuthUsersRef) {
189
+ unsupported.push({
190
+ kind: "auth_users_reference",
191
+ source: fqColumn,
192
+ reason: "Foreign key references Supabase's `auth.users` table; PocketBase has its own built-in `users` collection. The Phase C import script does NOT migrate auth users (Supabase bcrypt hashes are incompatible with PB's auth), so there's no id-map to translate this FK against.",
193
+ suggestion: "Phase C generates the field as nullable and the import script writes `null` for every row in this column. After wiring auth migration (separate manual step — Supabase users must re-authenticate against PB), build a `sourceSupabaseUserId → pbUserId` map and back-fill this field with a one-off SQL/admin script.",
194
+ });
195
+ }
196
+ return {
197
+ name: col.name,
198
+ type: "relation",
199
+ // Auth-user references MUST be nullable in PB regardless of
200
+ // the source's nullability — the import script writes null
201
+ // for every row in this column (PB would reject inserts
202
+ // pointing at a non-existent record in the built-in `users`
203
+ // collection). Codex P1 round 3 finding (2026-05-17).
204
+ required: isAuthUsersRef ? false : !col.isNullable,
205
+ unique: false,
206
+ options: {
207
+ collectionName: targetCollection,
208
+ cascadeDelete: false,
209
+ maxSelect: 1,
210
+ },
211
+ source: {
212
+ postgresType: col.postgresType,
213
+ sourceColumn: col.name,
214
+ flag: isAuthUsersRef ? "auth_users_reference" : undefined,
215
+ },
216
+ };
217
+ }
218
+ // Defensive: treat both formatted (`text[]`) and bare (`ARRAY`)
219
+ // shapes as arrays. Phase A's SQL collapses to the formatted form
220
+ // but we don't want a silent regression if that ever drifts.
221
+ if (col.postgresType === "ARRAY" || col.postgresType.endsWith("[]")) {
222
+ unsupported.push({
223
+ kind: "array_column",
224
+ source: fqColumn,
225
+ reason: `Postgres array (${col.postgresType}) has no PocketBase equivalent.`,
226
+ suggestion: "Mapped to `json`. For arrays of scalars this works fine. For arrays of references, model the relationship as a join collection in PocketBase instead.",
227
+ });
228
+ return jsonField(col, "array_column");
229
+ }
230
+ if (col.postgresType === "USER-DEFINED") {
231
+ unsupported.push({
232
+ kind: "user_defined_type",
233
+ source: fqColumn,
234
+ reason: "Source column uses a user-defined type (likely a Postgres enum). The Phase A introspection does not capture enum values.",
235
+ suggestion: "Mapped to `select` with an empty `values` list — fill in the allowed values manually before importing this collection into PocketBase.",
236
+ });
237
+ return {
238
+ name: col.name,
239
+ type: "select",
240
+ required: !col.isNullable,
241
+ unique: false,
242
+ options: { values: [], maxSelect: 1 },
243
+ source: {
244
+ postgresType: col.postgresType,
245
+ sourceColumn: col.name,
246
+ flag: "user_defined_type",
247
+ },
248
+ };
249
+ }
250
+ const mapping = mapScalarType(col.postgresType);
251
+ if (mapping.kind === "unmapped") {
252
+ unsupported.push({
253
+ kind: "unmapped_type",
254
+ source: fqColumn,
255
+ reason: `Postgres type \`${col.postgresType}\` has no direct PocketBase mapping.`,
256
+ suggestion: "Mapped to `json` so the data isn't lost. Pick a closer PB type manually if you have one in mind.",
257
+ });
258
+ return jsonField(col, "unmapped_type");
259
+ }
260
+ return {
261
+ name: col.name,
262
+ type: mapping.pbType,
263
+ required: !col.isNullable,
264
+ unique: false,
265
+ options: mapping.options,
266
+ source: {
267
+ postgresType: col.postgresType,
268
+ sourceColumn: col.name,
269
+ },
270
+ };
271
+ }
272
+ function mapScalarType(postgresType) {
273
+ const lower = postgresType.toLowerCase().trim();
274
+ // text family
275
+ if (lower === "text" ||
276
+ lower === "character varying" ||
277
+ lower === "varchar" ||
278
+ lower === "character" ||
279
+ lower === "char" ||
280
+ lower === "name" ||
281
+ lower === "citext") {
282
+ return { kind: "mapped", pbType: "text", options: { min: null, max: null, pattern: "" } };
283
+ }
284
+ // uuid — when not a primary key, PocketBase stores it as a text field.
285
+ if (lower === "uuid") {
286
+ return { kind: "mapped", pbType: "text", options: { min: null, max: null, pattern: "" } };
287
+ }
288
+ // numeric family — PB doesn't distinguish int sizes.
289
+ if (lower === "integer" ||
290
+ lower === "int" ||
291
+ lower === "int2" ||
292
+ lower === "int4" ||
293
+ lower === "int8" ||
294
+ lower === "smallint" ||
295
+ lower === "bigint" ||
296
+ lower === "numeric" ||
297
+ lower === "decimal" ||
298
+ lower === "real" ||
299
+ lower === "double precision" ||
300
+ lower === "float4" ||
301
+ lower === "float8" ||
302
+ lower === "money") {
303
+ return { kind: "mapped", pbType: "number", options: {} };
304
+ }
305
+ // boolean
306
+ if (lower === "boolean" || lower === "bool") {
307
+ return { kind: "mapped", pbType: "bool", options: {} };
308
+ }
309
+ // date/time — PB stores everything as an ISO string in `date` fields.
310
+ if (lower === "timestamp" ||
311
+ lower === "timestamp without time zone" ||
312
+ lower === "timestamp with time zone" ||
313
+ lower === "timestamptz" ||
314
+ lower === "date" ||
315
+ lower === "time" ||
316
+ lower === "time without time zone" ||
317
+ lower === "time with time zone" ||
318
+ lower === "timetz") {
319
+ return { kind: "mapped", pbType: "date", options: {} };
320
+ }
321
+ // json
322
+ if (lower === "json" || lower === "jsonb") {
323
+ return { kind: "mapped", pbType: "json", options: {} };
324
+ }
325
+ // bytea → file. NOTE: bytea in Postgres holds bytes inline; PB's
326
+ // `file` field expects an actual file upload. The import script
327
+ // (Phase C) will need to write each row's bytes to a temp file
328
+ // and upload via the admin SDK. Flag this as soon as a column is
329
+ // seen — but still emit `file` so the collection shape is right.
330
+ if (lower === "bytea") {
331
+ return { kind: "mapped", pbType: "file", options: {} };
332
+ }
333
+ return { kind: "unmapped" };
334
+ }
335
+ function jsonField(col, flag) {
336
+ return {
337
+ name: col.name,
338
+ type: "json",
339
+ required: !col.isNullable,
340
+ unique: false,
341
+ options: {},
342
+ source: {
343
+ postgresType: col.postgresType,
344
+ sourceColumn: col.name,
345
+ flag,
346
+ },
347
+ };
348
+ }
349
+ function isDateLike(postgresType) {
350
+ const lower = postgresType.toLowerCase();
351
+ return lower.startsWith("timestamp") || lower === "date" || lower.startsWith("time");
352
+ }
353
+ function pbCollectionName(table) {
354
+ // PB collection names accept [a-zA-Z0-9_]. Public-schema tables
355
+ // get their bare name (the overwhelmingly common case). Tables in
356
+ // other user schemas get a "<schema>_<name>" prefix to avoid
357
+ // collisions; the user can rename in PB if they want a different
358
+ // convention.
359
+ if (table.schema === "public")
360
+ return sanitizeName(table.name);
361
+ return sanitizeName(`${table.schema}_${table.name}`);
362
+ }
363
+ function pbCollectionNameFromRef(refTableName, allTables) {
364
+ // FK target tables only carry their bare name in Phase A's
365
+ // introspection — no schema. Resolve by preferring a public-schema
366
+ // match first, then any other schema, then fall back to the bare
367
+ // name (with a warning logged elsewhere if the table isn't in the
368
+ // user schema list at all).
369
+ const publicHit = allTables.find((t) => t.name === refTableName && t.schema === "public");
370
+ if (publicHit)
371
+ return pbCollectionName(publicHit);
372
+ const anyHit = allTables.find((t) => t.name === refTableName);
373
+ if (anyHit)
374
+ return pbCollectionName(anyHit);
375
+ return sanitizeName(refTableName);
376
+ }
377
+ function sanitizeName(raw) {
378
+ return raw.replace(/[^a-zA-Z0-9_]/g, "_");
379
+ }
380
+ // ── RLS policy rewriting ──────────────────────────────────────────
381
+ /**
382
+ * Conservative auth.uid() rewriter — recognises only the canonical
383
+ * Supabase pattern `auth.uid() = <column>` (with optional whitespace
384
+ * and parentheses). Anything more complex (`AND`, `OR`, subqueries,
385
+ * function calls, type casts) bypasses the rewriter and lands as
386
+ * `manual: true` so the user must rewrite by hand.
387
+ *
388
+ * The regex is deliberately tight. PB API rules use a different
389
+ * mental model than SQL RLS; a wrong guess is worse than no guess
390
+ * because it'll look plausible until the user notices that
391
+ * `@request.auth.id` doesn't behave the way they expect.
392
+ */
393
+ const AUTH_UID_EQUALS_COLUMN = /^\s*\(?\s*auth\.uid\(\)\s*=\s*([a-zA-Z_][a-zA-Z0-9_]*)\s*\)?\s*$/;
394
+ const COLUMN_EQUALS_AUTH_UID = /^\s*\(?\s*([a-zA-Z_][a-zA-Z0-9_]*)\s*=\s*auth\.uid\(\)\s*\)?\s*$/;
395
+ function rewriteRlsExpression(expr) {
396
+ if (!expr)
397
+ return null;
398
+ const m1 = AUTH_UID_EQUALS_COLUMN.exec(expr);
399
+ if (m1)
400
+ return `@request.auth.id = ${m1[1]}`;
401
+ const m2 = COLUMN_EQUALS_AUTH_UID.exec(expr);
402
+ if (m2)
403
+ return `@request.auth.id = ${m2[1]}`;
404
+ return null;
405
+ }
406
+ function mapRlsPolicy(table, policy) {
407
+ const rewrittenUsing = rewriteRlsExpression(policy.usingExpr);
408
+ const rewrittenWithCheck = rewriteRlsExpression(policy.withCheckExpr);
409
+ // A policy is "auto-translatable" when EVERY non-null expression
410
+ // matched the narrow rewriter. If either expression was non-null
411
+ // and didn't match, we fall back to manual.
412
+ const usingOk = policy.usingExpr === null || rewrittenUsing !== null;
413
+ const withCheckOk = policy.withCheckExpr === null || rewrittenWithCheck !== null;
414
+ const auto = usingOk && withCheckOk;
415
+ let suggestedRule = null;
416
+ if (auto) {
417
+ // For SELECT/DELETE PB uses listRule/viewRule/deleteRule (USING).
418
+ // For INSERT PB uses createRule (WITH CHECK).
419
+ // For UPDATE both — combine with `&&` if both present.
420
+ if (rewrittenUsing && rewrittenWithCheck && rewrittenUsing !== rewrittenWithCheck) {
421
+ suggestedRule = `${rewrittenUsing} && ${rewrittenWithCheck}`;
422
+ }
423
+ else {
424
+ suggestedRule = rewrittenUsing ?? rewrittenWithCheck;
425
+ }
426
+ }
427
+ return {
428
+ table: `${table.schema}.${table.name}`,
429
+ policyName: policy.name,
430
+ command: policy.command,
431
+ originalUsing: policy.usingExpr,
432
+ originalWithCheck: policy.withCheckExpr,
433
+ suggestedRule,
434
+ manual: !auto,
435
+ };
436
+ }
437
+ function collectWarnings(collections, rlsPolicies, unsupported) {
438
+ const warnings = [];
439
+ for (const u of unsupported) {
440
+ warnings.push(`[${u.kind}] ${u.source}: ${u.reason}`);
441
+ }
442
+ const manualPolicies = rlsPolicies.filter((p) => p.manual);
443
+ if (manualPolicies.length > 0) {
444
+ warnings.push(`${manualPolicies.length} RLS polic${manualPolicies.length === 1 ? "y" : "ies"} could not be auto-translated to PocketBase API rules — see migrationNotes.rlsPolicies for manual rewrites.`);
445
+ }
446
+ const collectionCount = collections.length;
447
+ if (collectionCount === 0) {
448
+ warnings.push("No user-schema tables found to migrate.");
449
+ }
450
+ return warnings;
451
+ }
452
+ //# sourceMappingURL=migrate-supabase-map.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"migrate-supabase-map.js","sourceRoot":"","sources":["../../src/commands/migrate-supabase-map.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,67 @@
1
+ import { z } from "zod";
2
+ import type { Context } from "../context";
3
+ import { type AskUserRecovery, type NoneRecovery, type ToolRecovery } from "../recovery";
4
+ import { type InspectSupabaseError } from "./migrate-supabase";
5
+ import { type MigrationPreview } from "./migrate-supabase-map";
6
+ /**
7
+ * FUTURE9 Phase B chunk 2 — schema migration write step.
8
+ *
9
+ * Wires Phase A (`inspectSupabase`) + Phase B chunk 1
10
+ * (`mapSupabaseToPocketBase`) together and writes the preview files
11
+ * to a sibling directory the user can inspect before committing to
12
+ * the full migration (Phases C–D).
13
+ *
14
+ * Dry-run / apply contract (locked in STATUS_FUTURE9_phase-a.md):
15
+ * - Phase A (`inspectSupabase`) — strictly read-only, no writes.
16
+ * - Phase B (this command) — writes to ./migration-preview/ by
17
+ * default. The sibling dir IS the dry-run posture relative to
18
+ * a future `--apply` flag (Phase C/D) that will write to
19
+ * project root.
20
+ * - `outputDir` override exists for CI/tests/users who already
21
+ * have a `./migration-preview/` they care about.
22
+ *
23
+ * Token stays on the user's machine — same invariant as Phase A.
24
+ * The Supabase PAT is forwarded straight into `inspectSupabase`,
25
+ * which calls api.supabase.com directly; we never round-trip it
26
+ * through Percher's wire.
27
+ */
28
+ export declare const migrateSupabaseSchemaInputSchema: z.ZodObject<{
29
+ projectRef: z.ZodString;
30
+ token: z.ZodString;
31
+ outputDir: z.ZodOptional<z.ZodString>;
32
+ }, z.core.$strip>;
33
+ export type MigrateSupabaseSchemaInput = z.infer<typeof migrateSupabaseSchemaInputSchema>;
34
+ export interface MigrateSupabaseSchemaResult {
35
+ status: "ok" | "failed";
36
+ projectRef: string;
37
+ /** Absolute path of the directory the preview files were (or would be) written to. */
38
+ outputDir: string;
39
+ /** Relative paths (from ctx.cwd) of every file written. Empty on failure. */
40
+ filesWritten: string[];
41
+ /** The full preview structure — same shape Phase B chunk 1 emits. */
42
+ preview: MigrationPreview | null;
43
+ recovery: ToolRecovery | NoneRecovery | AskUserRecovery;
44
+ summary: string;
45
+ error?: InspectSupabaseError | MigrateSchemaError;
46
+ }
47
+ export interface MigrateSchemaError {
48
+ code: "write_failed";
49
+ title: string;
50
+ explanation: string;
51
+ suggestion: string;
52
+ }
53
+ export declare function migrateSupabaseSchema(ctx: Context, input: MigrateSupabaseSchemaInput): Promise<MigrateSupabaseSchemaResult>;
54
+ /**
55
+ * Markdown report the user reads before deciding to commit. Sections
56
+ * follow the example in the FUTURE9 plan (Steg 2):
57
+ * 1. Header (projectRef, when generated, totals)
58
+ * 2. Collections — one block per mapped table
59
+ * 3. RLS policies — Supabase original + suggested PB rule (or MANUAL)
60
+ * 4. Unsupported items — every thing the mapper refused to guess at
61
+ * 5. Auth / storage notes
62
+ *
63
+ * Stable wording — tests snapshot-compare. Don't reword on a whim;
64
+ * change the test if you do.
65
+ */
66
+ export declare function renderMigrationNotes(preview: MigrationPreview): string;
67
+ //# sourceMappingURL=migrate-supabase-schema.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"migrate-supabase-schema.d.ts","sourceRoot":"","sources":["../../src/commands/migrate-supabase-schema.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,YAAY,CAAC;AAC1C,OAAO,EACL,KAAK,eAAe,EACpB,KAAK,YAAY,EAGjB,KAAK,YAAY,EAClB,MAAM,aAAa,CAAC;AACrB,OAAO,EACL,KAAK,oBAAoB,EAG1B,MAAM,oBAAoB,CAAC;AAC5B,OAAO,EAAE,KAAK,gBAAgB,EAA2B,MAAM,wBAAwB,CAAC;AAGxF;;;;;;;;;;;;;;;;;;;;;GAqBG;AAEH,eAAO,MAAM,gCAAgC;;;;iBAmB3C,CAAC;AACH,MAAM,MAAM,0BAA0B,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,gCAAgC,CAAC,CAAC;AAE1F,MAAM,WAAW,2BAA2B;IAC1C,MAAM,EAAE,IAAI,GAAG,QAAQ,CAAC;IACxB,UAAU,EAAE,MAAM,CAAC;IACnB,sFAAsF;IACtF,SAAS,EAAE,MAAM,CAAC;IAClB,6EAA6E;IAC7E,YAAY,EAAE,MAAM,EAAE,CAAC;IACvB,qEAAqE;IACrE,OAAO,EAAE,gBAAgB,GAAG,IAAI,CAAC;IACjC,QAAQ,EAAE,YAAY,GAAG,YAAY,GAAG,eAAe,CAAC;IACxD,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,CAAC,EAAE,oBAAoB,GAAG,kBAAkB,CAAC;CACnD;AAED,MAAM,WAAW,kBAAkB;IACjC,IAAI,EAAE,cAAc,CAAC;IACrB,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,EAAE,MAAM,CAAC;IACpB,UAAU,EAAE,MAAM,CAAC;CACpB;AAED,wBAAsB,qBAAqB,CACzC,GAAG,EAAE,OAAO,EACZ,KAAK,EAAE,0BAA0B,GAChC,OAAO,CAAC,2BAA2B,CAAC,CAqEtC;AAmED;;;;;;;;;;;GAWG;AACH,wBAAgB,oBAAoB,CAAC,OAAO,EAAE,gBAAgB,GAAG,MAAM,CAyKtE"}