@agent-native/core 0.2.1 → 0.2.7-dev.712fefc
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.
- package/README.md +122 -0
- package/dist/adapters/firestore/adapter.d.ts +47 -0
- package/dist/adapters/firestore/adapter.d.ts.map +1 -0
- package/dist/adapters/firestore/adapter.js +45 -0
- package/dist/adapters/firestore/adapter.js.map +1 -0
- package/dist/adapters/firestore/index.d.ts +3 -3
- package/dist/adapters/firestore/index.d.ts.map +1 -1
- package/dist/adapters/firestore/index.js +2 -3
- package/dist/adapters/firestore/index.js.map +1 -1
- package/dist/adapters/neon/adapter.d.ts +28 -0
- package/dist/adapters/neon/adapter.d.ts.map +1 -0
- package/dist/adapters/neon/adapter.js +119 -0
- package/dist/adapters/neon/adapter.js.map +1 -0
- package/dist/adapters/neon/index.d.ts +3 -0
- package/dist/adapters/neon/index.d.ts.map +1 -0
- package/dist/adapters/neon/index.js +3 -0
- package/dist/adapters/neon/index.js.map +1 -0
- package/dist/adapters/supabase/adapter.d.ts +42 -0
- package/dist/adapters/supabase/adapter.d.ts.map +1 -0
- package/dist/adapters/supabase/adapter.js +126 -0
- package/dist/adapters/supabase/adapter.js.map +1 -0
- package/dist/adapters/supabase/index.d.ts +3 -0
- package/dist/adapters/supabase/index.d.ts.map +1 -0
- package/dist/adapters/supabase/index.js +3 -0
- package/dist/adapters/supabase/index.js.map +1 -0
- package/dist/adapters/{firestore → sync}/config.d.ts +1 -1
- package/dist/adapters/sync/config.d.ts.map +1 -0
- package/dist/adapters/{firestore → sync}/config.js +1 -1
- package/dist/adapters/sync/config.js.map +1 -0
- package/dist/adapters/{firestore/sync.d.ts → sync/file-sync.d.ts} +6 -37
- package/dist/adapters/sync/file-sync.d.ts.map +1 -0
- package/dist/adapters/{firestore/sync.js → sync/file-sync.js} +45 -59
- package/dist/adapters/sync/file-sync.js.map +1 -0
- package/dist/adapters/sync/index.d.ts +5 -0
- package/dist/adapters/sync/index.d.ts.map +1 -0
- package/dist/adapters/sync/index.js +4 -0
- package/dist/adapters/sync/index.js.map +1 -0
- package/dist/adapters/sync/merge.d.ts.map +1 -0
- package/dist/adapters/sync/merge.js.map +1 -0
- package/dist/adapters/sync/types.d.ts +28 -0
- package/dist/adapters/sync/types.d.ts.map +1 -0
- package/dist/adapters/sync/types.js +2 -0
- package/dist/adapters/sync/types.js.map +1 -0
- package/dist/cli/create.d.ts.map +1 -1
- package/dist/cli/create.js +41 -3
- package/dist/cli/create.js.map +1 -1
- package/dist/cli/index.js +15 -10
- package/dist/cli/index.js.map +1 -1
- package/dist/client/components/ApiKeySettings.d.ts +12 -0
- package/dist/client/components/ApiKeySettings.d.ts.map +1 -0
- package/dist/client/components/ApiKeySettings.js +203 -0
- package/dist/client/components/ApiKeySettings.js.map +1 -0
- package/dist/client/components/MissingKeyCard.d.ts +7 -0
- package/dist/client/components/MissingKeyCard.d.ts.map +1 -0
- package/dist/client/components/MissingKeyCard.js +27 -0
- package/dist/client/components/MissingKeyCard.js.map +1 -0
- package/dist/client/index.d.ts +1 -0
- package/dist/client/index.d.ts.map +1 -1
- package/dist/client/index.js +1 -0
- package/dist/client/index.js.map +1 -1
- package/dist/client/use-file-watcher.d.ts.map +1 -1
- package/dist/client/use-file-watcher.js +24 -14
- package/dist/client/use-file-watcher.js.map +1 -1
- package/dist/index.browser.d.ts +1 -1
- package/dist/index.browser.d.ts.map +1 -1
- package/dist/index.browser.js +1 -1
- package/dist/index.browser.js.map +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/dist/scripts/runner.js +1 -1
- package/dist/scripts/runner.js.map +1 -1
- package/dist/server/create-server.d.ts +11 -0
- package/dist/server/create-server.d.ts.map +1 -1
- package/dist/server/create-server.js +102 -0
- package/dist/server/create-server.js.map +1 -1
- package/dist/server/index.d.ts +2 -1
- package/dist/server/index.d.ts.map +1 -1
- package/dist/server/index.js +1 -0
- package/dist/server/index.js.map +1 -1
- package/dist/server/missing-key.d.ts +17 -0
- package/dist/server/missing-key.d.ts.map +1 -0
- package/dist/server/missing-key.js +17 -0
- package/dist/server/missing-key.js.map +1 -0
- package/dist/shared/agent-env.d.ts +23 -0
- package/dist/shared/agent-env.d.ts.map +1 -0
- package/dist/shared/agent-env.js +36 -0
- package/dist/shared/agent-env.js.map +1 -0
- package/dist/shared/index.d.ts +1 -0
- package/dist/shared/index.d.ts.map +1 -1
- package/dist/shared/index.js +1 -0
- package/dist/shared/index.js.map +1 -1
- package/dist/vite/client.d.ts.map +1 -1
- package/dist/vite/client.js +31 -0
- package/dist/vite/client.js.map +1 -1
- package/package.json +27 -5
- package/src/templates/default/.claude/settings.json +68 -0
- package/src/templates/default/AGENTS.md +4 -0
- package/src/templates/default/data/.gitkeep +0 -0
- package/src/templates/default/learnings.md +0 -0
- package/dist/adapters/firestore/config.d.ts.map +0 -1
- package/dist/adapters/firestore/config.js.map +0 -1
- package/dist/adapters/firestore/merge.d.ts.map +0 -1
- package/dist/adapters/firestore/merge.js.map +0 -1
- package/dist/adapters/firestore/sync.d.ts.map +0 -1
- package/dist/adapters/firestore/sync.js.map +0 -1
- /package/dist/adapters/{firestore → sync}/merge.d.ts +0 -0
- /package/dist/adapters/{firestore → sync}/merge.js +0 -0
package/README.md
ADDED
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
# Agent-Native
|
|
2
|
+
|
|
3
|
+
**Agentic applications you own.**
|
|
4
|
+
|
|
5
|
+
Agent-native is an open source framework for building apps where an AI agent, a full application UI, and a computer work together as one. Fork a template, launch in minutes, and let AI help you customize it to your exact needs.
|
|
6
|
+
|
|
7
|
+
Other products charge you for rigid software you can't change. Agent-native gives you the code — you own it, you customize it, you evolve it with AI.
|
|
8
|
+
|
|
9
|
+
## Templates
|
|
10
|
+
|
|
11
|
+
Start from a production-ready template. Each one replaces tools you're paying for — except you own everything and can customize it however you want.
|
|
12
|
+
|
|
13
|
+
<table>
|
|
14
|
+
<tr>
|
|
15
|
+
<td width="20%" align="center" valign="top">
|
|
16
|
+
|
|
17
|
+
**Analytics**
|
|
18
|
+
|
|
19
|
+
<a href="https://agent-native.com/templates/analytics"><img src="https://cdn.builder.io/api/v1/image/assets%2FYJIGb4i01jvw0SRdL5Bt%2F4933a80cc3134d7e874631f688be828a?format=webp&width=800" alt="Analytics template" width="100%" /></a>
|
|
20
|
+
|
|
21
|
+
**AI-Native Amplitude, Mixpanel**
|
|
22
|
+
|
|
23
|
+
Connect any data source, prompt for any chart. Build reusable dashboards, not throwaway Q&A.
|
|
24
|
+
|
|
25
|
+
</td>
|
|
26
|
+
<td width="20%" align="center" valign="top">
|
|
27
|
+
|
|
28
|
+
**Content**
|
|
29
|
+
|
|
30
|
+
<a href="https://agent-native.com/templates/content"><img src="https://cdn.builder.io/api/v1/image/assets%2FYJIGb4i01jvw0SRdL5Bt%2F89bcfc6106304bfbaf8ec8a7ccd721eb?format=webp&width=800" alt="Content template" width="100%" /></a>
|
|
31
|
+
|
|
32
|
+
**AI-Native Notion, Google Docs**
|
|
33
|
+
|
|
34
|
+
Write and organize content with an agent that knows your brand and publishing workflow.
|
|
35
|
+
|
|
36
|
+
</td>
|
|
37
|
+
<td width="20%" align="center" valign="top">
|
|
38
|
+
|
|
39
|
+
**Slides**
|
|
40
|
+
|
|
41
|
+
<a href="https://agent-native.com/templates/slides"><img src="https://cdn.builder.io/api/v1/image/assets%2FYJIGb4i01jvw0SRdL5Bt%2F2c09b451d40c4a74a89a38d69170c2d8?format=webp&width=800" alt="Slides template" width="100%" /></a>
|
|
42
|
+
|
|
43
|
+
**AI-Native Google Slides, Pitch**
|
|
44
|
+
|
|
45
|
+
Generate and edit React-based presentations via prompt or point-and-click.
|
|
46
|
+
|
|
47
|
+
</td>
|
|
48
|
+
<td width="20%" align="center" valign="top">
|
|
49
|
+
|
|
50
|
+
**Video**
|
|
51
|
+
|
|
52
|
+
<a href="https://agent-native.com/templates/video"><img src="https://cdn.builder.io/api/v1/image/assets%2FYJIGb4i01jvw0SRdL5Bt%2F6b8bfcc18a1d4c47a491da3b2d4148a4?format=webp&width=800" alt="Video template" width="100%" /></a>
|
|
53
|
+
|
|
54
|
+
**AI-Native video editing**
|
|
55
|
+
|
|
56
|
+
Create and edit Remotion video compositions with agent assistance.
|
|
57
|
+
|
|
58
|
+
</td>
|
|
59
|
+
<td width="20%" align="center" valign="top">
|
|
60
|
+
|
|
61
|
+
**Calendar**
|
|
62
|
+
|
|
63
|
+
<a href="https://agent-native.com/templates/calendar"><img src="https://cdn.builder.io/api/v1/image/assets%2FYJIGb4i01jvw0SRdL5Bt%2Fcalendar-template-screenshot?format=webp&width=800" alt="Calendar template" width="100%" /></a>
|
|
64
|
+
|
|
65
|
+
**AI-Native Google Calendar, Calendly**
|
|
66
|
+
|
|
67
|
+
Manage events, sync with Google Calendar, and share a public booking page with AI scheduling.
|
|
68
|
+
|
|
69
|
+
</td>
|
|
70
|
+
</tr>
|
|
71
|
+
<tr>
|
|
72
|
+
<td align="center"><a href="https://agent-native.com/templates/analytics"><img src=".github/assets/launch-button.svg" alt="Launch Analytics" height="36" /></a></td>
|
|
73
|
+
<td align="center"><a href="https://agent-native.com/templates/content"><img src=".github/assets/launch-button.svg" alt="Launch Content" height="36" /></a></td>
|
|
74
|
+
<td align="center"><a href="https://agent-native.com/templates/slides"><img src=".github/assets/launch-button.svg" alt="Launch Slides" height="36" /></a></td>
|
|
75
|
+
<td align="center"><a href="https://agent-native.com/templates/video"><img src=".github/assets/launch-button.svg" alt="Launch Video" height="36" /></a></td>
|
|
76
|
+
<td align="center"><a href="https://agent-native.com/templates/calendar"><img src=".github/assets/launch-button.svg" alt="Launch Calendar" height="36" /></a></td>
|
|
77
|
+
</tr>
|
|
78
|
+
</table>
|
|
79
|
+
|
|
80
|
+
Every template is forkable, open source, and designed to be customized. Try them with example data before connecting your own sources.
|
|
81
|
+
|
|
82
|
+
## Quick Start
|
|
83
|
+
|
|
84
|
+
```bash
|
|
85
|
+
npx @agent-native/core create my-app
|
|
86
|
+
cd my-app
|
|
87
|
+
pnpm install
|
|
88
|
+
pnpm dev
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
Or **[launch a template](https://agent-native.com/templates)** — no setup required.
|
|
92
|
+
|
|
93
|
+
## How It Works
|
|
94
|
+
|
|
95
|
+
Agent-native apps follow five rules:
|
|
96
|
+
|
|
97
|
+
- **Files as database** — All state lives in files. The agent and UI share the same source of truth.
|
|
98
|
+
- **AI through the agent** — No inline LLM calls. The UI delegates to the agent via a chat bridge. One AI, customizable with skills and instructions.
|
|
99
|
+
- **Agent updates code** — The agent can modify the app itself. Your tools get better over time.
|
|
100
|
+
- **Real-time sync** — File watcher streams changes via SSE. Agent edits appear instantly.
|
|
101
|
+
- **Agent + UI + Computer** — The powerful trio. Everything the UI can do, the agent can do — and vice versa.
|
|
102
|
+
|
|
103
|
+
## Harnesses
|
|
104
|
+
|
|
105
|
+
Agent-native apps run inside a **harness** — a host that provides the AI agent alongside your app UI.
|
|
106
|
+
|
|
107
|
+
| | Local / Open Source | Builder Cloud |
|
|
108
|
+
|---|---|---|
|
|
109
|
+
| **Run** | Claude Code CLI or any local harness | One-click launch from templates |
|
|
110
|
+
| **Collaboration** | Solo | Real-time multiplayer |
|
|
111
|
+
| **Features** | Full permissions, full control | Visual editing, roles & permissions |
|
|
112
|
+
| **Best for** | Solo dev, local testing, OSS | Teams, production |
|
|
113
|
+
|
|
114
|
+
Your app code is identical regardless of harness. Start local, go to cloud when you need teams.
|
|
115
|
+
|
|
116
|
+
## Docs
|
|
117
|
+
|
|
118
|
+
Full documentation at **[agent-native.com](https://agent-native.com)**.
|
|
119
|
+
|
|
120
|
+
## License
|
|
121
|
+
|
|
122
|
+
MIT
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import type { FileSyncAdapter, FileRecord, FileChange, Unsubscribe } from "../sync/types.js";
|
|
2
|
+
export interface FirestoreCollection {
|
|
3
|
+
doc(id: string): FirestoreDocRef;
|
|
4
|
+
where(field: string, op: string, value: any): FirestoreQuery;
|
|
5
|
+
}
|
|
6
|
+
export interface FirestoreDocRef {
|
|
7
|
+
get(): Promise<FirestoreDocSnapshot>;
|
|
8
|
+
set(data: any, options?: {
|
|
9
|
+
merge?: boolean;
|
|
10
|
+
}): Promise<any>;
|
|
11
|
+
delete(): Promise<any>;
|
|
12
|
+
collection(name: string): FirestoreCollection;
|
|
13
|
+
}
|
|
14
|
+
export interface FirestoreQuery {
|
|
15
|
+
where(field: string, op: string, value: any): FirestoreQuery;
|
|
16
|
+
get(): Promise<FirestoreQuerySnapshot>;
|
|
17
|
+
onSnapshot(onNext: (snapshot: FirestoreQuerySnapshot) => void, onError: (error: any) => void): () => void;
|
|
18
|
+
}
|
|
19
|
+
export interface FirestoreDocSnapshot {
|
|
20
|
+
exists: boolean;
|
|
21
|
+
id: string;
|
|
22
|
+
data(): any;
|
|
23
|
+
}
|
|
24
|
+
export interface FirestoreQuerySnapshot {
|
|
25
|
+
docs: FirestoreDocSnapshot[];
|
|
26
|
+
size: number;
|
|
27
|
+
docChanges(): Array<{
|
|
28
|
+
type: "added" | "modified" | "removed";
|
|
29
|
+
doc: FirestoreDocSnapshot;
|
|
30
|
+
}>;
|
|
31
|
+
}
|
|
32
|
+
export declare class FirestoreFileSyncAdapter implements FileSyncAdapter {
|
|
33
|
+
private getCollection;
|
|
34
|
+
constructor(getCollection: () => FirestoreCollection);
|
|
35
|
+
query(appId: string, ownerId: string): Promise<{
|
|
36
|
+
id: string;
|
|
37
|
+
data: FileRecord;
|
|
38
|
+
}[]>;
|
|
39
|
+
get(id: string): Promise<{
|
|
40
|
+
id: string;
|
|
41
|
+
data: FileRecord;
|
|
42
|
+
} | null>;
|
|
43
|
+
set(id: string, record: Partial<FileRecord>): Promise<void>;
|
|
44
|
+
delete(id: string): Promise<void>;
|
|
45
|
+
subscribe(appId: string, ownerId: string, onChange: (changes: FileChange[]) => void, onError: (error: any) => void): Unsubscribe;
|
|
46
|
+
}
|
|
47
|
+
//# sourceMappingURL=adapter.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"adapter.d.ts","sourceRoot":"","sources":["../../../src/adapters/firestore/adapter.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,UAAU,EAAE,UAAU,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAM7F,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,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC;QAAE,EAAE,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,UAAU,CAAA;KAAE,EAAE,CAAC;IAYlF,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;CAgBf"}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
// ---------------------------------------------------------------------------
|
|
2
|
+
// Firestore adapter
|
|
3
|
+
// ---------------------------------------------------------------------------
|
|
4
|
+
export class FirestoreFileSyncAdapter {
|
|
5
|
+
getCollection;
|
|
6
|
+
constructor(getCollection) {
|
|
7
|
+
this.getCollection = getCollection;
|
|
8
|
+
}
|
|
9
|
+
async query(appId, ownerId) {
|
|
10
|
+
const snapshot = await this.getCollection()
|
|
11
|
+
.where("app", "==", appId)
|
|
12
|
+
.where("ownerId", "==", ownerId)
|
|
13
|
+
.get();
|
|
14
|
+
return snapshot.docs.map((doc) => ({
|
|
15
|
+
id: doc.id,
|
|
16
|
+
data: doc.data(),
|
|
17
|
+
}));
|
|
18
|
+
}
|
|
19
|
+
async get(id) {
|
|
20
|
+
const doc = await this.getCollection().doc(id).get();
|
|
21
|
+
if (!doc.exists)
|
|
22
|
+
return null;
|
|
23
|
+
return { id: doc.id, data: doc.data() };
|
|
24
|
+
}
|
|
25
|
+
async set(id, record) {
|
|
26
|
+
await this.getCollection().doc(id).set(record, { merge: true });
|
|
27
|
+
}
|
|
28
|
+
async delete(id) {
|
|
29
|
+
await this.getCollection().doc(id).delete();
|
|
30
|
+
}
|
|
31
|
+
subscribe(appId, ownerId, onChange, onError) {
|
|
32
|
+
return this.getCollection()
|
|
33
|
+
.where("app", "==", appId)
|
|
34
|
+
.where("ownerId", "==", ownerId)
|
|
35
|
+
.onSnapshot((snapshot) => {
|
|
36
|
+
const changes = snapshot.docChanges().map((change) => ({
|
|
37
|
+
type: change.type,
|
|
38
|
+
id: change.doc.id,
|
|
39
|
+
data: change.doc.data(),
|
|
40
|
+
}));
|
|
41
|
+
onChange(changes);
|
|
42
|
+
}, onError);
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
//# sourceMappingURL=adapter.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"adapter.js","sourceRoot":"","sources":["../../../src/adapters/firestore/adapter.ts"],"names":[],"mappings":"AA0CA,8EAA8E;AAC9E,oBAAoB;AACpB,8EAA8E;AAE9E,MAAM,OAAO,wBAAwB;IACf;IAApB,YAAoB,aAAwC;QAAxC,kBAAa,GAAb,aAAa,CAA2B;IAAG,CAAC;IAEhE,KAAK,CAAC,KAAK,CAAC,KAAa,EAAE,OAAe;QACxC,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,CACT,CAAC,QAAQ,EAAE,EAAE;YACX,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,EACD,OAAO,CACR,CAAC;IACN,CAAC;CACF"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export {
|
|
2
|
-
export {
|
|
3
|
-
export
|
|
1
|
+
export { FirestoreFileSyncAdapter } from "./adapter.js";
|
|
2
|
+
export type { FirestoreCollection, FirestoreDocRef, FirestoreQuery, FirestoreDocSnapshot, FirestoreQuerySnapshot, } from "./adapter.js";
|
|
3
|
+
export * from "../sync/index.js";
|
|
4
4
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/adapters/firestore/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/adapters/firestore/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,wBAAwB,EAAE,MAAM,cAAc,CAAC;AACxD,YAAY,EACV,mBAAmB,EACnB,eAAe,EACf,cAAc,EACd,oBAAoB,EACpB,sBAAsB,GACvB,MAAM,cAAc,CAAC;AACtB,cAAc,kBAAkB,CAAC"}
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
export {
|
|
2
|
-
export
|
|
3
|
-
export { loadSyncConfig, shouldSyncFile, getDocId, } from "./config.js";
|
|
1
|
+
export { FirestoreFileSyncAdapter } from "./adapter.js";
|
|
2
|
+
export * from "../sync/index.js";
|
|
4
3
|
//# sourceMappingURL=index.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/adapters/firestore/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/adapters/firestore/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,wBAAwB,EAAE,MAAM,cAAc,CAAC;AAQxD,cAAc,kBAAkB,CAAC"}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import type { FileSyncAdapter, FileRecord, FileChange, Unsubscribe } from "../sync/types.js";
|
|
2
|
+
interface NeonQueryResult {
|
|
3
|
+
rows: any[];
|
|
4
|
+
rowCount: number;
|
|
5
|
+
}
|
|
6
|
+
type NeonSql = (strings: TemplateStringsArray, ...values: any[]) => Promise<NeonQueryResult>;
|
|
7
|
+
export interface NeonAdapterOptions {
|
|
8
|
+
/** Polling interval in ms for subscribe(). Default: 2000 */
|
|
9
|
+
pollIntervalMs?: number;
|
|
10
|
+
}
|
|
11
|
+
export declare class NeonFileSyncAdapter implements FileSyncAdapter {
|
|
12
|
+
private sql;
|
|
13
|
+
private pollIntervalMs;
|
|
14
|
+
constructor(sql: NeonSql, options?: NeonAdapterOptions);
|
|
15
|
+
query(appId: string, ownerId: string): Promise<{
|
|
16
|
+
id: string;
|
|
17
|
+
data: FileRecord;
|
|
18
|
+
}[]>;
|
|
19
|
+
get(id: string): Promise<{
|
|
20
|
+
id: string;
|
|
21
|
+
data: FileRecord;
|
|
22
|
+
} | null>;
|
|
23
|
+
set(id: string, record: Partial<FileRecord>): Promise<void>;
|
|
24
|
+
delete(id: string): Promise<void>;
|
|
25
|
+
subscribe(appId: string, ownerId: string, onChange: (changes: FileChange[]) => void, onError: (error: any) => void): Unsubscribe;
|
|
26
|
+
}
|
|
27
|
+
export {};
|
|
28
|
+
//# sourceMappingURL=adapter.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"adapter.d.ts","sourceRoot":"","sources":["../../../src/adapters/neon/adapter.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,UAAU,EAAE,UAAU,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAM7F,UAAU,eAAe;IACvB,IAAI,EAAE,GAAG,EAAE,CAAC;IACZ,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED,KAAK,OAAO,GAAG,CAAC,OAAO,EAAE,oBAAoB,EAAE,GAAG,MAAM,EAAE,GAAG,EAAE,KAAK,OAAO,CAAC,eAAe,CAAC,CAAC;AA6B7F,MAAM,WAAW,kBAAkB;IACjC,4DAA4D;IAC5D,cAAc,CAAC,EAAE,MAAM,CAAC;CACzB;AAED,qBAAa,mBAAoB,YAAW,eAAe;IAIvD,OAAO,CAAC,GAAG;IAHb,OAAO,CAAC,cAAc,CAAS;gBAGrB,GAAG,EAAE,OAAO,EACpB,OAAO,CAAC,EAAE,kBAAkB;IAKxB,KAAK,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC;QAAE,EAAE,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,UAAU,CAAA;KAAE,EAAE,CAAC;IAOlF,GAAG,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC;QAAE,EAAE,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,UAAU,CAAA;KAAE,GAAG,IAAI,CAAC;IASjE,GAAG,CAAC,EAAE,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,CAAC,UAAU,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC;IAqB3D,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;CA4Df"}
|
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
// ---------------------------------------------------------------------------
|
|
2
|
+
// Column mapping helpers
|
|
3
|
+
// ---------------------------------------------------------------------------
|
|
4
|
+
/**
|
|
5
|
+
* Table schema (same as Supabase):
|
|
6
|
+
* files(id TEXT PK, path TEXT, content TEXT, app TEXT, owner_id TEXT,
|
|
7
|
+
* last_updated BIGINT, created_at BIGINT)
|
|
8
|
+
*
|
|
9
|
+
* CREATE INDEX idx_files_app_owner ON files(app, owner_id);
|
|
10
|
+
*/
|
|
11
|
+
function rowToRecord(row) {
|
|
12
|
+
return {
|
|
13
|
+
path: row.path,
|
|
14
|
+
content: row.content,
|
|
15
|
+
app: row.app,
|
|
16
|
+
ownerId: row.owner_id,
|
|
17
|
+
lastUpdated: Number(row.last_updated),
|
|
18
|
+
createdAt: row.created_at != null ? Number(row.created_at) : undefined,
|
|
19
|
+
};
|
|
20
|
+
}
|
|
21
|
+
export class NeonFileSyncAdapter {
|
|
22
|
+
sql;
|
|
23
|
+
pollIntervalMs;
|
|
24
|
+
constructor(sql, options) {
|
|
25
|
+
this.sql = sql;
|
|
26
|
+
this.pollIntervalMs = options?.pollIntervalMs ?? 2000;
|
|
27
|
+
}
|
|
28
|
+
async query(appId, ownerId) {
|
|
29
|
+
const result = await this.sql `
|
|
30
|
+
SELECT * FROM files WHERE app = ${appId} AND owner_id = ${ownerId}
|
|
31
|
+
`;
|
|
32
|
+
return result.rows.map((row) => ({ id: row.id, data: rowToRecord(row) }));
|
|
33
|
+
}
|
|
34
|
+
async get(id) {
|
|
35
|
+
const result = await this.sql `
|
|
36
|
+
SELECT * FROM files WHERE id = ${id} LIMIT 1
|
|
37
|
+
`;
|
|
38
|
+
if (result.rows.length === 0)
|
|
39
|
+
return null;
|
|
40
|
+
const row = result.rows[0];
|
|
41
|
+
return { id: row.id, data: rowToRecord(row) };
|
|
42
|
+
}
|
|
43
|
+
async set(id, record) {
|
|
44
|
+
const path = record.path ?? "";
|
|
45
|
+
const content = record.content ?? "";
|
|
46
|
+
const app = record.app ?? "";
|
|
47
|
+
const ownerId = record.ownerId ?? "";
|
|
48
|
+
const lastUpdated = record.lastUpdated ?? 0;
|
|
49
|
+
const createdAt = record.createdAt ?? null;
|
|
50
|
+
await this.sql `
|
|
51
|
+
INSERT INTO files (id, path, content, app, owner_id, last_updated, created_at)
|
|
52
|
+
VALUES (${id}, ${path}, ${content}, ${app}, ${ownerId}, ${lastUpdated}, ${createdAt})
|
|
53
|
+
ON CONFLICT (id) DO UPDATE SET
|
|
54
|
+
path = COALESCE(EXCLUDED.path, files.path),
|
|
55
|
+
content = COALESCE(EXCLUDED.content, files.content),
|
|
56
|
+
app = COALESCE(EXCLUDED.app, files.app),
|
|
57
|
+
owner_id = COALESCE(EXCLUDED.owner_id, files.owner_id),
|
|
58
|
+
last_updated = COALESCE(EXCLUDED.last_updated, files.last_updated),
|
|
59
|
+
created_at = COALESCE(EXCLUDED.created_at, files.created_at)
|
|
60
|
+
`;
|
|
61
|
+
}
|
|
62
|
+
async delete(id) {
|
|
63
|
+
await this.sql `DELETE FROM files WHERE id = ${id}`;
|
|
64
|
+
}
|
|
65
|
+
subscribe(appId, ownerId, onChange, onError) {
|
|
66
|
+
const snapshot = new Map();
|
|
67
|
+
let stopped = false;
|
|
68
|
+
const poll = async () => {
|
|
69
|
+
if (stopped)
|
|
70
|
+
return;
|
|
71
|
+
try {
|
|
72
|
+
const result = await this.sql `
|
|
73
|
+
SELECT * FROM files WHERE app = ${appId} AND owner_id = ${ownerId}
|
|
74
|
+
`;
|
|
75
|
+
const currentIds = new Set();
|
|
76
|
+
const changes = [];
|
|
77
|
+
for (const row of result.rows) {
|
|
78
|
+
currentIds.add(row.id);
|
|
79
|
+
const record = rowToRecord(row);
|
|
80
|
+
const prev = snapshot.get(row.id);
|
|
81
|
+
if (!prev) {
|
|
82
|
+
changes.push({ type: "added", id: row.id, data: record });
|
|
83
|
+
snapshot.set(row.id, { content: row.content, lastUpdated: Number(row.last_updated) });
|
|
84
|
+
}
|
|
85
|
+
else if (prev.content !== row.content || prev.lastUpdated !== Number(row.last_updated)) {
|
|
86
|
+
changes.push({ type: "modified", id: row.id, data: record });
|
|
87
|
+
snapshot.set(row.id, { content: row.content, lastUpdated: Number(row.last_updated) });
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
for (const [id] of snapshot) {
|
|
91
|
+
if (!currentIds.has(id)) {
|
|
92
|
+
const prev = snapshot.get(id);
|
|
93
|
+
changes.push({
|
|
94
|
+
type: "removed",
|
|
95
|
+
id,
|
|
96
|
+
data: { path: "", content: prev.content, app: appId, ownerId, lastUpdated: prev.lastUpdated },
|
|
97
|
+
});
|
|
98
|
+
snapshot.delete(id);
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
if (changes.length > 0) {
|
|
102
|
+
onChange(changes);
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
catch (err) {
|
|
106
|
+
onError(err);
|
|
107
|
+
}
|
|
108
|
+
if (!stopped) {
|
|
109
|
+
setTimeout(poll, this.pollIntervalMs);
|
|
110
|
+
}
|
|
111
|
+
};
|
|
112
|
+
// Start polling
|
|
113
|
+
poll();
|
|
114
|
+
return () => {
|
|
115
|
+
stopped = true;
|
|
116
|
+
};
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
//# sourceMappingURL=adapter.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"adapter.js","sourceRoot":"","sources":["../../../src/adapters/neon/adapter.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/adapters/neon/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,mBAAmB,EAAE,KAAK,kBAAkB,EAAE,MAAM,cAAc,CAAC;AAC5E,cAAc,kBAAkB,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/adapters/neon/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,mBAAmB,EAA2B,MAAM,cAAc,CAAC;AAC5E,cAAc,kBAAkB,CAAC"}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import type { FileSyncAdapter, FileRecord, FileChange, Unsubscribe } from "../sync/types.js";
|
|
2
|
+
interface SupabaseFilterBuilder {
|
|
3
|
+
select(columns: string): SupabaseFilterBuilder;
|
|
4
|
+
eq(column: string, value: any): SupabaseFilterBuilder;
|
|
5
|
+
maybeSingle(): SupabaseFilterBuilder;
|
|
6
|
+
then(resolve: (value: any) => any, reject?: (error: any) => any): any;
|
|
7
|
+
}
|
|
8
|
+
interface SupabaseQueryBuilder {
|
|
9
|
+
select(columns: string): SupabaseFilterBuilder;
|
|
10
|
+
upsert(values: any, options?: {
|
|
11
|
+
onConflict?: string;
|
|
12
|
+
}): SupabaseFilterBuilder;
|
|
13
|
+
delete(): SupabaseFilterBuilder;
|
|
14
|
+
}
|
|
15
|
+
interface SupabaseRealtimeChannel {
|
|
16
|
+
on(event: string, filter: any, callback: (payload: any) => void): SupabaseRealtimeChannel;
|
|
17
|
+
subscribe(callback?: (status: string) => void): SupabaseRealtimeChannel;
|
|
18
|
+
unsubscribe(): void;
|
|
19
|
+
}
|
|
20
|
+
interface SupabaseClient {
|
|
21
|
+
from(table: string): SupabaseQueryBuilder;
|
|
22
|
+
channel(name: string): SupabaseRealtimeChannel;
|
|
23
|
+
removeChannel(channel: SupabaseRealtimeChannel): void;
|
|
24
|
+
}
|
|
25
|
+
export declare class SupabaseFileSyncAdapter implements FileSyncAdapter {
|
|
26
|
+
private client;
|
|
27
|
+
private table;
|
|
28
|
+
constructor(client: SupabaseClient, table?: string);
|
|
29
|
+
query(appId: string, ownerId: string): Promise<{
|
|
30
|
+
id: string;
|
|
31
|
+
data: FileRecord;
|
|
32
|
+
}[]>;
|
|
33
|
+
get(id: string): Promise<{
|
|
34
|
+
id: string;
|
|
35
|
+
data: FileRecord;
|
|
36
|
+
} | null>;
|
|
37
|
+
set(id: string, record: Partial<FileRecord>): Promise<void>;
|
|
38
|
+
delete(id: string): Promise<void>;
|
|
39
|
+
subscribe(appId: string, ownerId: string, onChange: (changes: FileChange[]) => void, onError: (error: any) => void): Unsubscribe;
|
|
40
|
+
}
|
|
41
|
+
export {};
|
|
42
|
+
//# sourceMappingURL=adapter.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"adapter.d.ts","sourceRoot":"","sources":["../../../src/adapters/supabase/adapter.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,UAAU,EAAE,UAAU,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAM7F,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;AAwCD,qBAAa,uBAAwB,YAAW,eAAe;IAE3D,OAAO,CAAC,MAAM;IACd,OAAO,CAAC,KAAK;gBADL,MAAM,EAAE,cAAc,EACtB,KAAK,GAAE,MAAgB;IAG3B,KAAK,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC;QAAE,EAAE,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,UAAU,CAAA;KAAE,EAAE,CAAC;IAWlF,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;CAyCf"}
|
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
// ---------------------------------------------------------------------------
|
|
2
|
+
// Column mapping helpers
|
|
3
|
+
// ---------------------------------------------------------------------------
|
|
4
|
+
/**
|
|
5
|
+
* Table schema:
|
|
6
|
+
* files(id TEXT PK, path TEXT, content TEXT, app TEXT, owner_id TEXT,
|
|
7
|
+
* last_updated BIGINT, created_at BIGINT)
|
|
8
|
+
*
|
|
9
|
+
* CREATE INDEX idx_files_app_owner ON files(app, owner_id);
|
|
10
|
+
*/
|
|
11
|
+
function rowToRecord(row) {
|
|
12
|
+
return {
|
|
13
|
+
path: row.path,
|
|
14
|
+
content: row.content,
|
|
15
|
+
app: row.app,
|
|
16
|
+
ownerId: row.owner_id,
|
|
17
|
+
lastUpdated: row.last_updated,
|
|
18
|
+
createdAt: row.created_at ?? undefined,
|
|
19
|
+
};
|
|
20
|
+
}
|
|
21
|
+
function recordToRow(id, record) {
|
|
22
|
+
const row = { id };
|
|
23
|
+
if (record.path !== undefined)
|
|
24
|
+
row.path = record.path;
|
|
25
|
+
if (record.content !== undefined)
|
|
26
|
+
row.content = record.content;
|
|
27
|
+
if (record.app !== undefined)
|
|
28
|
+
row.app = record.app;
|
|
29
|
+
if (record.ownerId !== undefined)
|
|
30
|
+
row.owner_id = record.ownerId;
|
|
31
|
+
if (record.lastUpdated !== undefined)
|
|
32
|
+
row.last_updated = record.lastUpdated;
|
|
33
|
+
if (record.createdAt !== undefined)
|
|
34
|
+
row.created_at = record.createdAt;
|
|
35
|
+
return row;
|
|
36
|
+
}
|
|
37
|
+
// ---------------------------------------------------------------------------
|
|
38
|
+
// Supabase adapter
|
|
39
|
+
// ---------------------------------------------------------------------------
|
|
40
|
+
export class SupabaseFileSyncAdapter {
|
|
41
|
+
client;
|
|
42
|
+
table;
|
|
43
|
+
constructor(client, table = "files") {
|
|
44
|
+
this.client = client;
|
|
45
|
+
this.table = table;
|
|
46
|
+
}
|
|
47
|
+
async query(appId, ownerId) {
|
|
48
|
+
const { data, error } = await this.client
|
|
49
|
+
.from(this.table)
|
|
50
|
+
.select("*")
|
|
51
|
+
.eq("app", appId)
|
|
52
|
+
.eq("owner_id", ownerId);
|
|
53
|
+
if (error)
|
|
54
|
+
throw error;
|
|
55
|
+
return (data ?? []).map((row) => ({ id: row.id, data: rowToRecord(row) }));
|
|
56
|
+
}
|
|
57
|
+
async get(id) {
|
|
58
|
+
const { data, error } = await this.client
|
|
59
|
+
.from(this.table)
|
|
60
|
+
.select("*")
|
|
61
|
+
.eq("id", id)
|
|
62
|
+
.maybeSingle();
|
|
63
|
+
if (error)
|
|
64
|
+
throw error;
|
|
65
|
+
if (!data)
|
|
66
|
+
return null;
|
|
67
|
+
return { id: data.id, data: rowToRecord(data) };
|
|
68
|
+
}
|
|
69
|
+
async set(id, record) {
|
|
70
|
+
const row = recordToRow(id, record);
|
|
71
|
+
const { error } = await this.client
|
|
72
|
+
.from(this.table)
|
|
73
|
+
.upsert(row, { onConflict: "id" });
|
|
74
|
+
if (error)
|
|
75
|
+
throw error;
|
|
76
|
+
}
|
|
77
|
+
async delete(id) {
|
|
78
|
+
const { error } = await this.client
|
|
79
|
+
.from(this.table)
|
|
80
|
+
.delete()
|
|
81
|
+
.eq("id", id);
|
|
82
|
+
if (error)
|
|
83
|
+
throw error;
|
|
84
|
+
}
|
|
85
|
+
subscribe(appId, ownerId, onChange, onError) {
|
|
86
|
+
const channel = this.client
|
|
87
|
+
.channel(`file-sync-${appId}-${ownerId}`)
|
|
88
|
+
.on("postgres_changes", { event: "*", schema: "public", table: this.table, filter: `app=eq.${appId}` }, (payload) => {
|
|
89
|
+
try {
|
|
90
|
+
const row = payload.new ?? payload.old;
|
|
91
|
+
if (!row)
|
|
92
|
+
return;
|
|
93
|
+
// Client-side filter by owner_id (Realtime only supports one filter)
|
|
94
|
+
if (row.owner_id !== ownerId)
|
|
95
|
+
return;
|
|
96
|
+
let type;
|
|
97
|
+
if (payload.eventType === "INSERT")
|
|
98
|
+
type = "added";
|
|
99
|
+
else if (payload.eventType === "UPDATE")
|
|
100
|
+
type = "modified";
|
|
101
|
+
else if (payload.eventType === "DELETE")
|
|
102
|
+
type = "removed";
|
|
103
|
+
else
|
|
104
|
+
return;
|
|
105
|
+
const change = {
|
|
106
|
+
type,
|
|
107
|
+
id: row.id,
|
|
108
|
+
data: rowToRecord(row),
|
|
109
|
+
};
|
|
110
|
+
onChange([change]);
|
|
111
|
+
}
|
|
112
|
+
catch (err) {
|
|
113
|
+
onError(err);
|
|
114
|
+
}
|
|
115
|
+
})
|
|
116
|
+
.subscribe((status) => {
|
|
117
|
+
if (status === "CHANNEL_ERROR") {
|
|
118
|
+
onError(new Error("Supabase realtime channel error"));
|
|
119
|
+
}
|
|
120
|
+
});
|
|
121
|
+
return () => {
|
|
122
|
+
this.client.removeChannel(channel);
|
|
123
|
+
};
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
//# sourceMappingURL=adapter.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"adapter.js","sourceRoot":"","sources":["../../../src/adapters/supabase/adapter.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/adapters/supabase/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,uBAAuB,EAAE,MAAM,cAAc,CAAC;AACvD,cAAc,kBAAkB,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/adapters/supabase/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,uBAAuB,EAAE,MAAM,cAAc,CAAC;AACvD,cAAc,kBAAkB,CAAC"}
|
|
@@ -13,7 +13,7 @@ export declare function loadSyncConfig(configPath?: string): SyncConfig;
|
|
|
13
13
|
*/
|
|
14
14
|
export declare function shouldSyncFile(filePath: string, patterns: string[]): boolean;
|
|
15
15
|
/**
|
|
16
|
-
* Generate a deterministic
|
|
16
|
+
* Generate a deterministic doc ID from a file path.
|
|
17
17
|
* Prefixed with the app ID, path separators replaced with `__`.
|
|
18
18
|
*/
|
|
19
19
|
export declare function getDocId(appId: string, filePath: string): string;
|