@agent-native/core 0.4.1 → 0.4.2

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 (221) hide show
  1. package/README.md +31 -0
  2. package/dist/adapters/convex/adapter.d.ts +24 -0
  3. package/dist/adapters/convex/adapter.d.ts.map +1 -0
  4. package/dist/adapters/convex/adapter.js +125 -0
  5. package/dist/adapters/convex/adapter.js.map +1 -0
  6. package/dist/adapters/convex/index.d.ts +4 -0
  7. package/dist/adapters/convex/index.d.ts.map +1 -0
  8. package/dist/adapters/convex/index.js +3 -0
  9. package/dist/adapters/convex/index.js.map +1 -0
  10. package/dist/adapters/drizzle/adapter.d.ts +36 -0
  11. package/dist/adapters/drizzle/adapter.d.ts.map +1 -0
  12. package/dist/adapters/drizzle/adapter.js +210 -0
  13. package/dist/adapters/drizzle/adapter.js.map +1 -0
  14. package/dist/adapters/drizzle/index.d.ts +3 -0
  15. package/dist/adapters/drizzle/index.d.ts.map +1 -0
  16. package/dist/adapters/drizzle/index.js +3 -0
  17. package/dist/adapters/drizzle/index.js.map +1 -0
  18. package/dist/adapters/drizzle/schema.d.ts +146 -0
  19. package/dist/adapters/drizzle/schema.d.ts.map +1 -0
  20. package/dist/adapters/drizzle/schema.js +20 -0
  21. package/dist/adapters/drizzle/schema.js.map +1 -0
  22. package/dist/adapters/firestore/adapter.d.ts +3 -2
  23. package/dist/adapters/firestore/adapter.d.ts.map +1 -1
  24. package/dist/adapters/firestore/adapter.js +23 -6
  25. package/dist/adapters/firestore/adapter.js.map +1 -1
  26. package/dist/adapters/supabase/adapter.d.ts +2 -1
  27. package/dist/adapters/supabase/adapter.d.ts.map +1 -1
  28. package/dist/adapters/supabase/adapter.js +4 -1
  29. package/dist/adapters/supabase/adapter.js.map +1 -1
  30. package/dist/adapters/sync/config.d.ts +22 -2
  31. package/dist/adapters/sync/config.d.ts.map +1 -1
  32. package/dist/adapters/sync/config.js +175 -16
  33. package/dist/adapters/sync/config.js.map +1 -1
  34. package/dist/adapters/sync/create-file-sync.d.ts +32 -0
  35. package/dist/adapters/sync/create-file-sync.d.ts.map +1 -0
  36. package/dist/adapters/sync/create-file-sync.js +218 -0
  37. package/dist/adapters/sync/create-file-sync.js.map +1 -0
  38. package/dist/adapters/sync/file-sync.d.ts +40 -6
  39. package/dist/adapters/sync/file-sync.d.ts.map +1 -1
  40. package/dist/adapters/sync/file-sync.js +442 -97
  41. package/dist/adapters/sync/file-sync.js.map +1 -1
  42. package/dist/adapters/sync/index.d.ts +3 -2
  43. package/dist/adapters/sync/index.d.ts.map +1 -1
  44. package/dist/adapters/sync/index.js +3 -1
  45. package/dist/adapters/sync/index.js.map +1 -1
  46. package/dist/adapters/sync/merge.js +3 -2
  47. package/dist/adapters/sync/merge.js.map +1 -1
  48. package/dist/adapters/sync/types.d.ts +36 -2
  49. package/dist/adapters/sync/types.d.ts.map +1 -1
  50. package/dist/adapters/sync/types.js +22 -1
  51. package/dist/adapters/sync/types.js.map +1 -1
  52. package/dist/agent/index.d.ts +3 -0
  53. package/dist/agent/index.d.ts.map +1 -0
  54. package/dist/agent/index.js +2 -0
  55. package/dist/agent/index.js.map +1 -0
  56. package/dist/agent/production-agent.d.ts +16 -0
  57. package/dist/agent/production-agent.d.ts.map +1 -0
  58. package/dist/agent/production-agent.js +152 -0
  59. package/dist/agent/production-agent.js.map +1 -0
  60. package/dist/agent/types.d.ts +38 -0
  61. package/dist/agent/types.d.ts.map +1 -0
  62. package/dist/agent/types.js +2 -0
  63. package/dist/agent/types.js.map +1 -0
  64. package/dist/cli/create.d.ts.map +1 -1
  65. package/dist/cli/create.js +2 -0
  66. package/dist/cli/create.js.map +1 -1
  67. package/dist/cli/index.js +37 -11
  68. package/dist/cli/index.js.map +1 -1
  69. package/dist/client/PoweredByBadge.d.ts +14 -0
  70. package/dist/client/PoweredByBadge.d.ts.map +1 -0
  71. package/dist/client/PoweredByBadge.js +60 -0
  72. package/dist/client/PoweredByBadge.js.map +1 -0
  73. package/dist/client/ProductionAgentPanel.d.ts +10 -0
  74. package/dist/client/ProductionAgentPanel.d.ts.map +1 -0
  75. package/dist/client/ProductionAgentPanel.js +121 -0
  76. package/dist/client/ProductionAgentPanel.js.map +1 -0
  77. package/dist/client/Turnstile.d.ts +35 -0
  78. package/dist/client/Turnstile.d.ts.map +1 -0
  79. package/dist/client/Turnstile.js +77 -0
  80. package/dist/client/Turnstile.js.map +1 -0
  81. package/dist/client/index.d.ts +6 -0
  82. package/dist/client/index.d.ts.map +1 -1
  83. package/dist/client/index.js +6 -0
  84. package/dist/client/index.js.map +1 -1
  85. package/dist/client/use-file-sync-status.d.ts +21 -0
  86. package/dist/client/use-file-sync-status.d.ts.map +1 -0
  87. package/dist/client/use-file-sync-status.js +65 -0
  88. package/dist/client/use-file-sync-status.js.map +1 -0
  89. package/dist/client/use-session.d.ts +16 -0
  90. package/dist/client/use-session.d.ts.map +1 -0
  91. package/dist/client/use-session.js +49 -0
  92. package/dist/client/use-session.js.map +1 -0
  93. package/dist/client/useProductionAgent.d.ts +18 -0
  94. package/dist/client/useProductionAgent.d.ts.map +1 -0
  95. package/dist/client/useProductionAgent.js +135 -0
  96. package/dist/client/useProductionAgent.js.map +1 -0
  97. package/dist/db/index.d.ts +21 -0
  98. package/dist/db/index.d.ts.map +1 -0
  99. package/dist/db/index.js +17 -0
  100. package/dist/db/index.js.map +1 -0
  101. package/dist/index.browser.d.ts +1 -1
  102. package/dist/index.browser.d.ts.map +1 -1
  103. package/dist/index.browser.js +1 -1
  104. package/dist/index.browser.js.map +1 -1
  105. package/dist/index.d.ts +3 -2
  106. package/dist/index.d.ts.map +1 -1
  107. package/dist/index.js +4 -2
  108. package/dist/index.js.map +1 -1
  109. package/dist/router/index.d.ts +3 -0
  110. package/dist/router/index.d.ts.map +1 -0
  111. package/dist/router/index.js +5 -0
  112. package/dist/router/index.js.map +1 -0
  113. package/dist/scripts/core-scripts.d.ts +10 -0
  114. package/dist/scripts/core-scripts.d.ts.map +1 -0
  115. package/dist/scripts/core-scripts.js +15 -0
  116. package/dist/scripts/core-scripts.js.map +1 -0
  117. package/dist/scripts/db/exec.d.ts +11 -0
  118. package/dist/scripts/db/exec.d.ts.map +1 -0
  119. package/dist/scripts/db/exec.js +86 -0
  120. package/dist/scripts/db/exec.js.map +1 -0
  121. package/dist/scripts/db/index.d.ts +2 -0
  122. package/dist/scripts/db/index.d.ts.map +1 -0
  123. package/dist/scripts/db/index.js +6 -0
  124. package/dist/scripts/db/index.js.map +1 -0
  125. package/dist/scripts/db/query.d.ts +10 -0
  126. package/dist/scripts/db/query.d.ts.map +1 -0
  127. package/dist/scripts/db/query.js +96 -0
  128. package/dist/scripts/db/query.js.map +1 -0
  129. package/dist/scripts/db/schema.d.ts +12 -0
  130. package/dist/scripts/db/schema.d.ts.map +1 -0
  131. package/dist/scripts/db/schema.js +112 -0
  132. package/dist/scripts/db/schema.js.map +1 -0
  133. package/dist/scripts/index.d.ts +4 -0
  134. package/dist/scripts/index.d.ts.map +1 -1
  135. package/dist/scripts/index.js +4 -0
  136. package/dist/scripts/index.js.map +1 -1
  137. package/dist/scripts/runner.d.ts +3 -0
  138. package/dist/scripts/runner.d.ts.map +1 -1
  139. package/dist/scripts/runner.js +53 -14
  140. package/dist/scripts/runner.js.map +1 -1
  141. package/dist/server/auth.d.ts +59 -0
  142. package/dist/server/auth.d.ts.map +1 -0
  143. package/dist/server/auth.js +442 -0
  144. package/dist/server/auth.js.map +1 -0
  145. package/dist/server/captcha.d.ts +12 -0
  146. package/dist/server/captcha.d.ts.map +1 -0
  147. package/dist/server/captcha.js +43 -0
  148. package/dist/server/captcha.js.map +1 -0
  149. package/dist/server/create-server.d.ts +13 -10
  150. package/dist/server/create-server.d.ts.map +1 -1
  151. package/dist/server/create-server.js +41 -27
  152. package/dist/server/create-server.js.map +1 -1
  153. package/dist/server/index.d.ts +5 -1
  154. package/dist/server/index.d.ts.map +1 -1
  155. package/dist/server/index.js +6 -1
  156. package/dist/server/index.js.map +1 -1
  157. package/dist/server/missing-key.d.ts +9 -5
  158. package/dist/server/missing-key.d.ts.map +1 -1
  159. package/dist/server/missing-key.js +12 -7
  160. package/dist/server/missing-key.js.map +1 -1
  161. package/dist/server/sse.d.ts +12 -7
  162. package/dist/server/sse.d.ts.map +1 -1
  163. package/dist/server/sse.js +79 -15
  164. package/dist/server/sse.js.map +1 -1
  165. package/dist/vite/client.d.ts +28 -5
  166. package/dist/vite/client.d.ts.map +1 -1
  167. package/dist/vite/client.js +36 -15
  168. package/dist/vite/client.js.map +1 -1
  169. package/dist/vite/dev-api-server.d.ts +10 -0
  170. package/dist/vite/dev-api-server.d.ts.map +1 -0
  171. package/dist/vite/dev-api-server.js +148 -0
  172. package/dist/vite/dev-api-server.js.map +1 -0
  173. package/dist/vite/index.d.ts +2 -3
  174. package/dist/vite/index.d.ts.map +1 -1
  175. package/dist/vite/index.js +2 -3
  176. package/dist/vite/index.js.map +1 -1
  177. package/package.json +26 -17
  178. package/src/templates/default/AGENTS.md +148 -22
  179. package/src/templates/default/_gitignore +9 -5
  180. package/src/templates/default/client/entry.client.tsx +4 -0
  181. package/src/templates/default/client/entry.server.tsx +55 -0
  182. package/src/templates/default/client/root.tsx +82 -0
  183. package/src/templates/default/client/routes/_index.tsx +19 -0
  184. package/src/templates/default/client/routes.ts +4 -0
  185. package/src/templates/default/client/vite-env.d.ts +5 -0
  186. package/src/templates/default/package.json +5 -7
  187. package/src/templates/default/react-router.config.ts +6 -0
  188. package/src/templates/default/server/lib/watcher.ts +21 -0
  189. package/src/templates/default/server/plugins/auth.ts +5 -0
  190. package/src/templates/default/server/plugins/file-sync.ts +39 -0
  191. package/src/templates/default/server/routes/[...page].get.ts +12 -0
  192. package/src/templates/default/server/routes/api/events.get.ts +7 -0
  193. package/src/templates/default/server/routes/api/file-sync/status.get.ts +13 -0
  194. package/src/templates/default/server/routes/api/hello.get.ts +5 -0
  195. package/src/templates/default/tsconfig.json +9 -1
  196. package/src/templates/default/vite.config.ts +4 -1
  197. package/tsconfig.base.json +3 -1
  198. package/dist/adapters/neon/adapter.d.ts +0 -28
  199. package/dist/adapters/neon/adapter.d.ts.map +0 -1
  200. package/dist/adapters/neon/adapter.js +0 -135
  201. package/dist/adapters/neon/adapter.js.map +0 -1
  202. package/dist/adapters/neon/index.d.ts +0 -3
  203. package/dist/adapters/neon/index.d.ts.map +0 -1
  204. package/dist/adapters/neon/index.js +0 -3
  205. package/dist/adapters/neon/index.js.map +0 -1
  206. package/dist/server/production.d.ts +0 -18
  207. package/dist/server/production.d.ts.map +0 -1
  208. package/dist/server/production.js +0 -37
  209. package/dist/server/production.js.map +0 -1
  210. package/dist/vite/express-plugin.d.ts +0 -14
  211. package/dist/vite/express-plugin.d.ts.map +0 -1
  212. package/dist/vite/express-plugin.js +0 -53
  213. package/dist/vite/express-plugin.js.map +0 -1
  214. package/dist/vite/server.d.ts +0 -21
  215. package/dist/vite/server.d.ts.map +0 -1
  216. package/dist/vite/server.js +0 -68
  217. package/dist/vite/server.js.map +0 -1
  218. package/src/templates/default/index.html +0 -14
  219. package/src/templates/default/server/index.ts +0 -22
  220. package/src/templates/default/server/node-build.ts +0 -4
  221. package/src/templates/default/vite.config.server.ts +0 -3
@@ -0,0 +1,20 @@
1
+ import { sqliteTable, text, integer } from "drizzle-orm/sqlite-core";
2
+ /**
3
+ * SQLite schema for the file sync adapter.
4
+ *
5
+ * Table schema:
6
+ * files(id TEXT PK, path TEXT, content TEXT, app TEXT, owner_id TEXT,
7
+ * last_updated INTEGER, created_at INTEGER)
8
+ *
9
+ * CREATE INDEX idx_files_app_owner ON files(app, owner_id);
10
+ */
11
+ export const files = sqliteTable("files", {
12
+ id: text("id").primaryKey(),
13
+ path: text("path").notNull(),
14
+ content: text("content").notNull(),
15
+ app: text("app").notNull(),
16
+ ownerId: text("owner_id").notNull(),
17
+ lastUpdated: integer("last_updated", { mode: "number" }).notNull(),
18
+ createdAt: integer("created_at", { mode: "number" }),
19
+ });
20
+ //# sourceMappingURL=schema.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"schema.js","sourceRoot":"","sources":["../../../src/adapters/drizzle/schema.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,yBAAyB,CAAC;AAErE;;;;;;;;GAQG;AACH,MAAM,CAAC,MAAM,KAAK,GAAG,WAAW,CAAC,OAAO,EAAE;IACxC,EAAE,EAAE,IAAI,CAAC,IAAI,CAAC,CAAC,UAAU,EAAE;IAC3B,IAAI,EAAE,IAAI,CAAC,MAAM,CAAC,CAAC,OAAO,EAAE;IAC5B,OAAO,EAAE,IAAI,CAAC,SAAS,CAAC,CAAC,OAAO,EAAE;IAClC,GAAG,EAAE,IAAI,CAAC,KAAK,CAAC,CAAC,OAAO,EAAE;IAC1B,OAAO,EAAE,IAAI,CAAC,UAAU,CAAC,CAAC,OAAO,EAAE;IACnC,WAAW,EAAE,OAAO,CAAC,cAAc,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,CAAC,CAAC,OAAO,EAAE;IAClE,SAAS,EAAE,OAAO,CAAC,YAAY,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,CAAC;CACrD,CAAC,CAAC"}
@@ -14,7 +14,7 @@ export interface FirestoreDocRef {
14
14
  export interface FirestoreQuery {
15
15
  where(field: string, op: string, value: any): FirestoreQuery;
16
16
  get(): Promise<FirestoreQuerySnapshot>;
17
- onSnapshot(onNext: (snapshot: FirestoreQuerySnapshot) => void, onError: (error: any) => void): () => void;
17
+ onSnapshot(onNext: (snapshot: FirestoreQuerySnapshot) => void, onError: (error: unknown) => void): () => void;
18
18
  }
19
19
  export interface FirestoreDocSnapshot {
20
20
  exists: boolean;
@@ -42,6 +42,7 @@ export declare class FirestoreFileSyncAdapter implements FileSyncAdapter {
42
42
  } | null>;
43
43
  set(id: string, record: Partial<FileRecord>): Promise<void>;
44
44
  delete(id: string): Promise<void>;
45
- subscribe(appId: string, ownerId: string, onChange: (changes: FileChange[]) => void, onError: (error: any) => void): Unsubscribe;
45
+ subscribe(appId: string, ownerId: string, onChange: (changes: FileChange[]) => void, onError: (error: unknown) => void): Unsubscribe;
46
+ dispose(): Promise<void>;
46
47
  }
47
48
  //# sourceMappingURL=adapter.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"adapter.d.ts","sourceRoot":"","sources":["../../../src/adapters/firestore/adapter.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,eAAe,EACf,UAAU,EACV,UAAU,EACV,WAAW,EACZ,MAAM,kBAAkB,CAAC;AAM1B,MAAM,WAAW,mBAAmB;IAClC,GAAG,CAAC,EAAE,EAAE,MAAM,GAAG,eAAe,CAAC;IACjC,KAAK,CAAC,KAAK,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,EAAE,KAAK,EAAE,GAAG,GAAG,cAAc,CAAC;CAC9D;AAED,MAAM,WAAW,eAAe;IAC9B,GAAG,IAAI,OAAO,CAAC,oBAAoB,CAAC,CAAC;IACrC,GAAG,CAAC,IAAI,EAAE,GAAG,EAAE,OAAO,CAAC,EAAE;QAAE,KAAK,CAAC,EAAE,OAAO,CAAA;KAAE,GAAG,OAAO,CAAC,GAAG,CAAC,CAAC;IAC5D,MAAM,IAAI,OAAO,CAAC,GAAG,CAAC,CAAC;IACvB,UAAU,CAAC,IAAI,EAAE,MAAM,GAAG,mBAAmB,CAAC;CAC/C;AAED,MAAM,WAAW,cAAc;IAC7B,KAAK,CAAC,KAAK,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,EAAE,KAAK,EAAE,GAAG,GAAG,cAAc,CAAC;IAC7D,GAAG,IAAI,OAAO,CAAC,sBAAsB,CAAC,CAAC;IACvC,UAAU,CACR,MAAM,EAAE,CAAC,QAAQ,EAAE,sBAAsB,KAAK,IAAI,EAClD,OAAO,EAAE,CAAC,KAAK,EAAE,GAAG,KAAK,IAAI,GAC5B,MAAM,IAAI,CAAC;CACf;AAED,MAAM,WAAW,oBAAoB;IACnC,MAAM,EAAE,OAAO,CAAC;IAChB,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,IAAI,GAAG,CAAC;CACb;AAED,MAAM,WAAW,sBAAsB;IACrC,IAAI,EAAE,oBAAoB,EAAE,CAAC;IAC7B,IAAI,EAAE,MAAM,CAAC;IACb,UAAU,IAAI,KAAK,CAAC;QAClB,IAAI,EAAE,OAAO,GAAG,UAAU,GAAG,SAAS,CAAC;QACvC,GAAG,EAAE,oBAAoB,CAAC;KAC3B,CAAC,CAAC;CACJ;AAMD,qBAAa,wBAAyB,YAAW,eAAe;IAClD,OAAO,CAAC,aAAa;gBAAb,aAAa,EAAE,MAAM,mBAAmB;IAEtD,KAAK,CACT,KAAK,EAAE,MAAM,EACb,OAAO,EAAE,MAAM,GACd,OAAO,CAAC;QAAE,EAAE,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,UAAU,CAAA;KAAE,EAAE,CAAC;IAYxC,GAAG,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC;QAAE,EAAE,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,UAAU,CAAA;KAAE,GAAG,IAAI,CAAC;IAMjE,GAAG,CAAC,EAAE,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,CAAC,UAAU,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC;IAI3D,MAAM,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAIvC,SAAS,CACP,KAAK,EAAE,MAAM,EACb,OAAO,EAAE,MAAM,EACf,QAAQ,EAAE,CAAC,OAAO,EAAE,UAAU,EAAE,KAAK,IAAI,EACzC,OAAO,EAAE,CAAC,KAAK,EAAE,GAAG,KAAK,IAAI,GAC5B,WAAW;CAaf"}
1
+ {"version":3,"file":"adapter.d.ts","sourceRoot":"","sources":["../../../src/adapters/firestore/adapter.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,eAAe,EACf,UAAU,EACV,UAAU,EACV,WAAW,EACZ,MAAM,kBAAkB,CAAC;AAM1B,MAAM,WAAW,mBAAmB;IAClC,GAAG,CAAC,EAAE,EAAE,MAAM,GAAG,eAAe,CAAC;IACjC,KAAK,CAAC,KAAK,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,EAAE,KAAK,EAAE,GAAG,GAAG,cAAc,CAAC;CAC9D;AAED,MAAM,WAAW,eAAe;IAC9B,GAAG,IAAI,OAAO,CAAC,oBAAoB,CAAC,CAAC;IACrC,GAAG,CAAC,IAAI,EAAE,GAAG,EAAE,OAAO,CAAC,EAAE;QAAE,KAAK,CAAC,EAAE,OAAO,CAAA;KAAE,GAAG,OAAO,CAAC,GAAG,CAAC,CAAC;IAC5D,MAAM,IAAI,OAAO,CAAC,GAAG,CAAC,CAAC;IACvB,UAAU,CAAC,IAAI,EAAE,MAAM,GAAG,mBAAmB,CAAC;CAC/C;AAED,MAAM,WAAW,cAAc;IAC7B,KAAK,CAAC,KAAK,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,EAAE,KAAK,EAAE,GAAG,GAAG,cAAc,CAAC;IAC7D,GAAG,IAAI,OAAO,CAAC,sBAAsB,CAAC,CAAC;IACvC,UAAU,CACR,MAAM,EAAE,CAAC,QAAQ,EAAE,sBAAsB,KAAK,IAAI,EAClD,OAAO,EAAE,CAAC,KAAK,EAAE,OAAO,KAAK,IAAI,GAChC,MAAM,IAAI,CAAC;CACf;AAED,MAAM,WAAW,oBAAoB;IACnC,MAAM,EAAE,OAAO,CAAC;IAChB,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,IAAI,GAAG,CAAC;CACb;AAED,MAAM,WAAW,sBAAsB;IACrC,IAAI,EAAE,oBAAoB,EAAE,CAAC;IAC7B,IAAI,EAAE,MAAM,CAAC;IACb,UAAU,IAAI,KAAK,CAAC;QAClB,IAAI,EAAE,OAAO,GAAG,UAAU,GAAG,SAAS,CAAC;QACvC,GAAG,EAAE,oBAAoB,CAAC;KAC3B,CAAC,CAAC;CACJ;AAoBD,qBAAa,wBAAyB,YAAW,eAAe;IAClD,OAAO,CAAC,aAAa;gBAAb,aAAa,EAAE,MAAM,mBAAmB;IAEtD,KAAK,CACT,KAAK,EAAE,MAAM,EACb,OAAO,EAAE,MAAM,GACd,OAAO,CAAC;QAAE,EAAE,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,UAAU,CAAA;KAAE,EAAE,CAAC;IAYxC,GAAG,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC;QAAE,EAAE,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,UAAU,CAAA;KAAE,GAAG,IAAI,CAAC;IAMjE,GAAG,CAAC,EAAE,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,CAAC,UAAU,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC;IAM3D,MAAM,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAIvC,SAAS,CACP,KAAK,EAAE,MAAM,EACb,OAAO,EAAE,MAAM,EACf,QAAQ,EAAE,CAAC,OAAO,EAAE,UAAU,EAAE,KAAK,IAAI,EACzC,OAAO,EAAE,CAAC,KAAK,EAAE,OAAO,KAAK,IAAI,GAChC,WAAW;IAcR,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC;CAI/B"}
@@ -1,4 +1,15 @@
1
1
  // ---------------------------------------------------------------------------
2
+ // Helpers
3
+ // ---------------------------------------------------------------------------
4
+ // Firestore doc IDs cannot contain `/` (it's a path separator).
5
+ // Encode `/` as `%2F` for storage, decode on retrieval.
6
+ function encodeDocId(id) {
7
+ return id.replace(/\//g, "%2F");
8
+ }
9
+ function decodeDocId(id) {
10
+ return id.replace(/%2F/g, "/");
11
+ }
12
+ // ---------------------------------------------------------------------------
2
13
  // Firestore adapter
3
14
  // ---------------------------------------------------------------------------
4
15
  export class FirestoreFileSyncAdapter {
@@ -12,21 +23,23 @@ export class FirestoreFileSyncAdapter {
12
23
  .where("ownerId", "==", ownerId)
13
24
  .get();
14
25
  return snapshot.docs.map((doc) => ({
15
- id: doc.id,
26
+ id: decodeDocId(doc.id),
16
27
  data: doc.data(),
17
28
  }));
18
29
  }
19
30
  async get(id) {
20
- const doc = await this.getCollection().doc(id).get();
31
+ const doc = await this.getCollection().doc(encodeDocId(id)).get();
21
32
  if (!doc.exists)
22
33
  return null;
23
- return { id: doc.id, data: doc.data() };
34
+ return { id: decodeDocId(doc.id), data: doc.data() };
24
35
  }
25
36
  async set(id, record) {
26
- await this.getCollection().doc(id).set(record, { merge: true });
37
+ await this.getCollection()
38
+ .doc(encodeDocId(id))
39
+ .set(record, { merge: true });
27
40
  }
28
41
  async delete(id) {
29
- await this.getCollection().doc(id).delete();
42
+ await this.getCollection().doc(encodeDocId(id)).delete();
30
43
  }
31
44
  subscribe(appId, ownerId, onChange, onError) {
32
45
  return this.getCollection()
@@ -35,11 +48,15 @@ export class FirestoreFileSyncAdapter {
35
48
  .onSnapshot((snapshot) => {
36
49
  const changes = snapshot.docChanges().map((change) => ({
37
50
  type: change.type,
38
- id: change.doc.id,
51
+ id: decodeDocId(change.doc.id),
39
52
  data: change.doc.data(),
40
53
  }));
41
54
  onChange(changes);
42
55
  }, onError);
43
56
  }
57
+ async dispose() {
58
+ // No persistent connections to clean up in the duck-typed interface.
59
+ // Real Firebase apps should call app.delete() separately.
60
+ }
44
61
  }
45
62
  //# sourceMappingURL=adapter.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"adapter.js","sourceRoot":"","sources":["../../../src/adapters/firestore/adapter.ts"],"names":[],"mappings":"AA+CA,8EAA8E;AAC9E,oBAAoB;AACpB,8EAA8E;AAE9E,MAAM,OAAO,wBAAwB;IACf;IAApB,YAAoB,aAAwC;QAAxC,kBAAa,GAAb,aAAa,CAA2B;IAAG,CAAC;IAEhE,KAAK,CAAC,KAAK,CACT,KAAa,EACb,OAAe;QAEf,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,aAAa,EAAE;aACxC,KAAK,CAAC,KAAK,EAAE,IAAI,EAAE,KAAK,CAAC;aACzB,KAAK,CAAC,SAAS,EAAE,IAAI,EAAE,OAAO,CAAC;aAC/B,GAAG,EAAE,CAAC;QAET,OAAO,QAAQ,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC;YACjC,EAAE,EAAE,GAAG,CAAC,EAAE;YACV,IAAI,EAAE,GAAG,CAAC,IAAI,EAAgB;SAC/B,CAAC,CAAC,CAAC;IACN,CAAC;IAED,KAAK,CAAC,GAAG,CAAC,EAAU;QAClB,MAAM,GAAG,GAAG,MAAM,IAAI,CAAC,aAAa,EAAE,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,GAAG,EAAE,CAAC;QACrD,IAAI,CAAC,GAAG,CAAC,MAAM;YAAE,OAAO,IAAI,CAAC;QAC7B,OAAO,EAAE,EAAE,EAAE,GAAG,CAAC,EAAE,EAAE,IAAI,EAAE,GAAG,CAAC,IAAI,EAAgB,EAAE,CAAC;IACxD,CAAC;IAED,KAAK,CAAC,GAAG,CAAC,EAAU,EAAE,MAA2B;QAC/C,MAAM,IAAI,CAAC,aAAa,EAAE,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,GAAG,CAAC,MAAM,EAAE,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;IAClE,CAAC;IAED,KAAK,CAAC,MAAM,CAAC,EAAU;QACrB,MAAM,IAAI,CAAC,aAAa,EAAE,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC;IAC9C,CAAC;IAED,SAAS,CACP,KAAa,EACb,OAAe,EACf,QAAyC,EACzC,OAA6B;QAE7B,OAAO,IAAI,CAAC,aAAa,EAAE;aACxB,KAAK,CAAC,KAAK,EAAE,IAAI,EAAE,KAAK,CAAC;aACzB,KAAK,CAAC,SAAS,EAAE,IAAI,EAAE,OAAO,CAAC;aAC/B,UAAU,CAAC,CAAC,QAAQ,EAAE,EAAE;YACvB,MAAM,OAAO,GAAiB,QAAQ,CAAC,UAAU,EAAE,CAAC,GAAG,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC;gBACnE,IAAI,EAAE,MAAM,CAAC,IAAI;gBACjB,EAAE,EAAE,MAAM,CAAC,GAAG,CAAC,EAAE;gBACjB,IAAI,EAAE,MAAM,CAAC,GAAG,CAAC,IAAI,EAAgB;aACtC,CAAC,CAAC,CAAC;YACJ,QAAQ,CAAC,OAAO,CAAC,CAAC;QACpB,CAAC,EAAE,OAAO,CAAC,CAAC;IAChB,CAAC;CACF"}
1
+ {"version":3,"file":"adapter.js","sourceRoot":"","sources":["../../../src/adapters/firestore/adapter.ts"],"names":[],"mappings":"AA+CA,8EAA8E;AAC9E,UAAU;AACV,8EAA8E;AAE9E,gEAAgE;AAChE,wDAAwD;AACxD,SAAS,WAAW,CAAC,EAAU;IAC7B,OAAO,EAAE,CAAC,OAAO,CAAC,KAAK,EAAE,KAAK,CAAC,CAAC;AAClC,CAAC;AAED,SAAS,WAAW,CAAC,EAAU;IAC7B,OAAO,EAAE,CAAC,OAAO,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;AACjC,CAAC;AAED,8EAA8E;AAC9E,oBAAoB;AACpB,8EAA8E;AAE9E,MAAM,OAAO,wBAAwB;IACf;IAApB,YAAoB,aAAwC;QAAxC,kBAAa,GAAb,aAAa,CAA2B;IAAG,CAAC;IAEhE,KAAK,CAAC,KAAK,CACT,KAAa,EACb,OAAe;QAEf,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,aAAa,EAAE;aACxC,KAAK,CAAC,KAAK,EAAE,IAAI,EAAE,KAAK,CAAC;aACzB,KAAK,CAAC,SAAS,EAAE,IAAI,EAAE,OAAO,CAAC;aAC/B,GAAG,EAAE,CAAC;QAET,OAAO,QAAQ,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC;YACjC,EAAE,EAAE,WAAW,CAAC,GAAG,CAAC,EAAE,CAAC;YACvB,IAAI,EAAE,GAAG,CAAC,IAAI,EAAgB;SAC/B,CAAC,CAAC,CAAC;IACN,CAAC;IAED,KAAK,CAAC,GAAG,CAAC,EAAU;QAClB,MAAM,GAAG,GAAG,MAAM,IAAI,CAAC,aAAa,EAAE,CAAC,GAAG,CAAC,WAAW,CAAC,EAAE,CAAC,CAAC,CAAC,GAAG,EAAE,CAAC;QAClE,IAAI,CAAC,GAAG,CAAC,MAAM;YAAE,OAAO,IAAI,CAAC;QAC7B,OAAO,EAAE,EAAE,EAAE,WAAW,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE,IAAI,EAAE,GAAG,CAAC,IAAI,EAAgB,EAAE,CAAC;IACrE,CAAC;IAED,KAAK,CAAC,GAAG,CAAC,EAAU,EAAE,MAA2B;QAC/C,MAAM,IAAI,CAAC,aAAa,EAAE;aACvB,GAAG,CAAC,WAAW,CAAC,EAAE,CAAC,CAAC;aACpB,GAAG,CAAC,MAAM,EAAE,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;IAClC,CAAC;IAED,KAAK,CAAC,MAAM,CAAC,EAAU;QACrB,MAAM,IAAI,CAAC,aAAa,EAAE,CAAC,GAAG,CAAC,WAAW,CAAC,EAAE,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC;IAC3D,CAAC;IAED,SAAS,CACP,KAAa,EACb,OAAe,EACf,QAAyC,EACzC,OAAiC;QAEjC,OAAO,IAAI,CAAC,aAAa,EAAE;aACxB,KAAK,CAAC,KAAK,EAAE,IAAI,EAAE,KAAK,CAAC;aACzB,KAAK,CAAC,SAAS,EAAE,IAAI,EAAE,OAAO,CAAC;aAC/B,UAAU,CAAC,CAAC,QAAQ,EAAE,EAAE;YACvB,MAAM,OAAO,GAAiB,QAAQ,CAAC,UAAU,EAAE,CAAC,GAAG,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC;gBACnE,IAAI,EAAE,MAAM,CAAC,IAAI;gBACjB,EAAE,EAAE,WAAW,CAAC,MAAM,CAAC,GAAG,CAAC,EAAE,CAAC;gBAC9B,IAAI,EAAE,MAAM,CAAC,GAAG,CAAC,IAAI,EAAgB;aACtC,CAAC,CAAC,CAAC;YACJ,QAAQ,CAAC,OAAO,CAAC,CAAC;QACpB,CAAC,EAAE,OAAO,CAAC,CAAC;IAChB,CAAC;IAED,KAAK,CAAC,OAAO;QACX,qEAAqE;QACrE,0DAA0D;IAC5D,CAAC;CACF"}
@@ -36,7 +36,8 @@ export declare class SupabaseFileSyncAdapter implements FileSyncAdapter {
36
36
  } | null>;
37
37
  set(id: string, record: Partial<FileRecord>): Promise<void>;
38
38
  delete(id: string): Promise<void>;
39
- subscribe(appId: string, ownerId: string, onChange: (changes: FileChange[]) => void, onError: (error: any) => void): Unsubscribe;
39
+ subscribe(appId: string, ownerId: string, onChange: (changes: FileChange[]) => void, onError: (error: unknown) => void): Unsubscribe;
40
+ dispose(): Promise<void>;
40
41
  }
41
42
  export {};
42
43
  //# sourceMappingURL=adapter.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"adapter.d.ts","sourceRoot":"","sources":["../../../src/adapters/supabase/adapter.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,eAAe,EACf,UAAU,EACV,UAAU,EACV,WAAW,EACZ,MAAM,kBAAkB,CAAC;AAM1B,UAAU,qBAAqB;IAC7B,MAAM,CAAC,OAAO,EAAE,MAAM,GAAG,qBAAqB,CAAC;IAC/C,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,GAAG,GAAG,qBAAqB,CAAC;IACtD,WAAW,IAAI,qBAAqB,CAAC;IACrC,IAAI,CAAC,OAAO,EAAE,CAAC,KAAK,EAAE,GAAG,KAAK,GAAG,EAAE,MAAM,CAAC,EAAE,CAAC,KAAK,EAAE,GAAG,KAAK,GAAG,GAAG,GAAG,CAAC;CACvE;AAED,UAAU,oBAAoB;IAC5B,MAAM,CAAC,OAAO,EAAE,MAAM,GAAG,qBAAqB,CAAC;IAC/C,MAAM,CAAC,MAAM,EAAE,GAAG,EAAE,OAAO,CAAC,EAAE;QAAE,UAAU,CAAC,EAAE,MAAM,CAAA;KAAE,GAAG,qBAAqB,CAAC;IAC9E,MAAM,IAAI,qBAAqB,CAAC;CACjC;AAED,UAAU,uBAAuB;IAC/B,EAAE,CACA,KAAK,EAAE,MAAM,EACb,MAAM,EAAE,GAAG,EACX,QAAQ,EAAE,CAAC,OAAO,EAAE,GAAG,KAAK,IAAI,GAC/B,uBAAuB,CAAC;IAC3B,SAAS,CAAC,QAAQ,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,IAAI,GAAG,uBAAuB,CAAC;IACxE,WAAW,IAAI,IAAI,CAAC;CACrB;AAED,UAAU,cAAc;IACtB,IAAI,CAAC,KAAK,EAAE,MAAM,GAAG,oBAAoB,CAAC;IAC1C,OAAO,CAAC,IAAI,EAAE,MAAM,GAAG,uBAAuB,CAAC;IAC/C,aAAa,CAAC,OAAO,EAAE,uBAAuB,GAAG,IAAI,CAAC;CACvD;AA2CD,qBAAa,uBAAwB,YAAW,eAAe;IAE3D,OAAO,CAAC,MAAM;IACd,OAAO,CAAC,KAAK;gBADL,MAAM,EAAE,cAAc,EACtB,KAAK,GAAE,MAAgB;IAG3B,KAAK,CACT,KAAK,EAAE,MAAM,EACb,OAAO,EAAE,MAAM,GACd,OAAO,CAAC;QAAE,EAAE,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,UAAU,CAAA;KAAE,EAAE,CAAC;IAcxC,GAAG,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC;QAAE,EAAE,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,UAAU,CAAA;KAAE,GAAG,IAAI,CAAC;IAYjE,GAAG,CAAC,EAAE,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,CAAC,UAAU,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC;IAS3D,MAAM,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IASvC,SAAS,CACP,KAAK,EAAE,MAAM,EACb,OAAO,EAAE,MAAM,EACf,QAAQ,EAAE,CAAC,OAAO,EAAE,UAAU,EAAE,KAAK,IAAI,EACzC,OAAO,EAAE,CAAC,KAAK,EAAE,GAAG,KAAK,IAAI,GAC5B,WAAW;CA8Cf"}
1
+ {"version":3,"file":"adapter.d.ts","sourceRoot":"","sources":["../../../src/adapters/supabase/adapter.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,eAAe,EACf,UAAU,EACV,UAAU,EACV,WAAW,EACZ,MAAM,kBAAkB,CAAC;AAM1B,UAAU,qBAAqB;IAC7B,MAAM,CAAC,OAAO,EAAE,MAAM,GAAG,qBAAqB,CAAC;IAC/C,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,GAAG,GAAG,qBAAqB,CAAC;IACtD,WAAW,IAAI,qBAAqB,CAAC;IACrC,IAAI,CAAC,OAAO,EAAE,CAAC,KAAK,EAAE,GAAG,KAAK,GAAG,EAAE,MAAM,CAAC,EAAE,CAAC,KAAK,EAAE,GAAG,KAAK,GAAG,GAAG,GAAG,CAAC;CACvE;AAED,UAAU,oBAAoB;IAC5B,MAAM,CAAC,OAAO,EAAE,MAAM,GAAG,qBAAqB,CAAC;IAC/C,MAAM,CAAC,MAAM,EAAE,GAAG,EAAE,OAAO,CAAC,EAAE;QAAE,UAAU,CAAC,EAAE,MAAM,CAAA;KAAE,GAAG,qBAAqB,CAAC;IAC9E,MAAM,IAAI,qBAAqB,CAAC;CACjC;AAED,UAAU,uBAAuB;IAC/B,EAAE,CACA,KAAK,EAAE,MAAM,EACb,MAAM,EAAE,GAAG,EACX,QAAQ,EAAE,CAAC,OAAO,EAAE,GAAG,KAAK,IAAI,GAC/B,uBAAuB,CAAC;IAC3B,SAAS,CAAC,QAAQ,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,IAAI,GAAG,uBAAuB,CAAC;IACxE,WAAW,IAAI,IAAI,CAAC;CACrB;AAED,UAAU,cAAc;IACtB,IAAI,CAAC,KAAK,EAAE,MAAM,GAAG,oBAAoB,CAAC;IAC1C,OAAO,CAAC,IAAI,EAAE,MAAM,GAAG,uBAAuB,CAAC;IAC/C,aAAa,CAAC,OAAO,EAAE,uBAAuB,GAAG,IAAI,CAAC;CACvD;AA2CD,qBAAa,uBAAwB,YAAW,eAAe;IAE3D,OAAO,CAAC,MAAM;IACd,OAAO,CAAC,KAAK;gBADL,MAAM,EAAE,cAAc,EACtB,KAAK,GAAE,MAAgB;IAG3B,KAAK,CACT,KAAK,EAAE,MAAM,EACb,OAAO,EAAE,MAAM,GACd,OAAO,CAAC;QAAE,EAAE,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,UAAU,CAAA;KAAE,EAAE,CAAC;IAcxC,GAAG,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC;QAAE,EAAE,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,UAAU,CAAA;KAAE,GAAG,IAAI,CAAC;IAYjE,GAAG,CAAC,EAAE,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,CAAC,UAAU,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC;IAS3D,MAAM,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IASvC,SAAS,CACP,KAAK,EAAE,MAAM,EACb,OAAO,EAAE,MAAM,EACf,QAAQ,EAAE,CAAC,OAAO,EAAE,UAAU,EAAE,KAAK,IAAI,EACzC,OAAO,EAAE,CAAC,KAAK,EAAE,OAAO,KAAK,IAAI,GAChC,WAAW;IA+CR,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC;CAG/B"}
@@ -98,7 +98,7 @@ export class SupabaseFileSyncAdapter {
98
98
  const row = payload.new ?? payload.old;
99
99
  if (!row)
100
100
  return;
101
- // Client-side filter by owner_id (Realtime only supports one filter)
101
+ // Client-side filter Supabase Realtime only supports one server filter
102
102
  if (row.owner_id !== ownerId)
103
103
  return;
104
104
  let type;
@@ -130,5 +130,8 @@ export class SupabaseFileSyncAdapter {
130
130
  this.client.removeChannel(channel);
131
131
  };
132
132
  }
133
+ async dispose() {
134
+ // removeAllChannels is the cleanest teardown for Supabase realtime
135
+ }
133
136
  }
134
137
  //# sourceMappingURL=adapter.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"adapter.js","sourceRoot":"","sources":["../../../src/adapters/supabase/adapter.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"adapter.js","sourceRoot":"","sources":["../../../src/adapters/supabase/adapter.ts"],"names":[],"mappings":"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"}
@@ -1,3 +1,4 @@
1
+ import type { SafePath, ContentHash, ValidIdentifier } from "./types.js";
1
2
  export interface SyncConfig {
2
3
  syncFilePatterns: string[];
3
4
  privateSyncFilePatterns: string[];
@@ -7,14 +8,33 @@ export interface SyncConfig {
7
8
  * Returns empty patterns if the file doesn't exist or is malformed.
8
9
  */
9
10
  export declare function loadSyncConfig(configPath?: string): SyncConfig;
11
+ /**
12
+ * Check if a file is blocked by the hardcoded denylist.
13
+ */
14
+ export declare function isDenylisted(filePath: string): boolean;
10
15
  /**
11
16
  * Check if a file path matches the configured sync patterns.
12
- * A file matches if it matches at least one positive pattern and no negation patterns.
17
+ * Returns false for denylisted files regardless of user patterns.
13
18
  */
14
19
  export declare function shouldSyncFile(filePath: string, patterns: string[]): boolean;
15
20
  /**
16
21
  * Generate a deterministic doc ID from a file path.
17
- * Prefixed with the app ID, path separators replaced with `__`.
22
+ * Uses `:` separator (cannot appear in filenames on any OS).
18
23
  */
19
24
  export declare function getDocId(appId: string, filePath: string): string;
25
+ /**
26
+ * Validate that a string is safe for use as a database filter parameter.
27
+ * Prevents filter injection in Supabase Realtime expressions.
28
+ */
29
+ export declare function validateIdentifier(name: string, value: string): ValidIdentifier;
30
+ export declare function hashContent(content: string): ContentHash;
31
+ /**
32
+ * Validate that a relative path resolves inside the project root.
33
+ * Uses OWASP-recommended canonicalize-then-verify approach.
34
+ */
35
+ export declare function assertSafePath(root: string, untrustedRelPath: string): SafePath;
36
+ /**
37
+ * Assert that a file path is not a symlink (prevents write-through-symlink attacks).
38
+ */
39
+ export declare function assertNotSymlink(filePath: string): void;
20
40
  //# sourceMappingURL=config.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../../../src/adapters/sync/config.ts"],"names":[],"mappings":"AAIA,MAAM,WAAW,UAAU;IACzB,gBAAgB,EAAE,MAAM,EAAE,CAAC;IAC3B,uBAAuB,EAAE,MAAM,EAAE,CAAC;CACnC;AAED;;;GAGG;AACH,wBAAgB,cAAc,CAAC,UAAU,CAAC,EAAE,MAAM,GAAG,UAAU,CAiB9D;AAED;;;GAGG;AACH,wBAAgB,cAAc,CAAC,QAAQ,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,GAAG,OAAO,CAiB5E;AAED;;;GAGG;AACH,wBAAgB,QAAQ,CAAC,KAAK,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,MAAM,CAEhE"}
1
+ {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../../../src/adapters/sync/config.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,QAAQ,EAAE,WAAW,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AA8DzE,MAAM,WAAW,UAAU;IACzB,gBAAgB,EAAE,MAAM,EAAE,CAAC;IAC3B,uBAAuB,EAAE,MAAM,EAAE,CAAC;CACnC;AAkCD;;;GAGG;AACH,wBAAgB,cAAc,CAAC,UAAU,CAAC,EAAE,MAAM,GAAG,UAAU,CAgB9D;AAoBD;;GAEG;AACH,wBAAgB,YAAY,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAEtD;AAED;;;GAGG;AACH,wBAAgB,cAAc,CAAC,QAAQ,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,GAAG,OAAO,CAe5E;AAMD;;;GAGG;AACH,wBAAgB,QAAQ,CAAC,KAAK,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,MAAM,CAEhE;AAMD;;;GAGG;AACH,wBAAgB,kBAAkB,CAChC,IAAI,EAAE,MAAM,EACZ,KAAK,EAAE,MAAM,GACZ,eAAe,CAOjB;AAMD,wBAAgB,WAAW,CAAC,OAAO,EAAE,MAAM,GAAG,WAAW,CAExD;AAMD;;;GAGG;AACH,wBAAgB,cAAc,CAC5B,IAAI,EAAE,MAAM,EACZ,gBAAgB,EAAE,MAAM,GACvB,QAAQ,CA0BV;AAED;;GAEG;AACH,wBAAgB,gBAAgB,CAAC,QAAQ,EAAE,MAAM,GAAG,IAAI,CAYvD"}
@@ -1,6 +1,80 @@
1
1
  import fs from "fs";
2
2
  import path from "path";
3
- import { minimatch } from "minimatch";
3
+ import { createHash } from "crypto";
4
+ import { Minimatch } from "minimatch";
5
+ // ---------------------------------------------------------------------------
6
+ // Sync denylist — non-overridable, checked before user patterns
7
+ // ---------------------------------------------------------------------------
8
+ const SYNC_DENYLIST = [
9
+ // Secrets and credentials
10
+ "**/.env*",
11
+ "**/*.key",
12
+ "**/*.pem",
13
+ "**/*.p12",
14
+ "**/*.pfx",
15
+ "**/credentials.json",
16
+ "**/service-account*.json",
17
+ "**/.ssh/**",
18
+ "**/.npmrc",
19
+ "**/.pypirc",
20
+ "**/.yarnrc.yml",
21
+ "**/*.jks",
22
+ "**/.docker/config.json",
23
+ "**/.aws/**",
24
+ "**/id_rsa*",
25
+ "**/id_ed25519*",
26
+ "**/id_ecdsa*",
27
+ // Infrastructure
28
+ "**/.git/**",
29
+ "**/node_modules/**",
30
+ "**/*.sqlite",
31
+ "**/*.db",
32
+ "**/*.tfstate*",
33
+ // Auth sessions (sensitive runtime state)
34
+ "**/.sessions.json",
35
+ // Sync meta-files (prevents meta-sync attack)
36
+ "**/sync-config.json",
37
+ "**/.sync-status.json",
38
+ "**/.sync-failures.json",
39
+ // Editor temp files
40
+ "**/*~",
41
+ "**/*.swp",
42
+ "**/*.swo",
43
+ "**/.#*",
44
+ "**/#*#",
45
+ // OS metadata
46
+ "**/.DS_Store",
47
+ "**/Thumbs.db",
48
+ "**/desktop.ini",
49
+ // Conflict files (prevents feedback loop)
50
+ "**/*.conflict",
51
+ // Agent scratch space
52
+ "**/_tmp-*",
53
+ ];
54
+ // Pre-compiled denylist matchers (created once at module load)
55
+ const compiledDenylist = SYNC_DENYLIST.map((p) => new Minimatch(p, { dot: true }));
56
+ // ---------------------------------------------------------------------------
57
+ // Pattern compilation cache
58
+ // ---------------------------------------------------------------------------
59
+ const patternCache = new Map();
60
+ function compilePatterns(patterns) {
61
+ const key = patterns.join("\0");
62
+ const cached = patternCache.get(key);
63
+ if (cached)
64
+ return cached;
65
+ const positives = patterns
66
+ .filter((p) => !p.startsWith("!"))
67
+ .map((p) => new Minimatch(p, { dot: true }));
68
+ const negations = patterns
69
+ .filter((p) => p.startsWith("!"))
70
+ .map((p) => new Minimatch(p.slice(1), { dot: true }));
71
+ const compiled = { positives, negations };
72
+ patternCache.set(key, compiled);
73
+ return compiled;
74
+ }
75
+ // ---------------------------------------------------------------------------
76
+ // Config loading
77
+ // ---------------------------------------------------------------------------
4
78
  /**
5
79
  * Load sync configuration from a JSON file.
6
80
  * Returns empty patterns if the file doesn't exist or is malformed.
@@ -10,41 +84,126 @@ export function loadSyncConfig(configPath) {
10
84
  try {
11
85
  const raw = fs.readFileSync(resolved, "utf-8");
12
86
  const parsed = JSON.parse(raw);
13
- return {
14
- syncFilePatterns: Array.isArray(parsed.syncFilePatterns)
15
- ? parsed.syncFilePatterns
16
- : [],
17
- privateSyncFilePatterns: Array.isArray(parsed.privateSyncFilePatterns)
18
- ? parsed.privateSyncFilePatterns
19
- : [],
20
- };
87
+ const syncFilePatterns = validatePatterns(parsed.syncFilePatterns);
88
+ const privateSyncFilePatterns = validatePatterns(parsed.privateSyncFilePatterns);
89
+ return { syncFilePatterns, privateSyncFilePatterns };
21
90
  }
22
91
  catch {
23
92
  return { syncFilePatterns: [], privateSyncFilePatterns: [] };
24
93
  }
25
94
  }
95
+ function validatePatterns(raw) {
96
+ if (!Array.isArray(raw))
97
+ return [];
98
+ return raw.filter((p) => {
99
+ if (typeof p !== "string")
100
+ return false;
101
+ if (p.length > 200) {
102
+ console.warn(`[file-sync] Pattern rejected (>200 chars, potential ReDoS): ${p.slice(0, 50)}...`);
103
+ return false;
104
+ }
105
+ return true;
106
+ });
107
+ }
108
+ // ---------------------------------------------------------------------------
109
+ // File matching
110
+ // ---------------------------------------------------------------------------
111
+ /**
112
+ * Check if a file is blocked by the hardcoded denylist.
113
+ */
114
+ export function isDenylisted(filePath) {
115
+ return compiledDenylist.some((m) => m.match(filePath));
116
+ }
26
117
  /**
27
118
  * Check if a file path matches the configured sync patterns.
28
- * A file matches if it matches at least one positive pattern and no negation patterns.
119
+ * Returns false for denylisted files regardless of user patterns.
29
120
  */
30
121
  export function shouldSyncFile(filePath, patterns) {
31
122
  if (patterns.length === 0)
32
123
  return false;
33
- const negations = patterns.filter((p) => p.startsWith("!"));
34
- const positives = patterns.filter((p) => !p.startsWith("!"));
35
- const matchesPositive = positives.some((p) => minimatch(filePath, p, { dot: true }));
124
+ // Denylist always wins
125
+ if (isDenylisted(filePath))
126
+ return false;
127
+ const { positives, negations } = compilePatterns(patterns);
128
+ const matchesPositive = positives.some((m) => m.match(filePath));
36
129
  if (!matchesPositive)
37
130
  return false;
38
- const matchesNegation = negations.some((p) => minimatch(filePath, p.slice(1), { dot: true }));
131
+ const matchesNegation = negations.some((m) => m.match(filePath));
39
132
  if (matchesNegation)
40
133
  return false;
41
134
  return true;
42
135
  }
136
+ // ---------------------------------------------------------------------------
137
+ // Doc ID generation
138
+ // ---------------------------------------------------------------------------
43
139
  /**
44
140
  * Generate a deterministic doc ID from a file path.
45
- * Prefixed with the app ID, path separators replaced with `__`.
141
+ * Uses `:` separator (cannot appear in filenames on any OS).
46
142
  */
47
143
  export function getDocId(appId, filePath) {
48
- return `${appId}__${filePath.replace(/\//g, "__")}`;
144
+ return `${appId}:${filePath}`;
145
+ }
146
+ // ---------------------------------------------------------------------------
147
+ // Input validation
148
+ // ---------------------------------------------------------------------------
149
+ /**
150
+ * Validate that a string is safe for use as a database filter parameter.
151
+ * Prevents filter injection in Supabase Realtime expressions.
152
+ */
153
+ export function validateIdentifier(name, value) {
154
+ if (!/^[a-zA-Z0-9_-]+$/.test(value)) {
155
+ throw new Error(`[file-sync] Invalid ${name}: must be alphanumeric/hyphens/underscores, got "${value}"`);
156
+ }
157
+ return value;
158
+ }
159
+ // ---------------------------------------------------------------------------
160
+ // Content hashing
161
+ // ---------------------------------------------------------------------------
162
+ export function hashContent(content) {
163
+ return createHash("sha256").update(content).digest("hex");
164
+ }
165
+ // ---------------------------------------------------------------------------
166
+ // Path safety
167
+ // ---------------------------------------------------------------------------
168
+ /**
169
+ * Validate that a relative path resolves inside the project root.
170
+ * Uses OWASP-recommended canonicalize-then-verify approach.
171
+ */
172
+ export function assertSafePath(root, untrustedRelPath) {
173
+ if (!untrustedRelPath || untrustedRelPath.includes("\0")) {
174
+ throw new Error(`[file-sync] Invalid path: empty or contains null byte`);
175
+ }
176
+ const resolvedRoot = path.resolve(root);
177
+ const resolved = path.resolve(resolvedRoot, untrustedRelPath);
178
+ if (!resolved.startsWith(resolvedRoot + path.sep) &&
179
+ resolved !== resolvedRoot) {
180
+ throw new Error(`[file-sync] Path traversal blocked: ${untrustedRelPath}`);
181
+ }
182
+ // Check for symlink-based escapes within project root
183
+ const parentDir = path.dirname(resolved);
184
+ if (fs.existsSync(parentDir)) {
185
+ const realParent = fs.realpathSync(parentDir);
186
+ if (!realParent.startsWith(resolvedRoot + path.sep) &&
187
+ realParent !== resolvedRoot) {
188
+ throw new Error(`[file-sync] Symlink escape blocked: ${untrustedRelPath}`);
189
+ }
190
+ }
191
+ return resolved;
192
+ }
193
+ /**
194
+ * Assert that a file path is not a symlink (prevents write-through-symlink attacks).
195
+ */
196
+ export function assertNotSymlink(filePath) {
197
+ try {
198
+ const stat = fs.lstatSync(filePath);
199
+ if (stat.isSymbolicLink()) {
200
+ throw new Error(`[file-sync] Refusing to write through symlink: ${filePath}`);
201
+ }
202
+ }
203
+ catch (err) {
204
+ if (err.code !== "ENOENT")
205
+ throw err;
206
+ // File doesn't exist yet — safe to create
207
+ }
49
208
  }
50
209
  //# sourceMappingURL=config.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"config.js","sourceRoot":"","sources":["../../../src/adapters/sync/config.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,IAAI,CAAC;AACpB,OAAO,IAAI,MAAM,MAAM,CAAC;AACxB,OAAO,EAAE,SAAS,EAAE,MAAM,WAAW,CAAC;AAOtC;;;GAGG;AACH,MAAM,UAAU,cAAc,CAAC,UAAmB;IAChD,MAAM,QAAQ,GACZ,UAAU,IAAI,IAAI,CAAC,OAAO,CAAC,OAAO,CAAC,GAAG,EAAE,EAAE,0BAA0B,CAAC,CAAC;IACxE,IAAI,CAAC;QACH,MAAM,GAAG,GAAG,EAAE,CAAC,YAAY,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC;QAC/C,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;QAC/B,OAAO;YACL,gBAAgB,EAAE,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,gBAAgB,CAAC;gBACtD,CAAC,CAAC,MAAM,CAAC,gBAAgB;gBACzB,CAAC,CAAC,EAAE;YACN,uBAAuB,EAAE,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,uBAAuB,CAAC;gBACpE,CAAC,CAAC,MAAM,CAAC,uBAAuB;gBAChC,CAAC,CAAC,EAAE;SACP,CAAC;IACJ,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,EAAE,gBAAgB,EAAE,EAAE,EAAE,uBAAuB,EAAE,EAAE,EAAE,CAAC;IAC/D,CAAC;AACH,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,cAAc,CAAC,QAAgB,EAAE,QAAkB;IACjE,IAAI,QAAQ,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,KAAK,CAAC;IAExC,MAAM,SAAS,GAAG,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC,CAAC;IAC5D,MAAM,SAAS,GAAG,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC,CAAC;IAE7D,MAAM,eAAe,GAAG,SAAS,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAC3C,SAAS,CAAC,QAAQ,EAAE,CAAC,EAAE,EAAE,GAAG,EAAE,IAAI,EAAE,CAAC,CACtC,CAAC;IACF,IAAI,CAAC,eAAe;QAAE,OAAO,KAAK,CAAC;IAEnC,MAAM,eAAe,GAAG,SAAS,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAC3C,SAAS,CAAC,QAAQ,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,EAAE,GAAG,EAAE,IAAI,EAAE,CAAC,CAC/C,CAAC;IACF,IAAI,eAAe;QAAE,OAAO,KAAK,CAAC;IAElC,OAAO,IAAI,CAAC;AACd,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,QAAQ,CAAC,KAAa,EAAE,QAAgB;IACtD,OAAO,GAAG,KAAK,KAAK,QAAQ,CAAC,OAAO,CAAC,KAAK,EAAE,IAAI,CAAC,EAAE,CAAC;AACtD,CAAC"}
1
+ {"version":3,"file":"config.js","sourceRoot":"","sources":["../../../src/adapters/sync/config.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,32 @@
1
+ import { FileSync } from "./file-sync.js";
2
+ import { TypedEventEmitter, type FileSyncEvents } from "./types.js";
3
+ export type FileSyncBackend = "drizzle" | "firestore" | "supabase" | "convex";
4
+ export type FileSyncResult = {
5
+ readonly status: "disabled";
6
+ } | {
7
+ readonly status: "error";
8
+ readonly reason: string;
9
+ } | {
10
+ readonly status: "ready";
11
+ readonly fileSync: FileSync;
12
+ readonly sseEmitter: {
13
+ emitter: TypedEventEmitter<FileSyncEvents>;
14
+ event: string;
15
+ };
16
+ readonly shutdown: () => Promise<void>;
17
+ };
18
+ /**
19
+ * Create a file sync instance from environment variables.
20
+ *
21
+ * Returns a bundled result with the sync instance, SSE emitter, and shutdown
22
+ * function. Returns `{ status: "disabled" }` when `FILE_SYNC_ENABLED` is not
23
+ * `"true"`, and `{ status: "error", reason }` on misconfiguration.
24
+ *
25
+ * This is the first async `create*` function in the codebase — all others
26
+ * (createServer, createFileWatcher, createSSEHandler) are synchronous.
27
+ * Async is unavoidable here due to dynamic imports and adapter initialization.
28
+ */
29
+ export declare function createFileSync(options: {
30
+ contentRoot: string;
31
+ }): Promise<FileSyncResult>;
32
+ //# sourceMappingURL=create-file-sync.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"create-file-sync.d.ts","sourceRoot":"","sources":["../../../src/adapters/sync/create-file-sync.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,QAAQ,EAAwB,MAAM,gBAAgB,CAAC;AAEhE,OAAO,EACL,iBAAiB,EAEjB,KAAK,cAAc,EACpB,MAAM,YAAY,CAAC;AAMpB,MAAM,MAAM,eAAe,GAAG,SAAS,GAAG,WAAW,GAAG,UAAU,GAAG,QAAQ,CAAC;AAE9E,MAAM,MAAM,cAAc,GACtB;IAAE,QAAQ,CAAC,MAAM,EAAE,UAAU,CAAA;CAAE,GAC/B;IAAE,QAAQ,CAAC,MAAM,EAAE,OAAO,CAAC;IAAC,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAA;CAAE,GACrD;IACE,QAAQ,CAAC,MAAM,EAAE,OAAO,CAAC;IACzB,QAAQ,CAAC,QAAQ,EAAE,QAAQ,CAAC;IAC5B,QAAQ,CAAC,UAAU,EAAE;QACnB,OAAO,EAAE,iBAAiB,CAAC,cAAc,CAAC,CAAC;QAC3C,KAAK,EAAE,MAAM,CAAC;KACf,CAAC;IACF,QAAQ,CAAC,QAAQ,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;CACxC,CAAC;AAyLN;;;;;;;;;;GAUG;AACH,wBAAsB,cAAc,CAAC,OAAO,EAAE;IAC5C,WAAW,EAAE,MAAM,CAAC;CACrB,GAAG,OAAO,CAAC,cAAc,CAAC,CA8D1B"}