@pol-studios/powersync 1.0.30 → 1.0.33

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 (116) hide show
  1. package/dist/{CacheSettingsManager-uz-kbnRH.d.ts → CacheSettingsManager-0H_7thHW.d.ts} +21 -3
  2. package/dist/attachments/index.d.ts +30 -30
  3. package/dist/attachments/index.js +13 -4
  4. package/dist/{background-sync-CVR3PkFi.d.ts → background-sync-BujnI3IR.d.ts} +1 -1
  5. package/dist/{chunk-RE5HWLCB.js → chunk-2RDWLXJW.js} +322 -103
  6. package/dist/chunk-2RDWLXJW.js.map +1 -0
  7. package/dist/{chunk-P4HZA6ZT.js → chunk-4665ZSE5.js} +2 -2
  8. package/dist/chunk-4665ZSE5.js.map +1 -0
  9. package/dist/{chunk-XOY2CJ67.js → chunk-4F5B5CZ7.js} +3 -3
  10. package/dist/chunk-5WRI5ZAA.js +31 -0
  11. package/dist/{chunk-BC2SRII2.js → chunk-65A3SYJZ.js} +14 -1
  12. package/dist/chunk-65A3SYJZ.js.map +1 -0
  13. package/dist/chunk-6SZ64KCZ.js +755 -0
  14. package/dist/chunk-6SZ64KCZ.js.map +1 -0
  15. package/dist/{chunk-C2ACBYBZ.js → chunk-74TBHWJ4.js} +10 -96
  16. package/dist/{chunk-C2ACBYBZ.js.map → chunk-74TBHWJ4.js.map} +1 -1
  17. package/dist/chunk-ANXWYQEJ.js +1 -0
  18. package/dist/chunk-ANXWYQEJ.js.map +1 -0
  19. package/dist/{chunk-CAB26E6F.js → chunk-C4J4MLER.js} +29 -24
  20. package/dist/chunk-C4J4MLER.js.map +1 -0
  21. package/dist/{chunk-C5ODS3XH.js → chunk-EOW7JK7Q.js} +9 -16
  22. package/dist/chunk-EOW7JK7Q.js.map +1 -0
  23. package/dist/chunk-HRAVPIAZ.js +220 -0
  24. package/dist/chunk-HRAVPIAZ.js.map +1 -0
  25. package/dist/{chunk-XAEII4ZX.js → chunk-NUGQOTEM.js} +32 -4
  26. package/dist/chunk-NUGQOTEM.js.map +1 -0
  27. package/dist/chunk-OGUFUZSY.js +5415 -0
  28. package/dist/chunk-OGUFUZSY.js.map +1 -0
  29. package/dist/{chunk-JCGOZVWL.js → chunk-P4D6BQ4X.js} +115 -576
  30. package/dist/chunk-P4D6BQ4X.js.map +1 -0
  31. package/dist/{chunk-CACKC6XG.js → chunk-PGEDE6IM.js} +136 -89
  32. package/dist/chunk-PGEDE6IM.js.map +1 -0
  33. package/dist/{chunk-A4IBBWGO.js → chunk-RALHHPTU.js} +1 -1
  34. package/dist/chunk-RIDSPLE5.js +42 -0
  35. package/dist/chunk-RIDSPLE5.js.map +1 -0
  36. package/dist/{chunk-Z6VOBGTU.js → chunk-UOMHWUHV.js} +2 -12
  37. package/dist/chunk-UOMHWUHV.js.map +1 -0
  38. package/dist/{chunk-QREWE3NR.js → chunk-YONQYTVH.js} +2 -2
  39. package/dist/chunk-ZAN22NGL.js +13 -0
  40. package/dist/chunk-ZAN22NGL.js.map +1 -0
  41. package/dist/config/index.d.ts +200 -0
  42. package/dist/config/index.js +23 -0
  43. package/dist/config/index.js.map +1 -0
  44. package/dist/connector/index.d.ts +23 -5
  45. package/dist/connector/index.js +4 -1
  46. package/dist/core/index.d.ts +2 -2
  47. package/dist/core/index.js +1 -0
  48. package/dist/error/index.js +1 -0
  49. package/dist/generator/index.js +2 -0
  50. package/dist/generator/index.js.map +1 -1
  51. package/dist/index.d.ts +19 -16
  52. package/dist/index.js +68 -36
  53. package/dist/index.native.d.ts +18 -14
  54. package/dist/index.native.js +73 -34
  55. package/dist/index.web.d.ts +17 -14
  56. package/dist/index.web.js +68 -36
  57. package/dist/maintenance/index.d.ts +2 -2
  58. package/dist/maintenance/index.js +3 -2
  59. package/dist/platform/index.d.ts +1 -1
  60. package/dist/platform/index.js +2 -0
  61. package/dist/platform/index.js.map +1 -1
  62. package/dist/platform/index.native.d.ts +1 -1
  63. package/dist/platform/index.native.js +1 -0
  64. package/dist/platform/index.web.d.ts +1 -1
  65. package/dist/platform/index.web.js +1 -0
  66. package/dist/pol-attachment-queue-DqBvLAEY.d.ts +255 -0
  67. package/dist/provider/index.d.ts +149 -114
  68. package/dist/provider/index.js +9 -14
  69. package/dist/provider/index.native.d.ts +108 -0
  70. package/dist/provider/index.native.js +121 -0
  71. package/dist/provider/index.native.js.map +1 -0
  72. package/dist/provider/index.web.d.ts +16 -0
  73. package/dist/provider/index.web.js +112 -0
  74. package/dist/provider/index.web.js.map +1 -0
  75. package/dist/react/index.d.ts +16 -65
  76. package/dist/react/index.js +2 -9
  77. package/dist/storage/index.d.ts +5 -4
  78. package/dist/storage/index.js +12 -9
  79. package/dist/storage/index.native.d.ts +5 -4
  80. package/dist/storage/index.native.js +8 -5
  81. package/dist/storage/index.web.d.ts +5 -4
  82. package/dist/storage/index.web.js +11 -8
  83. package/dist/storage/upload/index.d.ts +4 -3
  84. package/dist/storage/upload/index.js +4 -2
  85. package/dist/storage/upload/index.native.d.ts +4 -3
  86. package/dist/storage/upload/index.native.js +4 -2
  87. package/dist/storage/upload/index.web.d.ts +2 -1
  88. package/dist/storage/upload/index.web.js +4 -2
  89. package/dist/{supabase-connector-C4YpH_l3.d.ts → supabase-connector-HMxBA9Kg.d.ts} +2 -2
  90. package/dist/sync/index.d.ts +155 -20
  91. package/dist/sync/index.js +13 -3
  92. package/dist/{types-CyvBaAl8.d.ts → types-6QHGELuY.d.ts} +4 -1
  93. package/dist/{types-Dv1uf0LZ.d.ts → types-B9MptP7E.d.ts} +7 -10
  94. package/dist/types-BhAEsJj-.d.ts +330 -0
  95. package/dist/{types-D0WcHrq6.d.ts → types-CGMibJKD.d.ts} +8 -0
  96. package/dist/{types-CpM2_LhU.d.ts → types-DqJnP50o.d.ts} +6 -1
  97. package/dist/{pol-attachment-queue-BE2HU3Us.d.ts → types-JCEhw2Lf.d.ts} +139 -346
  98. package/package.json +18 -4
  99. package/dist/chunk-654ERHA7.js +0 -1
  100. package/dist/chunk-BC2SRII2.js.map +0 -1
  101. package/dist/chunk-C5ODS3XH.js.map +0 -1
  102. package/dist/chunk-CAB26E6F.js.map +0 -1
  103. package/dist/chunk-CACKC6XG.js.map +0 -1
  104. package/dist/chunk-FNYQFILT.js +0 -44
  105. package/dist/chunk-FNYQFILT.js.map +0 -1
  106. package/dist/chunk-JCGOZVWL.js.map +0 -1
  107. package/dist/chunk-P4HZA6ZT.js.map +0 -1
  108. package/dist/chunk-RBPWEOIV.js +0 -358
  109. package/dist/chunk-RBPWEOIV.js.map +0 -1
  110. package/dist/chunk-RE5HWLCB.js.map +0 -1
  111. package/dist/chunk-XAEII4ZX.js.map +0 -1
  112. package/dist/chunk-Z6VOBGTU.js.map +0 -1
  113. /package/dist/{chunk-XOY2CJ67.js.map → chunk-4F5B5CZ7.js.map} +0 -0
  114. /package/dist/{chunk-654ERHA7.js.map → chunk-5WRI5ZAA.js.map} +0 -0
  115. /package/dist/{chunk-A4IBBWGO.js.map → chunk-RALHHPTU.js.map} +0 -0
  116. /package/dist/{chunk-QREWE3NR.js.map → chunk-YONQYTVH.js.map} +0 -0
@@ -0,0 +1,13 @@
1
+ // src/storage/upload/types.ts
2
+ var DEFAULT_UPLOAD_NOTIFICATION = {
3
+ enabled: true,
4
+ autoClear: true,
5
+ onProgressTitle: "Uploading...",
6
+ onCompleteTitle: "Upload complete",
7
+ onErrorTitle: "Upload failed"
8
+ };
9
+
10
+ export {
11
+ DEFAULT_UPLOAD_NOTIFICATION
12
+ };
13
+ //# sourceMappingURL=chunk-ZAN22NGL.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/storage/upload/types.ts"],"sourcesContent":["/**\n * Upload Handler Types for @pol-studios/powersync\n *\n * Defines types for platform-specific upload handlers.\n */\n\nimport type { SupabaseClient } from '@supabase/supabase-js';\n\n/**\n * Bucket configuration for multi-bucket routing.\n */\nexport interface BucketConfig {\n /** Default bucket for storage operations */\n defaultBucket: string;\n\n /** Map of path prefixes to bucket names */\n bucketMap?: Map<string, string>;\n\n /** Custom bucket resolver function */\n resolver?: (storagePath: string) => string | undefined;\n}\n\n/**\n * Options for creating a SupabaseUploadHandler.\n */\nexport interface SupabaseUploadHandlerOptions {\n /** Supabase client instance */\n supabaseClient: SupabaseClient;\n\n /** Bucket configuration for multi-bucket routing */\n bucketConfig: BucketConfig;\n}\n\n/**\n * Event handlers for upload progress tracking.\n */\nexport interface UploadEventHandlers {\n /** Called with progress updates during upload */\n onProgress?: (progress: {\n loaded: number;\n total: number;\n }) => void;\n\n /** Called when upload completes successfully */\n onComplete?: () => void;\n\n /** Called when upload fails */\n onError?: (error: Error) => void;\n}\n\n/**\n * Configuration for native upload notifications (Android).\n */\nexport interface UploadNotificationConfig {\n /** Whether to show upload notifications */\n enabled: boolean;\n\n /** Whether to auto-clear notification on completion */\n autoClear: boolean;\n\n /** Title shown during upload progress */\n onProgressTitle: string;\n\n /** Title shown when upload completes */\n onCompleteTitle: string;\n\n /** Title shown when upload fails */\n onErrorTitle: string;\n}\n\n/**\n * Default notification configuration for Android uploads.\n */\nexport const DEFAULT_UPLOAD_NOTIFICATION: UploadNotificationConfig = {\n enabled: true,\n autoClear: true,\n onProgressTitle: 'Uploading...',\n onCompleteTitle: 'Upload complete',\n onErrorTitle: 'Upload failed'\n};"],"mappings":";AAyEO,IAAM,8BAAwD;AAAA,EACnE,SAAS;AAAA,EACT,WAAW;AAAA,EACX,iBAAiB;AAAA,EACjB,iBAAiB;AAAA,EACjB,cAAc;AAChB;","names":[]}
@@ -0,0 +1,200 @@
1
+ import { D as DatabaseSchemaObject, T as TableSpec, f as DatabaseTableDef, P as PolConfig, a as ProcessedPolConfig, b as ProcessedTableStrategy } from '../types-BhAEsJj-.js';
2
+ export { g as DatabaseColumnDef, c as PolConfigAttachments, d as PolConfigConnector, e as PolConfigSync } from '../types-BhAEsJj-.js';
3
+ export { A as AttachmentSource, C as CustomAttachmentSource, A as PolAttachmentSource, b as SupabaseBucketSource } from '../types-JCEhw2Lf.js';
4
+ import { Schema } from '@powersync/react-native';
5
+ import '../types-DqJnP50o.js';
6
+ import '@supabase/supabase-js';
7
+ import '../types-B9MptP7E.js';
8
+ import '../platform/index.js';
9
+ import '@powersync/common';
10
+
11
+ /**
12
+ * Schema Generator for @pol-studios/powersync
13
+ *
14
+ * Generates PowerSync Schema at runtime from the Supabase database schema object.
15
+ * This eliminates the need to manually maintain a separate PowerSync schema file.
16
+ *
17
+ * Type Mapping:
18
+ * - number -> column.real (ALL numbers use real, no integer/real distinction)
19
+ * - boolean -> column.integer (SQLite stores booleans as 0/1)
20
+ * - string -> column.text
21
+ * - date -> column.text (ISO strings)
22
+ * - enum -> column.text
23
+ * - json -> SKIPPED (not supported in PowerSync)
24
+ * - arrays -> SKIPPED (not supported in PowerSync)
25
+ *
26
+ * Skipped columns:
27
+ * - `id` (PowerSync handles this automatically)
28
+ * - JSON types (complex objects not supported)
29
+ * - Array types (not supported)
30
+ */
31
+
32
+ /**
33
+ * Normalized table specification.
34
+ */
35
+ interface NormalizedTableSpec {
36
+ /** Table name (without schema prefix) */
37
+ tableName: string;
38
+ /** Schema name */
39
+ schemaName: string;
40
+ /** Whether to track sync metadata */
41
+ trackMetadata: boolean;
42
+ /**
43
+ * Alias for PowerSync table name.
44
+ * For cross-schema tables, this is SchemaTable (e.g., "CoreProfile").
45
+ * For public schema, this is just the table name.
46
+ */
47
+ alias: string;
48
+ }
49
+ /**
50
+ * Normalize a TableSpec to a consistent format.
51
+ *
52
+ * @param spec - The table specification (string or object)
53
+ * @returns Normalized specification with all fields filled
54
+ */
55
+ declare function normalizeTableSpec(spec: TableSpec): NormalizedTableSpec;
56
+ /**
57
+ * Get a table definition from the database schema.
58
+ *
59
+ * @param databaseSchema - The full database schema object
60
+ * @param schemaName - The schema name (e.g., "public", "core")
61
+ * @param tableName - The table name
62
+ * @returns The table definition or null if not found
63
+ */
64
+ declare function getTableFromSchema(databaseSchema: DatabaseSchemaObject, schemaName: string, tableName: string): DatabaseTableDef | null;
65
+ /**
66
+ * Result of schema generation.
67
+ */
68
+ interface SchemaGenerationResult {
69
+ /** The generated PowerSync Schema */
70
+ schema: Schema;
71
+ /** Warnings encountered during generation */
72
+ warnings: string[];
73
+ /** Map of table alias to normalized spec */
74
+ tableMap: Map<string, NormalizedTableSpec>;
75
+ }
76
+ /**
77
+ * Generate a PowerSync Schema from the database schema and table specs.
78
+ *
79
+ * @param databaseSchema - The database schema object (from generated types)
80
+ * @param tables - Array of table specifications to sync
81
+ * @returns The generated PowerSync Schema and metadata
82
+ *
83
+ * @example
84
+ * ```typescript
85
+ * const { schema, warnings } = generatePowerSyncSchema(databaseSchema, [
86
+ * "Project",
87
+ * "Task",
88
+ * { table: "Profile", schema: "core" },
89
+ * ]);
90
+ *
91
+ * // Use the schema with PowerSyncProvider
92
+ * <PowerSyncProvider config={{ schema, ... }} />
93
+ * ```
94
+ */
95
+ declare function generatePowerSyncSchema(databaseSchema: DatabaseSchemaObject, tables: TableSpec[]): SchemaGenerationResult;
96
+ /**
97
+ * Create a schema router function from the table map.
98
+ *
99
+ * @param tableMap - Map of table alias to normalized spec
100
+ * @returns A function that returns the schema for a given table
101
+ */
102
+ declare function createSchemaRouter(tableMap: Map<string, NormalizedTableSpec>): (table: string) => string;
103
+
104
+ /**
105
+ * Unified Configuration for @pol-studios/powersync
106
+ *
107
+ * This module provides the `definePolConfig` function for creating
108
+ * a unified configuration that automatically generates:
109
+ * - PowerSync Schema from the database schema
110
+ * - Table routing strategies for DataLayer
111
+ * - Attachment queue configuration
112
+ *
113
+ * @example
114
+ * ```typescript
115
+ * import { definePolConfig } from '@pol-studios/powersync/config';
116
+ * import { databaseSchema } from './databaseSchema';
117
+ *
118
+ * export const polConfig = definePolConfig({
119
+ * powerSyncUrl: process.env.EXPO_PUBLIC_POWERSYNC_URL,
120
+ * databaseSchema,
121
+ * powersync: ["Project", "Task", { table: "Profile", schema: "core" }],
122
+ * attachments: {
123
+ * source: { type: 'supabase-bucket', bucket: 'photos' },
124
+ * watchPaths: (db, supabase, onUpdate) => {
125
+ * const abort = new AbortController();
126
+ * db.watch(
127
+ * `SELECT storagePath FROM photos WHERE storagePath IS NOT NULL`,
128
+ * [],
129
+ * { onResult: (r) => onUpdate(r.rows._array.map(x => x.storagePath)) },
130
+ * { signal: abort.signal }
131
+ * );
132
+ * return () => abort.abort();
133
+ * },
134
+ * },
135
+ * });
136
+ *
137
+ * // Use with OfflineDataProvider
138
+ * <OfflineDataProvider polConfig={polConfig}>
139
+ * <App />
140
+ * </OfflineDataProvider>
141
+ * ```
142
+ */
143
+
144
+ /**
145
+ * Create a unified PowerSync configuration.
146
+ *
147
+ * This function processes the configuration to generate:
148
+ * - `__generatedSchema`: PowerSync Schema ready for use
149
+ * - `__tableStrategies`: Lookup map for routing queries
150
+ * - `__schemaRouter`: Function to resolve table schemas
151
+ *
152
+ * @param config - The unified configuration
153
+ * @returns Processed configuration with generated artifacts
154
+ *
155
+ * @example
156
+ * ```typescript
157
+ * const polConfig = definePolConfig({
158
+ * powerSyncUrl: 'https://your-instance.powersync.journeyapps.com',
159
+ * databaseSchema,
160
+ * powersync: [
161
+ * "Project",
162
+ * "Task",
163
+ * { table: "Profile", schema: "core" },
164
+ * ],
165
+ * });
166
+ *
167
+ * // Access generated schema
168
+ * console.log(polConfig.__generatedSchema);
169
+ *
170
+ * // Check if a table uses PowerSync
171
+ * const strategy = polConfig.__tableStrategies["Project"];
172
+ * console.log(strategy.strategy); // "powersync"
173
+ * ```
174
+ */
175
+ declare function definePolConfig(config: PolConfig): ProcessedPolConfig;
176
+ /**
177
+ * Check if a configuration is a processed PolConfig.
178
+ *
179
+ * @param config - The configuration to check
180
+ * @returns true if the config has been processed by definePolConfig
181
+ */
182
+ declare function isProcessedPolConfig(config: unknown): config is ProcessedPolConfig;
183
+ /**
184
+ * Get the strategy for a table from a processed config.
185
+ *
186
+ * @param config - The processed configuration
187
+ * @param tableName - Table name (can be "Table" or "schema.Table")
188
+ * @returns The strategy or undefined if not found
189
+ */
190
+ declare function getTableStrategy(config: ProcessedPolConfig, tableName: string): ProcessedTableStrategy | undefined;
191
+ /**
192
+ * Check if a table uses PowerSync for sync.
193
+ *
194
+ * @param config - The processed configuration
195
+ * @param tableName - Table name
196
+ * @returns true if the table is synced via PowerSync
197
+ */
198
+ declare function isTablePowerSync(config: ProcessedPolConfig, tableName: string): boolean;
199
+
200
+ export { DatabaseSchemaObject, DatabaseTableDef, PolConfig, ProcessedPolConfig, ProcessedTableStrategy, TableSpec, createSchemaRouter, definePolConfig, generatePowerSyncSchema, getTableFromSchema, getTableStrategy, isProcessedPolConfig, isTablePowerSync, normalizeTableSpec };
@@ -0,0 +1,23 @@
1
+ import {
2
+ createSchemaRouter,
3
+ definePolConfig,
4
+ generatePowerSyncSchema,
5
+ getTableFromSchema,
6
+ getTableStrategy,
7
+ isProcessedPolConfig,
8
+ isTablePowerSync,
9
+ normalizeTableSpec
10
+ } from "../chunk-HRAVPIAZ.js";
11
+ import "../chunk-OGUFUZSY.js";
12
+ import "../chunk-5WRI5ZAA.js";
13
+ export {
14
+ createSchemaRouter,
15
+ definePolConfig,
16
+ generatePowerSyncSchema,
17
+ getTableFromSchema,
18
+ getTableStrategy,
19
+ isProcessedPolConfig,
20
+ isTablePowerSync,
21
+ normalizeTableSpec
22
+ };
23
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":[],"sourcesContent":[],"mappings":"","names":[]}
@@ -1,8 +1,8 @@
1
- import { A as AuthProvider, h as UploadErrorMiddleware, g as UploadErrorContext, U as UploadErrorClassification } from '../types-CpM2_LhU.js';
2
- export { i as ConflictBus, C as ConnectorCircuitBreakerConfig, a as ConnectorConfig, c as CrudHandler, D as DEFAULT_RETRY_CONFIG, P as PowerSyncCredentials, e as RetryConfig, R as RetryStrategyConfig, b as SchemaRouter, f as Session, S as SupabaseConnectorOptions, d as defaultSchemaRouter } from '../types-CpM2_LhU.js';
3
- export { S as SupabaseConnector } from '../supabase-connector-C4YpH_l3.js';
1
+ import { A as AuthProvider, h as UploadErrorMiddleware, g as UploadErrorContext, U as UploadErrorClassification } from '../types-DqJnP50o.js';
2
+ export { i as ConflictBus, C as ConnectorCircuitBreakerConfig, a as ConnectorConfig, c as CrudHandler, D as DEFAULT_RETRY_CONFIG, P as PowerSyncCredentials, e as RetryConfig, R as RetryStrategyConfig, b as SchemaRouter, f as Session, S as SupabaseConnectorOptions, d as defaultSchemaRouter } from '../types-DqJnP50o.js';
3
+ export { S as SupabaseConnector } from '../supabase-connector-HMxBA9Kg.js';
4
4
  import { SupabaseClient } from '@supabase/supabase-js';
5
- export { P as PowerSyncBackendConnector } from '../types-Dv1uf0LZ.js';
5
+ export { P as PowerSyncBackendConnector } from '../types-B9MptP7E.js';
6
6
  import '../platform/index.js';
7
7
 
8
8
  /**
@@ -298,6 +298,24 @@ declare function idempotentTables(tables: string[]): UploadErrorMiddleware;
298
298
  * ```
299
299
  */
300
300
  declare function discardOrphaned(): UploadErrorMiddleware;
301
+ /**
302
+ * Create middleware that discards entries denied by Row Level Security (RLS).
303
+ *
304
+ * PostgreSQL error code 42501 (insufficient_privilege) is returned when a
305
+ * user attempts an operation that violates RLS policies. These are permanent
306
+ * errors that will never succeed on retry, so discarding them prevents
307
+ * the upload queue from getting blocked.
308
+ *
309
+ * @returns Middleware function
310
+ *
311
+ * @example
312
+ * ```typescript
313
+ * uploadErrorMiddleware: [
314
+ * discardOnRlsDenied(),
315
+ * ]
316
+ * ```
317
+ */
318
+ declare function discardOnRlsDenied(): UploadErrorMiddleware;
301
319
  /**
302
320
  * Create middleware that discards entries with specific PostgreSQL error codes.
303
321
  *
@@ -410,4 +428,4 @@ declare function runUploadErrorMiddleware(context: UploadErrorContext, middlewar
410
428
  */
411
429
  declare function runUploadErrorMiddlewareSync(context: UploadErrorContext, middleware: UploadErrorMiddleware[], defaultClassification?: UploadErrorClassification): UploadErrorClassification;
412
430
 
413
- export { AuthProvider, AuthRefreshError, CircuitBreaker, type CircuitBreakerConfig, type CircuitBreakerStats, CircuitOpenError, type CircuitState, DEFAULT_CIRCUIT_BREAKER_CONFIG, DiscardEntryError, type SupabaseAuthOptions, TransactionAbortError, UploadErrorClassification, UploadErrorContext, UploadErrorMiddleware, createSupabaseAuth, discardOnHttpStatus, discardOnPgCodes, discardOrphaned, idempotentTables, retryOnHttpStatus, runUploadErrorMiddleware, runUploadErrorMiddlewareSync, successOnPgCodes, tableHandlers };
431
+ export { AuthProvider, AuthRefreshError, CircuitBreaker, type CircuitBreakerConfig, type CircuitBreakerStats, CircuitOpenError, type CircuitState, DEFAULT_CIRCUIT_BREAKER_CONFIG, DiscardEntryError, type SupabaseAuthOptions, TransactionAbortError, UploadErrorClassification, UploadErrorContext, UploadErrorMiddleware, createSupabaseAuth, discardOnHttpStatus, discardOnPgCodes, discardOnRlsDenied, discardOrphaned, idempotentTables, retryOnHttpStatus, runUploadErrorMiddleware, runUploadErrorMiddlewareSync, successOnPgCodes, tableHandlers };
@@ -13,6 +13,7 @@ import {
13
13
  defaultSchemaRouter,
14
14
  discardOnHttpStatus,
15
15
  discardOnPgCodes,
16
+ discardOnRlsDenied,
16
17
  discardOrphaned,
17
18
  idempotentTables,
18
19
  retryOnHttpStatus,
@@ -20,8 +21,9 @@ import {
20
21
  runUploadErrorMiddlewareSync,
21
22
  successOnPgCodes,
22
23
  tableHandlers
23
- } from "../chunk-BC2SRII2.js";
24
+ } from "../chunk-65A3SYJZ.js";
24
25
  import "../chunk-I2AYMY5O.js";
26
+ import "../chunk-5WRI5ZAA.js";
25
27
  export {
26
28
  AuthRefreshError,
27
29
  CircuitBreaker,
@@ -35,6 +37,7 @@ export {
35
37
  defaultSchemaRouter,
36
38
  discardOnHttpStatus,
37
39
  discardOnPgCodes,
40
+ discardOnRlsDenied,
38
41
  discardOrphaned,
39
42
  idempotentTables,
40
43
  retryOnHttpStatus,
@@ -1,5 +1,5 @@
1
- import { g as SyncErrorType, i as ClassifiedError, f as SyncError, C as CrudEntry } from '../types-Dv1uf0LZ.js';
2
- export { A as AbstractPowerSyncDatabase, k as CacheStats, j as CompactResult, h as CompletedTransaction, b as ConnectionHealth, o as CountRow, l as CrudTransaction, n as DbStatRow, D as DownloadProgress, E as EntitySyncState, F as FailedTransaction, r as FreelistCountRow, s as IntegrityCheckRow, I as IntegrityResult, q as PageCountRow, p as PageSizeRow, P as PowerSyncBackendConnector, m as SqliteTableRow, c as StorageInfo, d as StorageQuota, e as SyncMetrics, S as SyncMode, a as SyncStatus, T as TableCacheStats, U as UploadBlockReason } from '../types-Dv1uf0LZ.js';
1
+ import { g as SyncErrorType, i as ClassifiedError, f as SyncError, C as CrudEntry } from '../types-B9MptP7E.js';
2
+ export { A as AbstractPowerSyncDatabase, k as CacheStats, j as CompactResult, h as CompletedTransaction, b as ConnectionHealth, o as CountRow, l as CrudTransaction, n as DbStatRow, D as DownloadProgress, E as EntitySyncState, F as FailedTransaction, r as FreelistCountRow, s as IntegrityCheckRow, I as IntegrityResult, q as PageCountRow, p as PageSizeRow, P as PowerSyncBackendConnector, m as SqliteTableRow, c as StorageInfo, d as StorageQuota, e as SyncMetrics, S as SyncMode, a as SyncStatus, T as TableCacheStats, U as UploadBlockReason } from '../types-B9MptP7E.js';
3
3
 
4
4
  /**
5
5
  * Constants for @pol-studios/powersync
@@ -50,6 +50,7 @@ import {
50
50
  isRlsError,
51
51
  toSyncOperationError
52
52
  } from "../chunk-I2AYMY5O.js";
53
+ import "../chunk-5WRI5ZAA.js";
53
54
  export {
54
55
  ATTACHMENT_DOWNLOAD_TIMEOUT_MS,
55
56
  ATTACHMENT_RETRY_DELAY_MS,
@@ -1,6 +1,7 @@
1
1
  import {
2
2
  PowerSyncErrorBoundary
3
3
  } from "../chunk-P6WOZO7H.js";
4
+ import "../chunk-5WRI5ZAA.js";
4
5
  export {
5
6
  PowerSyncErrorBoundary
6
7
  };
@@ -1,3 +1,5 @@
1
+ import "../chunk-5WRI5ZAA.js";
2
+
1
3
  // src/generator/config.ts
2
4
  function defineConfig(config) {
3
5
  return config;
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/generator/config.ts","../../src/generator/generator.ts","../../src/generator/parser.ts","../../src/generator/templates.ts","../../src/generator/fk-dependencies.ts"],"sourcesContent":["/**\n * Configuration types and helpers for PowerSync schema generator\n */\n\nexport interface TableConfig {\n /** Table name (PascalCase as it appears in database.types.ts) */\n name: string;\n /** Schema name (defaults to 'public') */\n schema?: string;\n /** Enable ps_crud timestamp tracking for optimistic UI updates */\n trackMetadata?: boolean;\n /**\n * Sync the primary key column (normally skipped as PowerSync handles it internally).\n *\n * Use this for tables with integer PKs that are referenced by FKs in other tables.\n * Example: `Group.id` is referenced by `UserGroup.groupId`, so Group needs `syncPrimaryKey: true`\n * to ensure the integer ID is available for client-side joins.\n */\n syncPrimaryKey?: boolean;\n /** @deprecated Use `syncPrimaryKey` instead */\n includeId?: boolean;\n /** Columns to skip for this specific table (in addition to global skipColumns) */\n skipColumns?: string[];\n /** Only include these columns (overrides skipColumns if specified) */\n onlyColumns?: string[];\n /** Alias for the table in PowerSync schema (for conflicting names across schemas) */\n alias?: string;\n /** Table is local-only (not synced through PowerSync) */\n localOnly?: boolean;\n}\nexport interface GeneratorConfig {\n /** Path to Supabase-generated database.types.ts file */\n typesPath: string;\n /** Output path for generated PowerSync schema */\n outputPath: string;\n /** Tables to include in the PowerSync schema */\n tables: TableConfig[];\n /** Columns to always skip (in addition to defaults like 'id') */\n skipColumns?: string[];\n /** Column name patterns that should use column.real for decimal values */\n decimalPatterns?: string[];\n /** Additional schemas to track (besides 'public' which is the default) */\n schemas?: string[];\n /** Generate indexes for FK and common columns (default: true) */\n autoIndexes?: boolean;\n /** Additional columns to index (exact column names) */\n indexColumns?: string[];\n /** Column patterns that should be indexed (regex patterns) */\n indexPatterns?: string[];\n}\n\n/**\n * Define a PowerSync generator configuration with type safety\n */\nexport function defineConfig(config: GeneratorConfig): GeneratorConfig {\n return config;\n}\n\n/**\n * Default columns that are skipped during generation\n */\nexport const DEFAULT_SKIP_COLUMNS = ['id',\n// PowerSync handles id automatically\n// Legacy numeric ID columns - typically not needed after UUID migration\n'legacyId'];\n\n/**\n * Default column name patterns that indicate decimal values\n */\nexport const DEFAULT_DECIMAL_PATTERNS = ['hours', 'watts', 'voltage', 'rate', 'amount', 'price', 'cost', 'total'];\n\n/**\n * Default column patterns that should be indexed\n * These are regex patterns matched against column names\n */\nexport const DEFAULT_INDEX_PATTERNS = ['Id$',\n// FK columns ending in Id (e.g., projectId, userId)\n'^createdAt$', '^updatedAt$', '^status$', '^type$'];\n\n/**\n * Required authentication/access control tables for offline auth\n * These tables are needed for proper offline access control\n */\nexport interface RequiredAuthTable {\n /** Table name (PascalCase) */\n name: string;\n /** Schema name */\n schema: string;\n /** Whether this table requires syncPrimaryKey to be true */\n requiresSyncPrimaryKey?: boolean;\n}\nexport const REQUIRED_AUTH_TABLES: RequiredAuthTable[] = [{\n name: 'UserAccess',\n schema: 'core'\n}, {\n name: 'UserGroup',\n schema: 'core'\n}, {\n name: 'GroupAccessKey',\n schema: 'core',\n requiresSyncPrimaryKey: true\n}, {\n name: 'Group',\n schema: 'core',\n requiresSyncPrimaryKey: true\n}];","/**\n * PowerSync schema generator\n *\n * Converts Supabase database.types.ts into PowerSync schema definitions\n */\n\nimport * as fs from 'fs';\nimport * as path from 'path';\nimport type { GeneratorConfig, TableConfig } from './config.js';\nimport { DEFAULT_SKIP_COLUMNS, DEFAULT_DECIMAL_PATTERNS, DEFAULT_INDEX_PATTERNS, REQUIRED_AUTH_TABLES } from './config.js';\nimport { parseTypesFile, type ParsedTable } from './parser.js';\nimport { generateTableDefinition, generateLocalOnlyTableDefinition, generateOutputFile, generateIndexDefinitions, type IndexDefinition } from './templates.js';\nimport { detectFKDependencies, type DependencyGraph } from './fk-dependencies.js';\nexport interface ColumnMapping {\n type: 'column.text' | 'column.integer' | 'column.real';\n isEnum?: boolean;\n isBoolean?: boolean;\n isJson?: boolean;\n}\nexport interface GenerateResult {\n success: boolean;\n tablesGenerated: number;\n outputPath: string;\n errors: string[];\n warnings: string[];\n /** Generated output (included when dryRun is true) */\n output?: string;\n /** Number of indexes generated */\n indexesGenerated?: number;\n /** FK dependency graph (when detected) */\n dependencyGraph?: DependencyGraph;\n}\n\n/**\n * Map TypeScript types to PowerSync column types\n */\nexport function mapTypeToPowerSync(tsType: string, columnName: string, decimalPatterns: string[]): ColumnMapping | null {\n // Clean up the type (remove nullability)\n const cleanType = tsType.trim().replace(/\\s*\\|\\s*null/g, '');\n\n // JSON types -> store as TEXT (will be parsed/stringified by type-transformer)\n if (cleanType.includes('Json')) {\n return {\n type: 'column.text',\n isJson: true\n };\n }\n\n // Skip complex types that can't be stored in SQLite\n if (cleanType.includes('unknown') || cleanType.includes('{')) {\n return null;\n }\n\n // Array types - skip\n if (cleanType.includes('[]')) {\n return null;\n }\n\n // Boolean -> integer (0/1)\n if (cleanType === 'boolean') {\n return {\n type: 'column.integer',\n isBoolean: true\n };\n }\n\n // Number types\n if (cleanType === 'number') {\n // Use real for columns that might have decimals\n if (decimalPatterns.some(pattern => columnName.toLowerCase().includes(pattern.toLowerCase()))) {\n return {\n type: 'column.real'\n };\n }\n return {\n type: 'column.integer'\n };\n }\n\n // String types\n if (cleanType === 'string') {\n return {\n type: 'column.text'\n };\n }\n\n // Enum types (Database[\"schema\"][\"Enums\"][\"EnumName\"]) -> store as text\n if (cleanType.includes('Database[') && cleanType.includes('Enums')) {\n return {\n type: 'column.text',\n isEnum: true\n };\n }\n\n // Default to text for unknown types (likely enums or other string-like types)\n return {\n type: 'column.text'\n };\n}\n\n/**\n * Generate column definitions for a table\n */\nexport function generateColumnDefs(table: ParsedTable, decimalPatterns: string[]): string[] {\n const columnDefs: string[] = [];\n for (const [columnName, tsType] of table.columns) {\n const mapping = mapTypeToPowerSync(tsType, columnName, decimalPatterns);\n if (mapping) {\n // Add comment for boolean, enum, and json columns\n let comment = '';\n if (mapping.isBoolean) {\n comment = ' // boolean stored as 0/1';\n } else if (mapping.isEnum) {\n comment = ' // enum stored as text';\n } else if (mapping.isJson) {\n comment = ' // JSON stored as text';\n }\n columnDefs.push(` ${columnName}: ${mapping.type},${comment}`);\n }\n }\n return columnDefs;\n}\n\n/**\n * Validate that required auth tables are included in config\n * Returns warnings for missing tables or misconfigured tables\n */\nexport function validateAuthTables(tables: TableConfig[]): string[] {\n const warnings: string[] = [];\n for (const authTable of REQUIRED_AUTH_TABLES) {\n const configTable = tables.find(t => t.name === authTable.name && (t.schema ?? 'public') === authTable.schema);\n if (!configTable) {\n warnings.push(`Missing required auth table: ${authTable.schema}.${authTable.name} - offline access control may not work correctly`);\n } else if (authTable.requiresSyncPrimaryKey && !configTable.syncPrimaryKey) {\n warnings.push(`Auth table ${authTable.schema}.${authTable.name} should have syncPrimaryKey: true for proper FK references`);\n }\n }\n return warnings;\n}\n\n/**\n * Validate FK references to ensure all referenced tables are in the config\n * Returns warnings for missing FK targets\n */\nexport function validateFKReferences(dependencyGraph: DependencyGraph, configuredTables: Set<string>): string[] {\n const warnings: string[] = [];\n for (const fk of dependencyGraph.fkRelationships) {\n if (!configuredTables.has(fk.referencedTable)) {\n warnings.push(`FK reference ${fk.table}.${fk.column} references table '${fk.referencedTable}' which is not in the config`);\n }\n }\n return warnings;\n}\n\n/**\n * Generate PowerSync schema from configuration\n */\nexport async function generateSchema(config: GeneratorConfig, options?: {\n cwd?: string;\n verbose?: boolean;\n dryRun?: boolean;\n}): Promise<GenerateResult> {\n const cwd = options?.cwd ?? process.cwd();\n const verbose = options?.verbose ?? false;\n const dryRun = options?.dryRun ?? false;\n const result: GenerateResult = {\n success: false,\n tablesGenerated: 0,\n outputPath: '',\n errors: [],\n warnings: []\n };\n\n // Resolve paths relative to cwd\n const typesPath = path.isAbsolute(config.typesPath) ? config.typesPath : path.resolve(cwd, config.typesPath);\n const outputPath = path.isAbsolute(config.outputPath) ? config.outputPath : path.resolve(cwd, config.outputPath);\n result.outputPath = outputPath;\n\n // Validate required auth tables\n const authWarnings = validateAuthTables(config.tables);\n result.warnings.push(...authWarnings);\n\n // Check if types file exists\n if (!fs.existsSync(typesPath)) {\n result.errors.push(`Types file not found: ${typesPath}`);\n return result;\n }\n\n // Read types file\n if (verbose) {\n console.log(`Reading types from: ${typesPath}`);\n }\n const typesContent = fs.readFileSync(typesPath, 'utf-8');\n\n // Build skip columns set\n const skipColumns = new Set([...DEFAULT_SKIP_COLUMNS, ...(config.skipColumns ?? [])]);\n\n // Build decimal patterns\n const decimalPatterns = [...DEFAULT_DECIMAL_PATTERNS, ...(config.decimalPatterns ?? [])];\n\n // Parse tables from types file\n const parsedTables = parseTypesFile(typesContent, config.tables, skipColumns);\n\n // Check for tables that weren't found\n for (const tableConfig of config.tables) {\n const found = parsedTables.some(t => t.name === tableConfig.name);\n if (!found) {\n result.warnings.push(`Table '${tableConfig.name}' not found in schema '${tableConfig.schema ?? 'public'}'`);\n }\n }\n if (parsedTables.length === 0) {\n result.errors.push('No tables were parsed successfully');\n return result;\n }\n\n // Build index patterns (auto-indexes enabled by default)\n const autoIndexes = config.autoIndexes ?? true;\n const indexPatterns = autoIndexes ? [...DEFAULT_INDEX_PATTERNS, ...(config.indexPatterns ?? [])] : config.indexPatterns ?? [];\n const indexColumns = config.indexColumns ?? [];\n\n // Detect FK dependencies\n const dependencyGraph = detectFKDependencies(parsedTables);\n result.dependencyGraph = dependencyGraph;\n\n // Validate FK references - warn if any FK targets a table not in config\n const configuredTableNames = new Set(config.tables.map(t => t.name));\n const fkWarnings = validateFKReferences(dependencyGraph, configuredTableNames);\n result.warnings.push(...fkWarnings);\n if (verbose && dependencyGraph.fkRelationships.length > 0) {\n console.log(`\\nFK Dependencies detected: ${dependencyGraph.fkRelationships.length}`);\n for (const fk of dependencyGraph.fkRelationships) {\n console.log(` ${fk.table}.${fk.column} -> ${fk.referencedTable}`);\n }\n console.log(`\\nRecommended upload order:`);\n dependencyGraph.uploadOrder.forEach((table, i) => {\n console.log(` ${i + 1}. ${table}`);\n });\n console.log('');\n }\n\n // Generate table definitions - separate synced and local-only tables\n const syncedTableDefs: string[] = [];\n const localOnlyTableDefs: string[] = [];\n let totalIndexes = 0;\n for (const table of parsedTables) {\n const isLocalOnly = table.config.localOnly ?? false;\n const tableAlias = table.config.alias;\n if (verbose) {\n const syncPK = table.config.syncPrimaryKey || table.config.includeId;\n const flags = [table.config.trackMetadata ? '[trackMetadata]' : '', syncPK ? '[syncPrimaryKey]' : '', isLocalOnly ? '[localOnly]' : '', tableAlias ? `[alias: ${tableAlias}]` : ''].filter(Boolean).join(' ');\n console.log(`Processing ${table.schema}.${table.name} (${table.columns.size} columns)${flags ? ' ' + flags : ''}`);\n }\n const columnDefs = generateColumnDefs(table, decimalPatterns);\n if (columnDefs.length === 0) {\n result.warnings.push(`Table '${table.name}' has no syncable columns`);\n continue;\n }\n\n // Generate indexes for this table (use alias for index naming if provided)\n const effectiveTableName = tableAlias ?? table.name;\n const columnNames = [...table.columns.keys()];\n const indexes = indexPatterns.length > 0 || indexColumns.length > 0 ? generateIndexDefinitions(effectiveTableName, columnNames, indexPatterns, indexColumns) : [];\n totalIndexes += indexes.length;\n if (verbose && indexes.length > 0) {\n console.log(` Indexes: ${indexes.map(i => i.name).join(', ')}`);\n }\n\n // Generate table definition based on localOnly flag\n if (isLocalOnly) {\n localOnlyTableDefs.push(generateLocalOnlyTableDefinition(table, columnDefs, indexes));\n } else {\n syncedTableDefs.push(generateTableDefinition(table, columnDefs, indexes));\n }\n }\n\n // Combine synced and local-only table definitions\n const tableDefs = [...syncedTableDefs, ...localOnlyTableDefs];\n result.indexesGenerated = totalIndexes;\n\n // Collect unique schemas\n const schemas = [...new Set(config.tables.map(t => t.schema ?? 'public'))];\n\n // Generate output file content\n const relativePath = path.relative(cwd, typesPath);\n // Filter tables that were successfully generated (check for both name and alias)\n const generatedTables = parsedTables.filter(t => {\n const effectiveName = t.config.alias ?? t.name;\n return tableDefs.some(def => def.includes(`const ${effectiveName} =`));\n });\n const output = generateOutputFile(generatedTables, tableDefs, schemas, relativePath);\n\n // If dry-run, return output without writing\n if (dryRun) {\n result.success = true;\n result.tablesGenerated = tableDefs.length;\n result.output = output;\n return result;\n }\n\n // Ensure output directory exists\n const outputDir = path.dirname(outputPath);\n if (!fs.existsSync(outputDir)) {\n fs.mkdirSync(outputDir, {\n recursive: true\n });\n }\n\n // Write output file\n fs.writeFileSync(outputPath, output);\n result.success = true;\n result.tablesGenerated = tableDefs.length;\n return result;\n}","/**\n * Parser for Supabase database.types.ts files\n *\n * Extracts table definitions and column types from the generated TypeScript types\n */\n\nimport type { TableConfig } from './config.js';\nexport interface ColumnInfo {\n name: string;\n tsType: string;\n isNullable: boolean;\n}\nexport interface ParsedTable {\n name: string;\n schema: string;\n columns: Map<string, string>;\n config: TableConfig;\n}\nexport interface ParseOptions {\n /** Columns to skip */\n skipColumns: Set<string>;\n /**\n * Include the id column (normally skipped).\n * Use for tables with integer PKs referenced by FKs in other tables.\n */\n syncPrimaryKey?: boolean;\n /** @deprecated Use `syncPrimaryKey` instead */\n includeId?: boolean;\n /** Only include these columns (overrides skipColumns if specified) */\n onlyColumns?: string[];\n}\n\n/**\n * Parse the Row type from a table definition and extract columns\n */\nexport function parseRowType(tableContent: string, options: ParseOptions): Map<string, string> {\n const columns = new Map<string, string>();\n\n // Find the Row block - handles nested braces in type definitions\n const rowMatch = tableContent.match(/Row:\\s*\\{([^}]+(?:\\{[^}]*\\}[^}]*)*)\\}/s);\n if (!rowMatch) return columns;\n const rowContent = rowMatch[1];\n\n // syncPrimaryKey takes precedence, with includeId as fallback for backwards compat\n const includePrimaryKey = options.syncPrimaryKey ?? options.includeId ?? false;\n\n // If onlyColumns is specified, use it as a whitelist (overrides skipColumns)\n const onlyColumnsSet = options.onlyColumns ? new Set(options.onlyColumns) : null;\n\n // Parse each column: \"columnName: type\" or \"columnName?: type\"\n const columnRegex = /(\\w+)\\??:\\s*([^,\\n]+)/g;\n let match;\n while ((match = columnRegex.exec(rowContent)) !== null) {\n const [, columnName, columnType] = match;\n\n // Determine if column should be included\n let shouldInclude: boolean;\n if (onlyColumnsSet) {\n // onlyColumns mode: only include explicitly listed columns\n // Exception: include 'id' if syncPrimaryKey is true\n shouldInclude = onlyColumnsSet.has(columnName) || includePrimaryKey && columnName === 'id';\n } else {\n // skipColumns mode: include unless explicitly skipped\n // Exception: include 'id' if syncPrimaryKey is true\n const isSkipped = options.skipColumns.has(columnName);\n shouldInclude = !isSkipped || includePrimaryKey && columnName === 'id';\n }\n if (shouldInclude) {\n columns.set(columnName, columnType.trim());\n }\n }\n return columns;\n}\n\n/**\n * Escape special regex characters in a string\n */\nfunction escapeRegex(str: string): string {\n return str.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&');\n}\n\n/**\n * Extract a table definition from the database.types.ts content\n *\n * Uses bracket-counting to properly handle nested arrays in Relationships\n * (e.g., columns: [\"parentId\"] inside relationship objects)\n */\nexport function extractTableDef(content: string, tableName: string, schema: string): string | null {\n // Escape special characters in schema and table names for regex safety\n const escapedSchema = escapeRegex(schema);\n const escapedTableName = escapeRegex(tableName);\n\n // Find the schema section\n const schemaRegex = new RegExp(`${escapedSchema}:\\\\s*\\\\{[\\\\s\\\\S]*?Tables:\\\\s*\\\\{`, 'g');\n const schemaMatch = schemaRegex.exec(content);\n if (!schemaMatch) return null;\n const startIndex = schemaMatch.index;\n const searchContent = content.slice(startIndex);\n\n // Find the start of this specific table\n // Use negative lookbehind (?<![A-Za-z]) to avoid matching table names that are\n // substrings of other names (e.g., \"Tag\" in \"CommentTag\")\n const tableStartRegex = new RegExp(`(?<![A-Za-z])${escapedTableName}:\\\\s*\\\\{`, 'g');\n const tableStartMatch = tableStartRegex.exec(searchContent);\n if (!tableStartMatch) return null;\n\n // Use bracket counting to find the matching closing brace\n const tableStartIndex = tableStartMatch.index;\n const openBraceIndex = tableStartMatch.index + tableStartMatch[0].length - 1;\n let braceCount = 1;\n let i = openBraceIndex + 1;\n while (i < searchContent.length && braceCount > 0) {\n const char = searchContent[i];\n if (char === '{') braceCount++;else if (char === '}') braceCount--;\n i++;\n }\n if (braceCount !== 0) return null;\n return searchContent.slice(tableStartIndex, i);\n}\n\n/**\n * Parse a database.types.ts file and extract specified tables\n */\nexport function parseTypesFile(content: string, tables: TableConfig[], globalSkipColumns: Set<string>): ParsedTable[] {\n const parsedTables: ParsedTable[] = [];\n for (const tableConfig of tables) {\n const {\n name,\n schema = 'public',\n syncPrimaryKey,\n includeId,\n skipColumns: tableSkipColumns,\n onlyColumns\n } = tableConfig;\n const tableDef = extractTableDef(content, name, schema);\n if (!tableDef) {\n continue;\n }\n\n // Merge global and per-table skipColumns\n const mergedSkipColumns = new Set([...globalSkipColumns, ...(tableSkipColumns ?? [])]);\n const columns = parseRowType(tableDef, {\n skipColumns: mergedSkipColumns,\n syncPrimaryKey,\n includeId,\n onlyColumns\n });\n if (columns.size > 0) {\n parsedTables.push({\n name,\n schema,\n columns,\n config: tableConfig\n });\n }\n }\n return parsedTables;\n}\n\n/**\n * Get all available schemas from the types file\n */\nexport function getAvailableSchemas(content: string): string[] {\n const schemas: string[] = [];\n const schemaRegex = /(\\w+):\\s*\\{[\\s\\S]*?Tables:\\s*\\{/g;\n let match;\n while ((match = schemaRegex.exec(content)) !== null) {\n schemas.push(match[1]);\n }\n return schemas;\n}\n\n/**\n * Get all table names in a schema\n */\nexport function getTablesInSchema(content: string, schema: string): string[] {\n const tables: string[] = [];\n\n // Find the schema section\n const schemaRegex = new RegExp(`${schema}:\\\\s*\\\\{[\\\\s\\\\S]*?Tables:\\\\s*\\\\{([\\\\s\\\\S]*?)\\\\}\\\\s*Views:`, 'g');\n const schemaMatch = schemaRegex.exec(content);\n if (!schemaMatch) return tables;\n const tablesContent = schemaMatch[1];\n\n // Find table names (they're at the start of each table definition)\n const tableNameRegex = /^\\s*(\\w+):\\s*\\{/gm;\n let match;\n while ((match = tableNameRegex.exec(tablesContent)) !== null) {\n tables.push(match[1]);\n }\n return tables;\n}","/**\n * Output templates for PowerSync schema generation\n */\n\nimport type { ParsedTable } from './parser.js';\nexport interface IndexDefinition {\n name: string;\n columns: string[];\n}\n\n/**\n * Convert table name to snake_case for index naming\n */\nfunction toSnakeCase(str: string): string {\n return str.replace(/([a-z])([A-Z])/g, '$1_$2').toLowerCase();\n}\n\n/**\n * Generate index definitions for a table based on column patterns\n *\n * @param tableName - The table name (PascalCase)\n * @param columns - Array of column names in the table\n * @param indexPatterns - Regex patterns to match against column names\n * @param additionalColumns - Specific column names to always index\n * @returns Array of index definitions\n */\nexport function generateIndexDefinitions(tableName: string, columns: string[], indexPatterns: string[], additionalColumns: string[] = []): IndexDefinition[] {\n const indexes: IndexDefinition[] = [];\n const snakeTableName = toSnakeCase(tableName);\n\n // Combine pattern matching and explicit columns\n const columnsToIndex = new Set<string>();\n\n // Pre-compile regex patterns with error handling\n const compiledPatterns: RegExp[] = [];\n for (const pattern of indexPatterns) {\n try {\n compiledPatterns.push(new RegExp(pattern));\n } catch {\n console.warn(`Warning: Invalid index pattern regex \"${pattern}\" - skipping`);\n }\n }\n\n // Match columns against patterns\n for (const column of columns) {\n // Skip 'id' column - it's the primary key and already indexed\n if (column === 'id') continue;\n for (const regex of compiledPatterns) {\n if (regex.test(column)) {\n columnsToIndex.add(column);\n break;\n }\n }\n }\n\n // Add explicitly specified columns (if they exist in the table)\n for (const column of additionalColumns) {\n if (columns.includes(column) && column !== 'id') {\n columnsToIndex.add(column);\n }\n }\n\n // Create index definitions\n for (const column of columnsToIndex) {\n const snakeColumn = toSnakeCase(column);\n indexes.push({\n name: `idx_${snakeTableName}_${snakeColumn}`,\n columns: [column]\n });\n }\n\n // Sort by index name for deterministic output\n indexes.sort((a, b) => a.name.localeCompare(b.name));\n return indexes;\n}\n\n/**\n * File header template\n */\nexport function generateHeader(typesPath: string): string {\n return `/**\n * PowerSync Schema Definition\n *\n * AUTO-GENERATED from ${typesPath}\n * Run: npx @pol-studios/powersync generate-schema\n *\n * DO NOT EDIT MANUALLY - changes will be overwritten\n */\n\nimport { column, Schema, Table } from \"@powersync/react-native\";\n`;\n}\n\n/**\n * Format indexes object for output (PowerSync SDK v1.32.0+ format)\n * Changed from array format [{ name, columns }] to object format { name: columns }\n */\nfunction formatIndexes(indexes: IndexDefinition[]): string {\n if (indexes.length === 0) return '';\n const indexLines = indexes.map(idx => {\n const columnsStr = idx.columns.map(c => `'${c}'`).join(', ');\n return ` '${idx.name}': [${columnsStr}],`;\n });\n return `indexes: {\\n${indexLines.join('\\n')}\\n }`;\n}\n\n/**\n * Generate the table definition for a parsed table\n */\nexport function generateTableDefinition(table: ParsedTable, columnDefs: string[], indexes: IndexDefinition[] = []): string {\n // Use alias if provided, otherwise use table name\n const effectiveName = table.config.alias ?? table.name;\n if (columnDefs.length === 0) {\n return `// ${effectiveName} - no syncable columns found`;\n }\n\n // Build options object\n const optionsParts: string[] = [];\n if (table.config.trackMetadata) {\n optionsParts.push('trackMetadata: true');\n }\n if (indexes.length > 0) {\n optionsParts.push(formatIndexes(indexes));\n }\n const optionsStr = optionsParts.length > 0 ? `, {\\n ${optionsParts.join(',\\n ')}\\n}` : '';\n return `const ${effectiveName} = new Table({\n${columnDefs.join('\\n')}\n}${optionsStr});`;\n}\n\n/**\n * Generate the table definition for a local-only table (not synced through PowerSync)\n */\nexport function generateLocalOnlyTableDefinition(table: ParsedTable, columnDefs: string[], indexes: IndexDefinition[] = []): string {\n // Use alias if provided, otherwise use table name\n const effectiveName = table.config.alias ?? table.name;\n if (columnDefs.length === 0) {\n return `// ${effectiveName} - no syncable columns found`;\n }\n\n // Build options object - always include localOnly: true\n const optionsParts: string[] = ['localOnly: true'];\n if (indexes.length > 0) {\n optionsParts.push(formatIndexes(indexes));\n }\n const optionsStr = `, {\\n ${optionsParts.join(',\\n ')}\\n}`;\n return `// Local-only table (not synced)\nconst ${effectiveName} = new Table({\n${columnDefs.join('\\n')}\n}${optionsStr});`;\n}\n\n/**\n * Generate the schema export section\n */\nexport function generateSchemaExport(tables: ParsedTable[]): string {\n // Use alias if provided, otherwise use table name\n const tableNames = tables.map(t => t.config.alias ?? t.name);\n return `// ============================================================================\n// SCHEMA EXPORT\n// ============================================================================\n\n// NOTE: photo_attachments is NOT included here.\n// The AttachmentQueue from @powersync/attachments creates and manages\n// its own internal SQLite table (not a view) during queue.init().\n// This allows INSERT/UPDATE operations to work correctly.\n\nexport const AppSchema = new Schema({\n${tableNames.map(name => ` ${name},`).join('\\n')}\n});\n\nexport type Database = (typeof AppSchema)[\"types\"];`;\n}\n\n/**\n * Generate schema mapping utilities\n */\nexport function generateSchemaMapping(tables: ParsedTable[], schemas: string[]): string {\n // Group tables by non-public schemas (use alias if provided)\n const schemaGroups = new Map<string, string[]>();\n for (const schema of schemas) {\n if (schema !== 'public') {\n schemaGroups.set(schema, []);\n }\n }\n for (const table of tables) {\n const effectiveName = table.config.alias ?? table.name;\n if (table.schema !== 'public' && schemaGroups.has(table.schema)) {\n schemaGroups.get(table.schema)!.push(effectiveName);\n }\n }\n const sections: string[] = [`// ============================================================================\n// SCHEMA MAPPING FOR CONNECTOR\n// ============================================================================`];\n\n // Generate constants for each non-public schema\n for (const [schema, tableNames] of schemaGroups) {\n if (tableNames.length > 0) {\n const constName = `${schema.toUpperCase()}_SCHEMA_TABLES`;\n sections.push(`\n// Tables in the '${schema}' schema (need .schema('${schema}') in Supabase queries)\nexport const ${constName} = new Set([\n${tableNames.map(name => ` \"${name}\",`).join('\\n')}\n]);`);\n }\n }\n\n // Generate helper function\n const schemaChecks = Array.from(schemaGroups.entries()).filter(([, names]) => names.length > 0).map(([schema]) => {\n const constName = `${schema.toUpperCase()}_SCHEMA_TABLES`;\n return ` if (${constName}.has(tableName)) return \"${schema}\";`;\n });\n if (schemaChecks.length > 0) {\n sections.push(`\n/**\n * Get the Supabase schema for a table\n */\nexport function getTableSchema(tableName: string): ${schemas.map(s => `\"${s}\"`).join(' | ')} {\n${schemaChecks.join('\\n')}\n return \"public\";\n}`);\n } else {\n sections.push(`\n/**\n * Get the Supabase schema for a table\n */\nexport function getTableSchema(tableName: string): \"public\" {\n return \"public\";\n}`);\n }\n return sections.join('\\n');\n}\n\n/**\n * Generate the FK detection utility (helpful for consumers)\n */\nexport function generateFKUtility(): string {\n return `\n// ============================================================================\n// FOREIGN KEY UTILITIES\n// ============================================================================\n\n/**\n * Check if a column name represents a foreign key reference\n * Convention: columns ending in 'Id' are foreign keys (e.g., projectId -> Project table)\n */\nexport function isForeignKeyColumn(columnName: string): boolean {\n return columnName.endsWith('Id') && columnName !== 'id';\n}\n\n/**\n * Get the referenced table name from a foreign key column\n * e.g., 'projectId' -> 'Project', 'equipmentFixtureUnitId' -> 'EquipmentFixtureUnit'\n */\nexport function getForeignKeyTable(columnName: string): string | null {\n if (!isForeignKeyColumn(columnName)) return null;\n // Remove 'Id' suffix and capitalize first letter\n const baseName = columnName.slice(0, -2);\n return baseName.charAt(0).toUpperCase() + baseName.slice(1);\n}`;\n}\n\n/**\n * Generate complete output file\n */\nexport function generateOutputFile(tables: ParsedTable[], tableDefs: string[], schemas: string[], typesPath: string): string {\n return `${generateHeader(typesPath)}\n\n// ============================================================================\n// TABLE DEFINITIONS\n// ============================================================================\n\n${tableDefs.join('\\n\\n')}\n\n${generateSchemaExport(tables)}\n\n${generateSchemaMapping(tables, ['public', ...schemas.filter(s => s !== 'public')])}\n${generateFKUtility()}\n`;\n}","/**\n * Foreign Key Dependency Detection\n *\n * Analyzes parsed tables to detect FK relationships and determine\n * optimal upload order for offline-first sync.\n */\n\nimport type { ParsedTable } from './parser.js';\nexport interface FKDependency {\n /** Table containing the FK column */\n table: string;\n /** FK column name (e.g., 'projectId') */\n column: string;\n /** Referenced table name (e.g., 'Project') */\n referencedTable: string;\n}\nexport interface DependencyGraph {\n /** Map of table -> tables it depends on (has FK references to) */\n dependencies: Map<string, string[]>;\n /** Map of table -> tables that depend on it (have FKs referencing this table) */\n dependents: Map<string, string[]>;\n /** Topologically sorted table names for optimal upload order */\n uploadOrder: string[];\n /** All detected FK relationships */\n fkRelationships: FKDependency[];\n}\n\n/**\n * Convert a FK column name to its referenced table name\n * Convention: columns ending in 'Id' reference the PascalCase table\n * e.g., projectId -> Project, equipmentUnitId -> EquipmentUnit\n */\nexport function fkColumnToTableName(columnName: string): string | null {\n if (!columnName.endsWith('Id') || columnName === 'id') {\n return null;\n }\n // Remove 'Id' suffix and capitalize first letter\n const baseName = columnName.slice(0, -2);\n return baseName.charAt(0).toUpperCase() + baseName.slice(1);\n}\n\n/**\n * Detect FK dependencies from parsed tables\n *\n * Uses naming convention: columns ending in 'Id' reference the PascalCase table\n * Only considers references to tables that are in the provided list (ignores external references)\n */\nexport function detectFKDependencies(tables: ParsedTable[]): DependencyGraph {\n const tableNames = new Set(tables.map(t => t.name));\n const dependencies = new Map<string, string[]>();\n const dependents = new Map<string, string[]>();\n const fkRelationships: FKDependency[] = [];\n\n // Initialize maps for all tables\n for (const table of tables) {\n dependencies.set(table.name, []);\n dependents.set(table.name, []);\n }\n\n // Detect FK relationships\n for (const table of tables) {\n for (const [columnName] of table.columns) {\n const referencedTable = fkColumnToTableName(columnName);\n\n // Only track references to tables in our schema\n if (referencedTable && tableNames.has(referencedTable)) {\n // This table depends on the referenced table\n const tableDeps = dependencies.get(table.name) || [];\n if (!tableDeps.includes(referencedTable)) {\n tableDeps.push(referencedTable);\n dependencies.set(table.name, tableDeps);\n }\n\n // The referenced table has this table as a dependent\n const refDeps = dependents.get(referencedTable) || [];\n if (!refDeps.includes(table.name)) {\n refDeps.push(table.name);\n dependents.set(referencedTable, refDeps);\n }\n\n // Record the FK relationship\n fkRelationships.push({\n table: table.name,\n column: columnName,\n referencedTable\n });\n }\n }\n }\n\n // Calculate upload order via topological sort\n const uploadOrder = getUploadOrder({\n dependencies\n });\n return {\n dependencies,\n dependents,\n uploadOrder,\n fkRelationships\n };\n}\n\n/**\n * Get optimal upload order using Kahn's topological sort algorithm\n *\n * Tables with no dependencies are uploaded first, then tables that depend on them, etc.\n * This ensures that when a row references another table, the referenced row exists first.\n */\nexport function getUploadOrder(graph: Pick<DependencyGraph, 'dependencies'>): string[] {\n const result: string[] = [];\n const inDegree = new Map<string, number>();\n const adjList = new Map<string, string[]>();\n\n // Initialize in-degree (number of dependencies) for each table\n for (const [table, deps] of graph.dependencies) {\n inDegree.set(table, deps.length);\n adjList.set(table, []);\n }\n\n // Build adjacency list (reverse of dependencies - who depends on this table)\n for (const [table, deps] of graph.dependencies) {\n for (const dep of deps) {\n const list = adjList.get(dep) || [];\n list.push(table);\n adjList.set(dep, list);\n }\n }\n\n // Start with tables that have no dependencies\n const queue: string[] = [];\n for (const [table, degree] of inDegree) {\n if (degree === 0) {\n queue.push(table);\n }\n }\n\n // Sort queue alphabetically for deterministic output\n queue.sort();\n\n // Process queue\n while (queue.length > 0) {\n const table = queue.shift()!;\n result.push(table);\n\n // Reduce in-degree for all tables that depend on this one\n const dependentTables = adjList.get(table) || [];\n for (const dependent of dependentTables) {\n const newDegree = (inDegree.get(dependent) || 0) - 1;\n inDegree.set(dependent, newDegree);\n if (newDegree === 0) {\n queue.push(dependent);\n // Keep queue sorted for deterministic output\n queue.sort();\n }\n }\n }\n\n // Check for cycles (if result doesn't include all tables)\n if (result.length < graph.dependencies.size) {\n // There's a cycle - just append remaining tables alphabetically\n const remaining = [...graph.dependencies.keys()].filter(t => !result.includes(t)).sort();\n result.push(...remaining);\n }\n return result;\n}\n\n/**\n * Get tables that have no dependencies (root tables)\n * These are typically reference/lookup tables like User, Project, etc.\n */\nexport function getRootTables(graph: DependencyGraph): string[] {\n const roots: string[] = [];\n for (const [table, deps] of graph.dependencies) {\n if (deps.length === 0) {\n roots.push(table);\n }\n }\n return roots.sort();\n}\n\n/**\n * Get tables that have no dependents (leaf tables)\n * These are typically transaction/event tables that reference other tables\n */\nexport function getLeafTables(graph: DependencyGraph): string[] {\n const leaves: string[] = [];\n for (const [table, deps] of graph.dependents) {\n if (deps.length === 0) {\n leaves.push(table);\n }\n }\n return leaves.sort();\n}\n\n/**\n * Format the dependency graph as a human-readable string\n */\nexport function formatDependencyGraph(graph: DependencyGraph): string {\n const lines: string[] = [];\n lines.push('FK Dependencies:');\n for (const fk of graph.fkRelationships) {\n lines.push(` ${fk.table}.${fk.column} -> ${fk.referencedTable}`);\n }\n if (graph.fkRelationships.length === 0) {\n lines.push(' (none detected)');\n }\n lines.push('');\n lines.push('Upload Order (topological):');\n graph.uploadOrder.forEach((table, i) => {\n const deps = graph.dependencies.get(table) || [];\n const depStr = deps.length > 0 ? ` (depends on: ${deps.join(', ')})` : ' (root)';\n lines.push(` ${i + 1}. ${table}${depStr}`);\n });\n return lines.join('\\n');\n}"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../../src/generator/config.ts","../../src/generator/generator.ts","../../src/generator/parser.ts","../../src/generator/templates.ts","../../src/generator/fk-dependencies.ts"],"sourcesContent":["/**\n * Configuration types and helpers for PowerSync schema generator\n */\n\nexport interface TableConfig {\n /** Table name (PascalCase as it appears in database.types.ts) */\n name: string;\n /** Schema name (defaults to 'public') */\n schema?: string;\n /** Enable ps_crud timestamp tracking for optimistic UI updates */\n trackMetadata?: boolean;\n /**\n * Sync the primary key column (normally skipped as PowerSync handles it internally).\n *\n * Use this for tables with integer PKs that are referenced by FKs in other tables.\n * Example: `Group.id` is referenced by `UserGroup.groupId`, so Group needs `syncPrimaryKey: true`\n * to ensure the integer ID is available for client-side joins.\n */\n syncPrimaryKey?: boolean;\n /** @deprecated Use `syncPrimaryKey` instead */\n includeId?: boolean;\n /** Columns to skip for this specific table (in addition to global skipColumns) */\n skipColumns?: string[];\n /** Only include these columns (overrides skipColumns if specified) */\n onlyColumns?: string[];\n /** Alias for the table in PowerSync schema (for conflicting names across schemas) */\n alias?: string;\n /** Table is local-only (not synced through PowerSync) */\n localOnly?: boolean;\n}\nexport interface GeneratorConfig {\n /** Path to Supabase-generated database.types.ts file */\n typesPath: string;\n /** Output path for generated PowerSync schema */\n outputPath: string;\n /** Tables to include in the PowerSync schema */\n tables: TableConfig[];\n /** Columns to always skip (in addition to defaults like 'id') */\n skipColumns?: string[];\n /** Column name patterns that should use column.real for decimal values */\n decimalPatterns?: string[];\n /** Additional schemas to track (besides 'public' which is the default) */\n schemas?: string[];\n /** Generate indexes for FK and common columns (default: true) */\n autoIndexes?: boolean;\n /** Additional columns to index (exact column names) */\n indexColumns?: string[];\n /** Column patterns that should be indexed (regex patterns) */\n indexPatterns?: string[];\n}\n\n/**\n * Define a PowerSync generator configuration with type safety\n */\nexport function defineConfig(config: GeneratorConfig): GeneratorConfig {\n return config;\n}\n\n/**\n * Default columns that are skipped during generation\n */\nexport const DEFAULT_SKIP_COLUMNS = ['id',\n// PowerSync handles id automatically\n// Legacy numeric ID columns - typically not needed after UUID migration\n'legacyId'];\n\n/**\n * Default column name patterns that indicate decimal values\n */\nexport const DEFAULT_DECIMAL_PATTERNS = ['hours', 'watts', 'voltage', 'rate', 'amount', 'price', 'cost', 'total'];\n\n/**\n * Default column patterns that should be indexed\n * These are regex patterns matched against column names\n */\nexport const DEFAULT_INDEX_PATTERNS = ['Id$',\n// FK columns ending in Id (e.g., projectId, userId)\n'^createdAt$', '^updatedAt$', '^status$', '^type$'];\n\n/**\n * Required authentication/access control tables for offline auth\n * These tables are needed for proper offline access control\n */\nexport interface RequiredAuthTable {\n /** Table name (PascalCase) */\n name: string;\n /** Schema name */\n schema: string;\n /** Whether this table requires syncPrimaryKey to be true */\n requiresSyncPrimaryKey?: boolean;\n}\nexport const REQUIRED_AUTH_TABLES: RequiredAuthTable[] = [{\n name: 'UserAccess',\n schema: 'core'\n}, {\n name: 'UserGroup',\n schema: 'core'\n}, {\n name: 'GroupAccessKey',\n schema: 'core',\n requiresSyncPrimaryKey: true\n}, {\n name: 'Group',\n schema: 'core',\n requiresSyncPrimaryKey: true\n}];","/**\n * PowerSync schema generator\n *\n * Converts Supabase database.types.ts into PowerSync schema definitions\n */\n\nimport * as fs from 'fs';\nimport * as path from 'path';\nimport type { GeneratorConfig, TableConfig } from './config.js';\nimport { DEFAULT_SKIP_COLUMNS, DEFAULT_DECIMAL_PATTERNS, DEFAULT_INDEX_PATTERNS, REQUIRED_AUTH_TABLES } from './config.js';\nimport { parseTypesFile, type ParsedTable } from './parser.js';\nimport { generateTableDefinition, generateLocalOnlyTableDefinition, generateOutputFile, generateIndexDefinitions, type IndexDefinition } from './templates.js';\nimport { detectFKDependencies, type DependencyGraph } from './fk-dependencies.js';\nexport interface ColumnMapping {\n type: 'column.text' | 'column.integer' | 'column.real';\n isEnum?: boolean;\n isBoolean?: boolean;\n isJson?: boolean;\n}\nexport interface GenerateResult {\n success: boolean;\n tablesGenerated: number;\n outputPath: string;\n errors: string[];\n warnings: string[];\n /** Generated output (included when dryRun is true) */\n output?: string;\n /** Number of indexes generated */\n indexesGenerated?: number;\n /** FK dependency graph (when detected) */\n dependencyGraph?: DependencyGraph;\n}\n\n/**\n * Map TypeScript types to PowerSync column types\n */\nexport function mapTypeToPowerSync(tsType: string, columnName: string, decimalPatterns: string[]): ColumnMapping | null {\n // Clean up the type (remove nullability)\n const cleanType = tsType.trim().replace(/\\s*\\|\\s*null/g, '');\n\n // JSON types -> store as TEXT (will be parsed/stringified by type-transformer)\n if (cleanType.includes('Json')) {\n return {\n type: 'column.text',\n isJson: true\n };\n }\n\n // Skip complex types that can't be stored in SQLite\n if (cleanType.includes('unknown') || cleanType.includes('{')) {\n return null;\n }\n\n // Array types - skip\n if (cleanType.includes('[]')) {\n return null;\n }\n\n // Boolean -> integer (0/1)\n if (cleanType === 'boolean') {\n return {\n type: 'column.integer',\n isBoolean: true\n };\n }\n\n // Number types\n if (cleanType === 'number') {\n // Use real for columns that might have decimals\n if (decimalPatterns.some(pattern => columnName.toLowerCase().includes(pattern.toLowerCase()))) {\n return {\n type: 'column.real'\n };\n }\n return {\n type: 'column.integer'\n };\n }\n\n // String types\n if (cleanType === 'string') {\n return {\n type: 'column.text'\n };\n }\n\n // Enum types (Database[\"schema\"][\"Enums\"][\"EnumName\"]) -> store as text\n if (cleanType.includes('Database[') && cleanType.includes('Enums')) {\n return {\n type: 'column.text',\n isEnum: true\n };\n }\n\n // Default to text for unknown types (likely enums or other string-like types)\n return {\n type: 'column.text'\n };\n}\n\n/**\n * Generate column definitions for a table\n */\nexport function generateColumnDefs(table: ParsedTable, decimalPatterns: string[]): string[] {\n const columnDefs: string[] = [];\n for (const [columnName, tsType] of table.columns) {\n const mapping = mapTypeToPowerSync(tsType, columnName, decimalPatterns);\n if (mapping) {\n // Add comment for boolean, enum, and json columns\n let comment = '';\n if (mapping.isBoolean) {\n comment = ' // boolean stored as 0/1';\n } else if (mapping.isEnum) {\n comment = ' // enum stored as text';\n } else if (mapping.isJson) {\n comment = ' // JSON stored as text';\n }\n columnDefs.push(` ${columnName}: ${mapping.type},${comment}`);\n }\n }\n return columnDefs;\n}\n\n/**\n * Validate that required auth tables are included in config\n * Returns warnings for missing tables or misconfigured tables\n */\nexport function validateAuthTables(tables: TableConfig[]): string[] {\n const warnings: string[] = [];\n for (const authTable of REQUIRED_AUTH_TABLES) {\n const configTable = tables.find(t => t.name === authTable.name && (t.schema ?? 'public') === authTable.schema);\n if (!configTable) {\n warnings.push(`Missing required auth table: ${authTable.schema}.${authTable.name} - offline access control may not work correctly`);\n } else if (authTable.requiresSyncPrimaryKey && !configTable.syncPrimaryKey) {\n warnings.push(`Auth table ${authTable.schema}.${authTable.name} should have syncPrimaryKey: true for proper FK references`);\n }\n }\n return warnings;\n}\n\n/**\n * Validate FK references to ensure all referenced tables are in the config\n * Returns warnings for missing FK targets\n */\nexport function validateFKReferences(dependencyGraph: DependencyGraph, configuredTables: Set<string>): string[] {\n const warnings: string[] = [];\n for (const fk of dependencyGraph.fkRelationships) {\n if (!configuredTables.has(fk.referencedTable)) {\n warnings.push(`FK reference ${fk.table}.${fk.column} references table '${fk.referencedTable}' which is not in the config`);\n }\n }\n return warnings;\n}\n\n/**\n * Generate PowerSync schema from configuration\n */\nexport async function generateSchema(config: GeneratorConfig, options?: {\n cwd?: string;\n verbose?: boolean;\n dryRun?: boolean;\n}): Promise<GenerateResult> {\n const cwd = options?.cwd ?? process.cwd();\n const verbose = options?.verbose ?? false;\n const dryRun = options?.dryRun ?? false;\n const result: GenerateResult = {\n success: false,\n tablesGenerated: 0,\n outputPath: '',\n errors: [],\n warnings: []\n };\n\n // Resolve paths relative to cwd\n const typesPath = path.isAbsolute(config.typesPath) ? config.typesPath : path.resolve(cwd, config.typesPath);\n const outputPath = path.isAbsolute(config.outputPath) ? config.outputPath : path.resolve(cwd, config.outputPath);\n result.outputPath = outputPath;\n\n // Validate required auth tables\n const authWarnings = validateAuthTables(config.tables);\n result.warnings.push(...authWarnings);\n\n // Check if types file exists\n if (!fs.existsSync(typesPath)) {\n result.errors.push(`Types file not found: ${typesPath}`);\n return result;\n }\n\n // Read types file\n if (verbose) {\n console.log(`Reading types from: ${typesPath}`);\n }\n const typesContent = fs.readFileSync(typesPath, 'utf-8');\n\n // Build skip columns set\n const skipColumns = new Set([...DEFAULT_SKIP_COLUMNS, ...(config.skipColumns ?? [])]);\n\n // Build decimal patterns\n const decimalPatterns = [...DEFAULT_DECIMAL_PATTERNS, ...(config.decimalPatterns ?? [])];\n\n // Parse tables from types file\n const parsedTables = parseTypesFile(typesContent, config.tables, skipColumns);\n\n // Check for tables that weren't found\n for (const tableConfig of config.tables) {\n const found = parsedTables.some(t => t.name === tableConfig.name);\n if (!found) {\n result.warnings.push(`Table '${tableConfig.name}' not found in schema '${tableConfig.schema ?? 'public'}'`);\n }\n }\n if (parsedTables.length === 0) {\n result.errors.push('No tables were parsed successfully');\n return result;\n }\n\n // Build index patterns (auto-indexes enabled by default)\n const autoIndexes = config.autoIndexes ?? true;\n const indexPatterns = autoIndexes ? [...DEFAULT_INDEX_PATTERNS, ...(config.indexPatterns ?? [])] : config.indexPatterns ?? [];\n const indexColumns = config.indexColumns ?? [];\n\n // Detect FK dependencies\n const dependencyGraph = detectFKDependencies(parsedTables);\n result.dependencyGraph = dependencyGraph;\n\n // Validate FK references - warn if any FK targets a table not in config\n const configuredTableNames = new Set(config.tables.map(t => t.name));\n const fkWarnings = validateFKReferences(dependencyGraph, configuredTableNames);\n result.warnings.push(...fkWarnings);\n if (verbose && dependencyGraph.fkRelationships.length > 0) {\n console.log(`\\nFK Dependencies detected: ${dependencyGraph.fkRelationships.length}`);\n for (const fk of dependencyGraph.fkRelationships) {\n console.log(` ${fk.table}.${fk.column} -> ${fk.referencedTable}`);\n }\n console.log(`\\nRecommended upload order:`);\n dependencyGraph.uploadOrder.forEach((table, i) => {\n console.log(` ${i + 1}. ${table}`);\n });\n console.log('');\n }\n\n // Generate table definitions - separate synced and local-only tables\n const syncedTableDefs: string[] = [];\n const localOnlyTableDefs: string[] = [];\n let totalIndexes = 0;\n for (const table of parsedTables) {\n const isLocalOnly = table.config.localOnly ?? false;\n const tableAlias = table.config.alias;\n if (verbose) {\n const syncPK = table.config.syncPrimaryKey || table.config.includeId;\n const flags = [table.config.trackMetadata ? '[trackMetadata]' : '', syncPK ? '[syncPrimaryKey]' : '', isLocalOnly ? '[localOnly]' : '', tableAlias ? `[alias: ${tableAlias}]` : ''].filter(Boolean).join(' ');\n console.log(`Processing ${table.schema}.${table.name} (${table.columns.size} columns)${flags ? ' ' + flags : ''}`);\n }\n const columnDefs = generateColumnDefs(table, decimalPatterns);\n if (columnDefs.length === 0) {\n result.warnings.push(`Table '${table.name}' has no syncable columns`);\n continue;\n }\n\n // Generate indexes for this table (use alias for index naming if provided)\n const effectiveTableName = tableAlias ?? table.name;\n const columnNames = [...table.columns.keys()];\n const indexes = indexPatterns.length > 0 || indexColumns.length > 0 ? generateIndexDefinitions(effectiveTableName, columnNames, indexPatterns, indexColumns) : [];\n totalIndexes += indexes.length;\n if (verbose && indexes.length > 0) {\n console.log(` Indexes: ${indexes.map(i => i.name).join(', ')}`);\n }\n\n // Generate table definition based on localOnly flag\n if (isLocalOnly) {\n localOnlyTableDefs.push(generateLocalOnlyTableDefinition(table, columnDefs, indexes));\n } else {\n syncedTableDefs.push(generateTableDefinition(table, columnDefs, indexes));\n }\n }\n\n // Combine synced and local-only table definitions\n const tableDefs = [...syncedTableDefs, ...localOnlyTableDefs];\n result.indexesGenerated = totalIndexes;\n\n // Collect unique schemas\n const schemas = [...new Set(config.tables.map(t => t.schema ?? 'public'))];\n\n // Generate output file content\n const relativePath = path.relative(cwd, typesPath);\n // Filter tables that were successfully generated (check for both name and alias)\n const generatedTables = parsedTables.filter(t => {\n const effectiveName = t.config.alias ?? t.name;\n return tableDefs.some(def => def.includes(`const ${effectiveName} =`));\n });\n const output = generateOutputFile(generatedTables, tableDefs, schemas, relativePath);\n\n // If dry-run, return output without writing\n if (dryRun) {\n result.success = true;\n result.tablesGenerated = tableDefs.length;\n result.output = output;\n return result;\n }\n\n // Ensure output directory exists\n const outputDir = path.dirname(outputPath);\n if (!fs.existsSync(outputDir)) {\n fs.mkdirSync(outputDir, {\n recursive: true\n });\n }\n\n // Write output file\n fs.writeFileSync(outputPath, output);\n result.success = true;\n result.tablesGenerated = tableDefs.length;\n return result;\n}","/**\n * Parser for Supabase database.types.ts files\n *\n * Extracts table definitions and column types from the generated TypeScript types\n */\n\nimport type { TableConfig } from './config.js';\nexport interface ColumnInfo {\n name: string;\n tsType: string;\n isNullable: boolean;\n}\nexport interface ParsedTable {\n name: string;\n schema: string;\n columns: Map<string, string>;\n config: TableConfig;\n}\nexport interface ParseOptions {\n /** Columns to skip */\n skipColumns: Set<string>;\n /**\n * Include the id column (normally skipped).\n * Use for tables with integer PKs referenced by FKs in other tables.\n */\n syncPrimaryKey?: boolean;\n /** @deprecated Use `syncPrimaryKey` instead */\n includeId?: boolean;\n /** Only include these columns (overrides skipColumns if specified) */\n onlyColumns?: string[];\n}\n\n/**\n * Parse the Row type from a table definition and extract columns\n */\nexport function parseRowType(tableContent: string, options: ParseOptions): Map<string, string> {\n const columns = new Map<string, string>();\n\n // Find the Row block - handles nested braces in type definitions\n const rowMatch = tableContent.match(/Row:\\s*\\{([^}]+(?:\\{[^}]*\\}[^}]*)*)\\}/s);\n if (!rowMatch) return columns;\n const rowContent = rowMatch[1];\n\n // syncPrimaryKey takes precedence, with includeId as fallback for backwards compat\n const includePrimaryKey = options.syncPrimaryKey ?? options.includeId ?? false;\n\n // If onlyColumns is specified, use it as a whitelist (overrides skipColumns)\n const onlyColumnsSet = options.onlyColumns ? new Set(options.onlyColumns) : null;\n\n // Parse each column: \"columnName: type\" or \"columnName?: type\"\n const columnRegex = /(\\w+)\\??:\\s*([^,\\n]+)/g;\n let match;\n while ((match = columnRegex.exec(rowContent)) !== null) {\n const [, columnName, columnType] = match;\n\n // Determine if column should be included\n let shouldInclude: boolean;\n if (onlyColumnsSet) {\n // onlyColumns mode: only include explicitly listed columns\n // Exception: include 'id' if syncPrimaryKey is true\n shouldInclude = onlyColumnsSet.has(columnName) || includePrimaryKey && columnName === 'id';\n } else {\n // skipColumns mode: include unless explicitly skipped\n // Exception: include 'id' if syncPrimaryKey is true\n const isSkipped = options.skipColumns.has(columnName);\n shouldInclude = !isSkipped || includePrimaryKey && columnName === 'id';\n }\n if (shouldInclude) {\n columns.set(columnName, columnType.trim());\n }\n }\n return columns;\n}\n\n/**\n * Escape special regex characters in a string\n */\nfunction escapeRegex(str: string): string {\n return str.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&');\n}\n\n/**\n * Extract a table definition from the database.types.ts content\n *\n * Uses bracket-counting to properly handle nested arrays in Relationships\n * (e.g., columns: [\"parentId\"] inside relationship objects)\n */\nexport function extractTableDef(content: string, tableName: string, schema: string): string | null {\n // Escape special characters in schema and table names for regex safety\n const escapedSchema = escapeRegex(schema);\n const escapedTableName = escapeRegex(tableName);\n\n // Find the schema section\n const schemaRegex = new RegExp(`${escapedSchema}:\\\\s*\\\\{[\\\\s\\\\S]*?Tables:\\\\s*\\\\{`, 'g');\n const schemaMatch = schemaRegex.exec(content);\n if (!schemaMatch) return null;\n const startIndex = schemaMatch.index;\n const searchContent = content.slice(startIndex);\n\n // Find the start of this specific table\n // Use negative lookbehind (?<![A-Za-z]) to avoid matching table names that are\n // substrings of other names (e.g., \"Tag\" in \"CommentTag\")\n const tableStartRegex = new RegExp(`(?<![A-Za-z])${escapedTableName}:\\\\s*\\\\{`, 'g');\n const tableStartMatch = tableStartRegex.exec(searchContent);\n if (!tableStartMatch) return null;\n\n // Use bracket counting to find the matching closing brace\n const tableStartIndex = tableStartMatch.index;\n const openBraceIndex = tableStartMatch.index + tableStartMatch[0].length - 1;\n let braceCount = 1;\n let i = openBraceIndex + 1;\n while (i < searchContent.length && braceCount > 0) {\n const char = searchContent[i];\n if (char === '{') braceCount++;else if (char === '}') braceCount--;\n i++;\n }\n if (braceCount !== 0) return null;\n return searchContent.slice(tableStartIndex, i);\n}\n\n/**\n * Parse a database.types.ts file and extract specified tables\n */\nexport function parseTypesFile(content: string, tables: TableConfig[], globalSkipColumns: Set<string>): ParsedTable[] {\n const parsedTables: ParsedTable[] = [];\n for (const tableConfig of tables) {\n const {\n name,\n schema = 'public',\n syncPrimaryKey,\n includeId,\n skipColumns: tableSkipColumns,\n onlyColumns\n } = tableConfig;\n const tableDef = extractTableDef(content, name, schema);\n if (!tableDef) {\n continue;\n }\n\n // Merge global and per-table skipColumns\n const mergedSkipColumns = new Set([...globalSkipColumns, ...(tableSkipColumns ?? [])]);\n const columns = parseRowType(tableDef, {\n skipColumns: mergedSkipColumns,\n syncPrimaryKey,\n includeId,\n onlyColumns\n });\n if (columns.size > 0) {\n parsedTables.push({\n name,\n schema,\n columns,\n config: tableConfig\n });\n }\n }\n return parsedTables;\n}\n\n/**\n * Get all available schemas from the types file\n */\nexport function getAvailableSchemas(content: string): string[] {\n const schemas: string[] = [];\n const schemaRegex = /(\\w+):\\s*\\{[\\s\\S]*?Tables:\\s*\\{/g;\n let match;\n while ((match = schemaRegex.exec(content)) !== null) {\n schemas.push(match[1]);\n }\n return schemas;\n}\n\n/**\n * Get all table names in a schema\n */\nexport function getTablesInSchema(content: string, schema: string): string[] {\n const tables: string[] = [];\n\n // Find the schema section\n const schemaRegex = new RegExp(`${schema}:\\\\s*\\\\{[\\\\s\\\\S]*?Tables:\\\\s*\\\\{([\\\\s\\\\S]*?)\\\\}\\\\s*Views:`, 'g');\n const schemaMatch = schemaRegex.exec(content);\n if (!schemaMatch) return tables;\n const tablesContent = schemaMatch[1];\n\n // Find table names (they're at the start of each table definition)\n const tableNameRegex = /^\\s*(\\w+):\\s*\\{/gm;\n let match;\n while ((match = tableNameRegex.exec(tablesContent)) !== null) {\n tables.push(match[1]);\n }\n return tables;\n}","/**\n * Output templates for PowerSync schema generation\n */\n\nimport type { ParsedTable } from './parser.js';\nexport interface IndexDefinition {\n name: string;\n columns: string[];\n}\n\n/**\n * Convert table name to snake_case for index naming\n */\nfunction toSnakeCase(str: string): string {\n return str.replace(/([a-z])([A-Z])/g, '$1_$2').toLowerCase();\n}\n\n/**\n * Generate index definitions for a table based on column patterns\n *\n * @param tableName - The table name (PascalCase)\n * @param columns - Array of column names in the table\n * @param indexPatterns - Regex patterns to match against column names\n * @param additionalColumns - Specific column names to always index\n * @returns Array of index definitions\n */\nexport function generateIndexDefinitions(tableName: string, columns: string[], indexPatterns: string[], additionalColumns: string[] = []): IndexDefinition[] {\n const indexes: IndexDefinition[] = [];\n const snakeTableName = toSnakeCase(tableName);\n\n // Combine pattern matching and explicit columns\n const columnsToIndex = new Set<string>();\n\n // Pre-compile regex patterns with error handling\n const compiledPatterns: RegExp[] = [];\n for (const pattern of indexPatterns) {\n try {\n compiledPatterns.push(new RegExp(pattern));\n } catch {\n console.warn(`Warning: Invalid index pattern regex \"${pattern}\" - skipping`);\n }\n }\n\n // Match columns against patterns\n for (const column of columns) {\n // Skip 'id' column - it's the primary key and already indexed\n if (column === 'id') continue;\n for (const regex of compiledPatterns) {\n if (regex.test(column)) {\n columnsToIndex.add(column);\n break;\n }\n }\n }\n\n // Add explicitly specified columns (if they exist in the table)\n for (const column of additionalColumns) {\n if (columns.includes(column) && column !== 'id') {\n columnsToIndex.add(column);\n }\n }\n\n // Create index definitions\n for (const column of columnsToIndex) {\n const snakeColumn = toSnakeCase(column);\n indexes.push({\n name: `idx_${snakeTableName}_${snakeColumn}`,\n columns: [column]\n });\n }\n\n // Sort by index name for deterministic output\n indexes.sort((a, b) => a.name.localeCompare(b.name));\n return indexes;\n}\n\n/**\n * File header template\n */\nexport function generateHeader(typesPath: string): string {\n return `/**\n * PowerSync Schema Definition\n *\n * AUTO-GENERATED from ${typesPath}\n * Run: npx @pol-studios/powersync generate-schema\n *\n * DO NOT EDIT MANUALLY - changes will be overwritten\n */\n\nimport { column, Schema, Table } from \"@powersync/react-native\";\n`;\n}\n\n/**\n * Format indexes object for output (PowerSync SDK v1.32.0+ format)\n * Changed from array format [{ name, columns }] to object format { name: columns }\n */\nfunction formatIndexes(indexes: IndexDefinition[]): string {\n if (indexes.length === 0) return '';\n const indexLines = indexes.map(idx => {\n const columnsStr = idx.columns.map(c => `'${c}'`).join(', ');\n return ` '${idx.name}': [${columnsStr}],`;\n });\n return `indexes: {\\n${indexLines.join('\\n')}\\n }`;\n}\n\n/**\n * Generate the table definition for a parsed table\n */\nexport function generateTableDefinition(table: ParsedTable, columnDefs: string[], indexes: IndexDefinition[] = []): string {\n // Use alias if provided, otherwise use table name\n const effectiveName = table.config.alias ?? table.name;\n if (columnDefs.length === 0) {\n return `// ${effectiveName} - no syncable columns found`;\n }\n\n // Build options object\n const optionsParts: string[] = [];\n if (table.config.trackMetadata) {\n optionsParts.push('trackMetadata: true');\n }\n if (indexes.length > 0) {\n optionsParts.push(formatIndexes(indexes));\n }\n const optionsStr = optionsParts.length > 0 ? `, {\\n ${optionsParts.join(',\\n ')}\\n}` : '';\n return `const ${effectiveName} = new Table({\n${columnDefs.join('\\n')}\n}${optionsStr});`;\n}\n\n/**\n * Generate the table definition for a local-only table (not synced through PowerSync)\n */\nexport function generateLocalOnlyTableDefinition(table: ParsedTable, columnDefs: string[], indexes: IndexDefinition[] = []): string {\n // Use alias if provided, otherwise use table name\n const effectiveName = table.config.alias ?? table.name;\n if (columnDefs.length === 0) {\n return `// ${effectiveName} - no syncable columns found`;\n }\n\n // Build options object - always include localOnly: true\n const optionsParts: string[] = ['localOnly: true'];\n if (indexes.length > 0) {\n optionsParts.push(formatIndexes(indexes));\n }\n const optionsStr = `, {\\n ${optionsParts.join(',\\n ')}\\n}`;\n return `// Local-only table (not synced)\nconst ${effectiveName} = new Table({\n${columnDefs.join('\\n')}\n}${optionsStr});`;\n}\n\n/**\n * Generate the schema export section\n */\nexport function generateSchemaExport(tables: ParsedTable[]): string {\n // Use alias if provided, otherwise use table name\n const tableNames = tables.map(t => t.config.alias ?? t.name);\n return `// ============================================================================\n// SCHEMA EXPORT\n// ============================================================================\n\n// NOTE: photo_attachments is NOT included here.\n// The AttachmentQueue from @powersync/attachments creates and manages\n// its own internal SQLite table (not a view) during queue.init().\n// This allows INSERT/UPDATE operations to work correctly.\n\nexport const AppSchema = new Schema({\n${tableNames.map(name => ` ${name},`).join('\\n')}\n});\n\nexport type Database = (typeof AppSchema)[\"types\"];`;\n}\n\n/**\n * Generate schema mapping utilities\n */\nexport function generateSchemaMapping(tables: ParsedTable[], schemas: string[]): string {\n // Group tables by non-public schemas (use alias if provided)\n const schemaGroups = new Map<string, string[]>();\n for (const schema of schemas) {\n if (schema !== 'public') {\n schemaGroups.set(schema, []);\n }\n }\n for (const table of tables) {\n const effectiveName = table.config.alias ?? table.name;\n if (table.schema !== 'public' && schemaGroups.has(table.schema)) {\n schemaGroups.get(table.schema)!.push(effectiveName);\n }\n }\n const sections: string[] = [`// ============================================================================\n// SCHEMA MAPPING FOR CONNECTOR\n// ============================================================================`];\n\n // Generate constants for each non-public schema\n for (const [schema, tableNames] of schemaGroups) {\n if (tableNames.length > 0) {\n const constName = `${schema.toUpperCase()}_SCHEMA_TABLES`;\n sections.push(`\n// Tables in the '${schema}' schema (need .schema('${schema}') in Supabase queries)\nexport const ${constName} = new Set([\n${tableNames.map(name => ` \"${name}\",`).join('\\n')}\n]);`);\n }\n }\n\n // Generate helper function\n const schemaChecks = Array.from(schemaGroups.entries()).filter(([, names]) => names.length > 0).map(([schema]) => {\n const constName = `${schema.toUpperCase()}_SCHEMA_TABLES`;\n return ` if (${constName}.has(tableName)) return \"${schema}\";`;\n });\n if (schemaChecks.length > 0) {\n sections.push(`\n/**\n * Get the Supabase schema for a table\n */\nexport function getTableSchema(tableName: string): ${schemas.map(s => `\"${s}\"`).join(' | ')} {\n${schemaChecks.join('\\n')}\n return \"public\";\n}`);\n } else {\n sections.push(`\n/**\n * Get the Supabase schema for a table\n */\nexport function getTableSchema(tableName: string): \"public\" {\n return \"public\";\n}`);\n }\n return sections.join('\\n');\n}\n\n/**\n * Generate the FK detection utility (helpful for consumers)\n */\nexport function generateFKUtility(): string {\n return `\n// ============================================================================\n// FOREIGN KEY UTILITIES\n// ============================================================================\n\n/**\n * Check if a column name represents a foreign key reference\n * Convention: columns ending in 'Id' are foreign keys (e.g., projectId -> Project table)\n */\nexport function isForeignKeyColumn(columnName: string): boolean {\n return columnName.endsWith('Id') && columnName !== 'id';\n}\n\n/**\n * Get the referenced table name from a foreign key column\n * e.g., 'projectId' -> 'Project', 'equipmentFixtureUnitId' -> 'EquipmentFixtureUnit'\n */\nexport function getForeignKeyTable(columnName: string): string | null {\n if (!isForeignKeyColumn(columnName)) return null;\n // Remove 'Id' suffix and capitalize first letter\n const baseName = columnName.slice(0, -2);\n return baseName.charAt(0).toUpperCase() + baseName.slice(1);\n}`;\n}\n\n/**\n * Generate complete output file\n */\nexport function generateOutputFile(tables: ParsedTable[], tableDefs: string[], schemas: string[], typesPath: string): string {\n return `${generateHeader(typesPath)}\n\n// ============================================================================\n// TABLE DEFINITIONS\n// ============================================================================\n\n${tableDefs.join('\\n\\n')}\n\n${generateSchemaExport(tables)}\n\n${generateSchemaMapping(tables, ['public', ...schemas.filter(s => s !== 'public')])}\n${generateFKUtility()}\n`;\n}","/**\n * Foreign Key Dependency Detection\n *\n * Analyzes parsed tables to detect FK relationships and determine\n * optimal upload order for offline-first sync.\n */\n\nimport type { ParsedTable } from './parser.js';\nexport interface FKDependency {\n /** Table containing the FK column */\n table: string;\n /** FK column name (e.g., 'projectId') */\n column: string;\n /** Referenced table name (e.g., 'Project') */\n referencedTable: string;\n}\nexport interface DependencyGraph {\n /** Map of table -> tables it depends on (has FK references to) */\n dependencies: Map<string, string[]>;\n /** Map of table -> tables that depend on it (have FKs referencing this table) */\n dependents: Map<string, string[]>;\n /** Topologically sorted table names for optimal upload order */\n uploadOrder: string[];\n /** All detected FK relationships */\n fkRelationships: FKDependency[];\n}\n\n/**\n * Convert a FK column name to its referenced table name\n * Convention: columns ending in 'Id' reference the PascalCase table\n * e.g., projectId -> Project, equipmentUnitId -> EquipmentUnit\n */\nexport function fkColumnToTableName(columnName: string): string | null {\n if (!columnName.endsWith('Id') || columnName === 'id') {\n return null;\n }\n // Remove 'Id' suffix and capitalize first letter\n const baseName = columnName.slice(0, -2);\n return baseName.charAt(0).toUpperCase() + baseName.slice(1);\n}\n\n/**\n * Detect FK dependencies from parsed tables\n *\n * Uses naming convention: columns ending in 'Id' reference the PascalCase table\n * Only considers references to tables that are in the provided list (ignores external references)\n */\nexport function detectFKDependencies(tables: ParsedTable[]): DependencyGraph {\n const tableNames = new Set(tables.map(t => t.name));\n const dependencies = new Map<string, string[]>();\n const dependents = new Map<string, string[]>();\n const fkRelationships: FKDependency[] = [];\n\n // Initialize maps for all tables\n for (const table of tables) {\n dependencies.set(table.name, []);\n dependents.set(table.name, []);\n }\n\n // Detect FK relationships\n for (const table of tables) {\n for (const [columnName] of table.columns) {\n const referencedTable = fkColumnToTableName(columnName);\n\n // Only track references to tables in our schema\n if (referencedTable && tableNames.has(referencedTable)) {\n // This table depends on the referenced table\n const tableDeps = dependencies.get(table.name) || [];\n if (!tableDeps.includes(referencedTable)) {\n tableDeps.push(referencedTable);\n dependencies.set(table.name, tableDeps);\n }\n\n // The referenced table has this table as a dependent\n const refDeps = dependents.get(referencedTable) || [];\n if (!refDeps.includes(table.name)) {\n refDeps.push(table.name);\n dependents.set(referencedTable, refDeps);\n }\n\n // Record the FK relationship\n fkRelationships.push({\n table: table.name,\n column: columnName,\n referencedTable\n });\n }\n }\n }\n\n // Calculate upload order via topological sort\n const uploadOrder = getUploadOrder({\n dependencies\n });\n return {\n dependencies,\n dependents,\n uploadOrder,\n fkRelationships\n };\n}\n\n/**\n * Get optimal upload order using Kahn's topological sort algorithm\n *\n * Tables with no dependencies are uploaded first, then tables that depend on them, etc.\n * This ensures that when a row references another table, the referenced row exists first.\n */\nexport function getUploadOrder(graph: Pick<DependencyGraph, 'dependencies'>): string[] {\n const result: string[] = [];\n const inDegree = new Map<string, number>();\n const adjList = new Map<string, string[]>();\n\n // Initialize in-degree (number of dependencies) for each table\n for (const [table, deps] of graph.dependencies) {\n inDegree.set(table, deps.length);\n adjList.set(table, []);\n }\n\n // Build adjacency list (reverse of dependencies - who depends on this table)\n for (const [table, deps] of graph.dependencies) {\n for (const dep of deps) {\n const list = adjList.get(dep) || [];\n list.push(table);\n adjList.set(dep, list);\n }\n }\n\n // Start with tables that have no dependencies\n const queue: string[] = [];\n for (const [table, degree] of inDegree) {\n if (degree === 0) {\n queue.push(table);\n }\n }\n\n // Sort queue alphabetically for deterministic output\n queue.sort();\n\n // Process queue\n while (queue.length > 0) {\n const table = queue.shift()!;\n result.push(table);\n\n // Reduce in-degree for all tables that depend on this one\n const dependentTables = adjList.get(table) || [];\n for (const dependent of dependentTables) {\n const newDegree = (inDegree.get(dependent) || 0) - 1;\n inDegree.set(dependent, newDegree);\n if (newDegree === 0) {\n queue.push(dependent);\n // Keep queue sorted for deterministic output\n queue.sort();\n }\n }\n }\n\n // Check for cycles (if result doesn't include all tables)\n if (result.length < graph.dependencies.size) {\n // There's a cycle - just append remaining tables alphabetically\n const remaining = [...graph.dependencies.keys()].filter(t => !result.includes(t)).sort();\n result.push(...remaining);\n }\n return result;\n}\n\n/**\n * Get tables that have no dependencies (root tables)\n * These are typically reference/lookup tables like User, Project, etc.\n */\nexport function getRootTables(graph: DependencyGraph): string[] {\n const roots: string[] = [];\n for (const [table, deps] of graph.dependencies) {\n if (deps.length === 0) {\n roots.push(table);\n }\n }\n return roots.sort();\n}\n\n/**\n * Get tables that have no dependents (leaf tables)\n * These are typically transaction/event tables that reference other tables\n */\nexport function getLeafTables(graph: DependencyGraph): string[] {\n const leaves: string[] = [];\n for (const [table, deps] of graph.dependents) {\n if (deps.length === 0) {\n leaves.push(table);\n }\n }\n return leaves.sort();\n}\n\n/**\n * Format the dependency graph as a human-readable string\n */\nexport function formatDependencyGraph(graph: DependencyGraph): string {\n const lines: string[] = [];\n lines.push('FK Dependencies:');\n for (const fk of graph.fkRelationships) {\n lines.push(` ${fk.table}.${fk.column} -> ${fk.referencedTable}`);\n }\n if (graph.fkRelationships.length === 0) {\n lines.push(' (none detected)');\n }\n lines.push('');\n lines.push('Upload Order (topological):');\n graph.uploadOrder.forEach((table, i) => {\n const deps = graph.dependencies.get(table) || [];\n const depStr = deps.length > 0 ? ` (depends on: ${deps.join(', ')})` : ' (root)';\n lines.push(` ${i + 1}. ${table}${depStr}`);\n });\n return lines.join('\\n');\n}"],"mappings":"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","names":[]}