History

refactor(v2): integrate drizzle-kit for database operations and remove legacy SQL schema

- Added drizzle-kit for database generation and migration scripts in package.json. - Introduced new database operations and removed outdated SQL schema files. - Updated end-to-end tests to accommodate changes in database handling and state management.

Rhys Sullivan committed 8 months ago

Commit 41edbe81 parent 616093c25 files · +5296 −1208Browse files

Unified · Split

25 files
  1. apps/pm/src/approval-runtime.e2e.test.ts +336 −0
  2. apps/pm/src/execute.e2e.test.ts +17 −2
  3. bun.lock +117 −0
  4. packages/persistence-sql/drizzle.config.pg.ts +14 −0
  5. packages/persistence-sql/drizzle.config.ts +12 −0
  6. packages/persistence-sql/drizzle/0000_initial_schema.sql +0 −139
  7. packages/persistence-sql/drizzle/meta/_journal.json +0 −13
  8. packages/persistence-sql/drizzle/postgres/0000_spicy_barracuda.sql +224 −0
  9. packages/persistence-sql/drizzle/postgres/meta/0000_snapshot.json +1509 −0
  10. packages/persistence-sql/drizzle/postgres/meta/_journal.json +13 −0
  11. packages/persistence-sql/drizzle/sqlite/0000_curved_raider.sql +224 −0
  12. packages/persistence-sql/drizzle/sqlite/meta/0000_snapshot.json +1437 −0
  13. packages/persistence-sql/drizzle/sqlite/meta/_journal.json +13 −0
  14. packages/persistence-sql/package.json +11 −1
  15. packages/persistence-sql/src/persistence-codecs.ts +0 −52
  16. packages/persistence-sql/src/row-operations-auth.ts +199 −92
  17. packages/persistence-sql/src/row-operations-core.ts +252 −125
  18. packages/persistence-sql/src/rows-effect-api-auth.ts +116 −0
  19. packages/persistence-sql/src/rows-effect-api-core.ts +157 −0
  20. packages/persistence-sql/src/rows-effect-api.ts +5 −296
  21. packages/persistence-sql/src/rows-effect-helpers.ts +55 −0
  22. packages/persistence-sql/src/schema-pg.ts +304 −0
  23. packages/persistence-sql/src/schema.ts +212 −42
  24. packages/persistence-sql/src/source-artifact-stores.ts +69 −28
  25. packages/persistence-sql/src/sql-internals.ts +0 −418
apps/pm/src/approval-runtime.e2e.test.ts+336−0
@@ -0,0 +1,336 @@
1import { createServer, type IncomingMessage, type ServerResponse } from "node:http";
2import { mkdtemp, rm } from "node:fs/promises";
3import { tmpdir } from "node:os";
4import * as path from "node:path";
5
6import {
7 HttpApi,
8 HttpApiEndpoint,
9 HttpApiGroup,
10 HttpApiSchema,
11 OpenApi,
12} from "@effect/platform";
13import { describe, expect, it } from "@effect/vitest";
14import { makeSourceManagerService } from "@executor-v2/management-api";
15import {
16 createRunExecutor,
17 createSourceToolRegistry,
18 makeOpenApiToolProvider,
19 makeRuntimeAdapterRegistry,
20 makeToolProviderRegistry,
21} from "@executor-v2/engine";
22import { makeSqlControlPlanePersistence } from "@executor-v2/persistence-sql";
23import { SourceSchema, type Source } from "@executor-v2/schema";
24import { makeLocalInProcessRuntimeAdapter } from "@executor-v2/runtime-local-inproc";
25import * as Effect from "effect/Effect";
26import * as Schema from "effect/Schema";
27
28import {
29 createPmApprovalsService,
30 createPmPersistentToolApprovalPolicy,
31} from "./approvals-service";
32import { createPmExecuteRuntimeRun } from "./runtime-execution-port";
33
34type TestServer = {
35 baseUrl: string;
36 requests: Array<string>;
37 close: () => Promise<void>;
38};
39
40const decodeSource = Schema.decodeUnknownSync(SourceSchema);
41
42const githubOwnerParam = HttpApiSchema.param("owner", Schema.String);
43const githubRepoParam = HttpApiSchema.param("repo", Schema.String);
44
45class GitHubReposApi extends HttpApiGroup.make("repos").add(
46 HttpApiEndpoint.get("getRepo")`/repos/${githubOwnerParam}/${githubRepoParam}`.addSuccess(
47 Schema.Unknown,
48 ),
49) {}
50
51class GitHubApi extends HttpApi.make("github").add(GitHubReposApi) {}
52
53const githubOpenApiSpec = OpenApi.fromApi(GitHubApi);
54
55const getHeaderValue = (req: IncomingMessage, key: string): string | null => {
56 const value = req.headers[key];
57 if (typeof value === "string") {
58 return value;
59 }
60
61 if (Array.isArray(value)) {
62 return value[0] ?? null;
63 }
64
65 return null;
66};
67
68const makeTestServer = Effect.acquireRelease(
69 Effect.promise<TestServer>(
70 () =>
71 new Promise<TestServer>((resolve, reject) => {
72 const requests: Array<string> = [];
73
74 const server = createServer((req, res) => {
75 const host = getHeaderValue(req, "host") ?? "127.0.0.1";
76 const url = new URL(req.url ?? "/", `http://${host}`);
77
78 if (url.pathname === "/repos/octocat/hello-world" && req.method === "GET") {
79 requests.push(url.pathname);
80 res.statusCode = 200;
81 res.setHeader("content-type", "application/json");
82 res.end(
83 JSON.stringify({
84 full_name: "octocat/hello-world",
85 stargazers_count: 42,
86 }),
87 );
88 return;
89 }
90
91 res.statusCode = 404;
92 res.setHeader("content-type", "application/json");
93 res.end(JSON.stringify({ error: "not found" }));
94 });
95
96 server.once("error", (error) => reject(error));
97 server.listen(0, "127.0.0.1", () => {
98 const address = server.address();
99 if (!address || typeof address === "string") {
100 reject(new Error("failed to resolve test server address"));
101 return;
102 }
103
104 resolve({
105 baseUrl: `http://127.0.0.1:${address.port}`,
106 requests,
107 close: () =>
108 new Promise<void>((closeResolve, closeReject) => {
109 server.close((error) => {
110 if (error) {
111 closeReject(error);
112 return;
113 }
114
115 closeResolve();
116 });
117 }),
118 });
119 });
120 }),
121 ),
122 (server) => Effect.promise(() => server.close()).pipe(Effect.orDie),
123);
124
125const withFixedRandomUuid = <A>(
126 fixedValue: string,
127 run: () => Effect.Effect<A>,
128): Effect.Effect<A> =>
129 Effect.acquireUseRelease(
130 Effect.sync(() => {
131 const original = crypto.randomUUID;
132 (crypto as { randomUUID: () => string }).randomUUID = () => fixedValue;
133 return original;
134 }),
135 () => run(),
136 (original) =>
137 Effect.sync(() => {
138 (crypto as { randomUUID: () => string }).randomUUID = original;
139 }).pipe(Effect.orDie),
140 );
141
142const setupApprovalRuntimeHarness = (runId: string) =>
143 Effect.gen(function* () {
144 const stateDir = yield* Effect.acquireRelease(
145 Effect.promise(() =>
146 mkdtemp(path.join(tmpdir(), "executor-v2-approval-e2e-")),
147 ),
148 (directory) =>
149 Effect.promise(() =>
150 rm(directory, { recursive: true, force: true }),
151 ).pipe(Effect.orDie),
152 );
153
154 const persistence = yield* Effect.acquireRelease(
155 makeSqlControlPlanePersistence({
156 sqlitePath: path.resolve(stateDir, "control-plane.sqlite"),
157 }),
158 (resource) => Effect.promise(() => resource.close()).pipe(Effect.orDie),
159 );
160
161 const server = yield* makeTestServer;
162
163 const source: Source = decodeSource({
164 id: "src_github",
165 workspaceId: "ws_local",
166 name: "github",
167 kind: "openapi",
168 endpoint: server.baseUrl,
169 status: "connected",
170 enabled: true,
171 configJson: JSON.stringify({ baseUrl: server.baseUrl }),
172 sourceHash: null,
173 lastError: null,
174 createdAt: Date.now(),
175 updatedAt: Date.now(),
176 });
177
178 yield* persistence.sourceStore.upsert(source);
179
180 const sourceManager = makeSourceManagerService(persistence.toolArtifactStore);
181 yield* sourceManager.refreshOpenApiArtifact({
182 source,
183 openApiSpec: githubOpenApiSpec,
184 });
185
186 const approvalsService = createPmApprovalsService(persistence.rows);
187 const approvalPolicy = createPmPersistentToolApprovalPolicy(persistence.rows, {
188 requireApprovals: true,
189 retryAfterMs: 50,
190 });
191
192 const toolRegistry = createSourceToolRegistry({
193 workspaceId: source.workspaceId,
194 sourceStore: persistence.sourceStore,
195 toolArtifactStore: persistence.toolArtifactStore,
196 toolProviderRegistry: makeToolProviderRegistry([makeOpenApiToolProvider()]),
197 approvalPolicy,
198 });
199
200 const discovered = yield* toolRegistry.discover({ query: "repo", limit: 5 });
201 const toolPath = discovered.bestPath;
202 if (!toolPath) {
203 throw new Error("expected source tool discovery to return a bestPath");
204 }
205
206 const toolPathAccessor = toolPath
207 .split(".")
208 .map((segment) => `[${JSON.stringify(segment)}]`)
209 .join("");
210
211 const code = `
212const response = await tools${toolPathAccessor}({ owner: "octocat", repo: "hello-world" });
213return response.body.full_name;
214`;
215
216 const runtimeAdapters = makeRuntimeAdapterRegistry([
217 makeLocalInProcessRuntimeAdapter(),
218 ]);
219
220 const executeRuntimeRun = createPmExecuteRuntimeRun({
221 defaultRuntimeKind: "local-inproc",
222 runtimeAdapters,
223 toolRegistry,
224 });
225
226 const executor = createRunExecutor(executeRuntimeRun, {
227 makeRunId: () => runId,
228 });
229
230 return {
231 persistence,
232 server,
233 source,
234 approvalsService,
235 executor,
236 code,
237 };
238 });
239
240describe("PM approval execution E2E", () => {
241 it.scoped("persists pending approval, resolves it, and completes sandbox tool call", () =>
242 Effect.gen(function* () {
243 const { persistence, server, source, approvalsService, executor, code } =
244 yield* setupApprovalRuntimeHarness("run_approval_e2e");
245
246 const firstAttempt = yield* withFixedRandomUuid("approval_call_e2e", () =>
247 executor.executeRun({ code }),
248 );
249
250 expect(firstAttempt.status).toBe("failed");
251 if (firstAttempt.status === "failed") {
252 expect(firstAttempt.error).toContain("requires approval");
253 }
254
255 const approvalsAfterFirstAttempt = yield* persistence.rows.approvals.list();
256 expect(approvalsAfterFirstAttempt).toHaveLength(1);
257
258 const pendingApproval = approvalsAfterFirstAttempt[0];
259 if (!pendingApproval) {
260 throw new Error("expected pending approval record");
261 }
262
263 expect(pendingApproval.status).toBe("pending");
264
265 yield* approvalsService.resolveApproval({
266 workspaceId: source.workspaceId,
267 approvalId: pendingApproval.id,
268 payload: {
269 status: "approved",
270 reason: "approved in e2e test",
271 },
272 });
273
274 const secondAttempt = yield* withFixedRandomUuid("approval_call_e2e", () =>
275 executor.executeRun({ code }),
276 );
277
278 expect(secondAttempt.status).toBe("completed");
279 if (secondAttempt.status === "completed") {
280 expect(secondAttempt.result).toBe("octocat/hello-world");
281 }
282
283 const approvalsAfterSecondAttempt = yield* persistence.rows.approvals.list();
284 expect(approvalsAfterSecondAttempt[0]?.status).toBe("approved");
285 expect(server.requests).toEqual(["/repos/octocat/hello-world"]);
286 }),
287 );
288
289 it.scoped("persists pending approval and blocks execution when denied", () =>
290 Effect.gen(function* () {
291 const { persistence, server, source, approvalsService, executor, code } =
292 yield* setupApprovalRuntimeHarness("run_approval_e2e_denied");
293
294 const firstAttempt = yield* withFixedRandomUuid("approval_call_e2e_denied", () =>
295 executor.executeRun({ code }),
296 );
297
298 expect(firstAttempt.status).toBe("failed");
299 if (firstAttempt.status === "failed") {
300 expect(firstAttempt.error).toContain("requires approval");
301 }
302
303 const approvalsAfterFirstAttempt = yield* persistence.rows.approvals.list();
304 expect(approvalsAfterFirstAttempt).toHaveLength(1);
305
306 const pendingApproval = approvalsAfterFirstAttempt[0];
307 if (!pendingApproval) {
308 throw new Error("expected pending approval record");
309 }
310
311 expect(pendingApproval.status).toBe("pending");
312
313 yield* approvalsService.resolveApproval({
314 workspaceId: source.workspaceId,
315 approvalId: pendingApproval.id,
316 payload: {
317 status: "denied",
318 reason: "denied in e2e test",
319 },
320 });
321
322 const secondAttempt = yield* withFixedRandomUuid("approval_call_e2e_denied", () =>
323 executor.executeRun({ code }),
324 );
325
326 expect(secondAttempt.status).toBe("failed");
327 if (secondAttempt.status === "failed") {
328 expect((secondAttempt.error ?? "").toLowerCase()).toContain("denied");
329 }
330
331 const approvalsAfterSecondAttempt = yield* persistence.rows.approvals.list();
332 expect(approvalsAfterSecondAttempt[0]?.status).toBe("denied");
333 expect(server.requests).toEqual([]);
334 }),
335 );
336});
apps/pm/src/execute.e2e.test.ts+17−2
@@ -1,5 +1,8 @@
1import { spawn } from "node:child_process";1import { spawn } from "node:child_process";
2import { mkdtemp, rm } from "node:fs/promises";
2import { createServer } from "node:net";3import { createServer } from "node:net";
4import { tmpdir } from "node:os";
5import * as path from "node:path";
3import { Client } from "@modelcontextprotocol/sdk/client/index.js";6import { Client } from "@modelcontextprotocol/sdk/client/index.js";
4import { StreamableHTTPClientTransport } from "@modelcontextprotocol/sdk/client/streamableHttp.js";7import { StreamableHTTPClientTransport } from "@modelcontextprotocol/sdk/client/streamableHttp.js";
5import { describe, expect, it } from "@effect/vitest";8import { describe, expect, it } from "@effect/vitest";
@@ -84,7 +87,15 @@ const waitForHealth = (port: number) => · 78 unmodified lines
84 });87 });
85 });88 });
86 89
87const withPmProcess = (port: number) =>90const withStateDir = Effect.acquireRelease(
91 Effect.promise(() => mkdtemp(path.join(tmpdir(), "executor-v2-pm-e2e-"))),
92 (directory) =>
93 Effect.promise(() => rm(directory, { recursive: true, force: true })).pipe(
94 Effect.orDie,
95 ),
96);
97
98const withPmProcess = (port: number, sqlitePath: string) =>
88 Effect.acquireRelease(99 Effect.acquireRelease(
89 Effect.sync(() =>100 Effect.sync(() =>
90 spawn("bun", ["src/main.ts"], {101 spawn("bun", ["src/main.ts"], {
@@ -92,6 +103,7 @@ const withPmProcess = (port: number) => · 1 unmodified line
92 env: {103 env: {
93 ...process.env,104 ...process.env,
94 PORT: String(port),105 PORT: String(port),
106 PM_CONTROL_PLANE_SQLITE_PATH: sqlitePath,
95 },107 },
96 stdio: "pipe",108 stdio: "pipe",
97 }),109 }),
@@ -140,7 +152,10 @@ describe("PM execute E2E", () => { · 42 unmodified lines
140 Effect.scoped(152 Effect.scoped(
141 Effect.gen(function* () {153 Effect.gen(function* () {
142 const port = yield* findFreePort;154 const port = yield* findFreePort;
143 yield* withPmProcess(port);155 const stateDir = yield* withStateDir;
156 const sqlitePath = path.resolve(stateDir, "control-plane.sqlite");
157
158 yield* withPmProcess(port, sqlitePath);
144 yield* waitForHealth(port);159 yield* waitForHealth(port);
145 160
146 const { client } = yield* withMcpClient(port);161 const { client } = yield* withMcpClient(port);
bun.lock+117−0
@@ -169,6 +169,9 @@ · 168 unmodified lines
169 "effect": "catalog:",169 "effect": "catalog:",
170 "postgres": "^3.4.7",170 "postgres": "^3.4.7",
171 },171 },
172 "devDependencies": {
173 "drizzle-kit": "^0.31.9",
174 },
172 },175 },
173 "packages/runtime-cloudflare-worker-loader": {176 "packages/runtime-cloudflare-worker-loader": {
174 "name": "@executor-v2/runtime-cloudflare-worker-loader",177 "name": "@executor-v2/runtime-cloudflare-worker-loader",
@@ -320,6 +323,8 @@ · 145 unmodified lines
320 323
321 "@cspotcode/source-map-support": ["@cspotcode/source-map-support@0.8.1", "", { "dependencies": { "@jridgewell/trace-mapping": "0.3.9" } }, "sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw=="],324 "@cspotcode/source-map-support": ["@cspotcode/source-map-support@0.8.1", "", { "dependencies": { "@jridgewell/trace-mapping": "0.3.9" } }, "sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw=="],
322 325
326 "@drizzle-team/brocli": ["@drizzle-team/brocli@0.10.2", "", {}, "sha512-z33Il7l5dKjUgGULTqBsQBQwckHh5AbIuxhdsIxDDiZAzBOrZO6q9ogcWC65kU382AfynTfgNumVcNIjuIua6w=="],
327
323 "@edge-runtime/format": ["@edge-runtime/format@2.2.1", "", {}, "sha512-JQTRVuiusQLNNLe2W9tnzBlV/GvSVcozLl4XZHk5swnRZ/v6jp8TqR8P7sqmJsQqblDZ3EztcWmLDbhRje/+8g=="],328 "@edge-runtime/format": ["@edge-runtime/format@2.2.1", "", {}, "sha512-JQTRVuiusQLNNLe2W9tnzBlV/GvSVcozLl4XZHk5swnRZ/v6jp8TqR8P7sqmJsQqblDZ3EztcWmLDbhRje/+8g=="],
324 329
325 "@edge-runtime/node-utils": ["@edge-runtime/node-utils@2.3.0", "", {}, "sha512-uUtx8BFoO1hNxtHjp3eqVPC/mWImGb2exOfGjMLUoipuWgjej+f4o/VP4bUI8U40gu7Teogd5VTeZUkGvJSPOQ=="],330 "@edge-runtime/node-utils": ["@edge-runtime/node-utils@2.3.0", "", {}, "sha512-uUtx8BFoO1hNxtHjp3eqVPC/mWImGb2exOfGjMLUoipuWgjej+f4o/VP4bUI8U40gu7Teogd5VTeZUkGvJSPOQ=="],
@@ -374,6 +379,10 @@ · 48 unmodified lines
374 379
375 "@emnapi/wasi-threads": ["@emnapi/wasi-threads@1.1.0", "", { "dependencies": { "tslib": "^2.4.0" } }, "sha512-WI0DdZ8xFSbgMjR1sFsKABJ/C5OnRrjT06JXbZKexJGrDuPTzZdDYfFlsgcCXCyf+suG5QU2e/y1Wo2V/OapLQ=="],380 "@emnapi/wasi-threads": ["@emnapi/wasi-threads@1.1.0", "", { "dependencies": { "tslib": "^2.4.0" } }, "sha512-WI0DdZ8xFSbgMjR1sFsKABJ/C5OnRrjT06JXbZKexJGrDuPTzZdDYfFlsgcCXCyf+suG5QU2e/y1Wo2V/OapLQ=="],
376 381
382 "@esbuild-kit/core-utils": ["@esbuild-kit/core-utils@3.3.2", "", { "dependencies": { "esbuild": "~0.18.20", "source-map-support": "^0.5.21" } }, "sha512-sPRAnw9CdSsRmEtnsl2WXWdyquogVpB3yZ3dgwJfe8zrOzTsV7cJvmwrKVa+0ma5BoiGJ+BoqkMvawbayKUsqQ=="],
383
384 "@esbuild-kit/esm-loader": ["@esbuild-kit/esm-loader@2.6.5", "", { "dependencies": { "@esbuild-kit/core-utils": "^3.3.2", "get-tsconfig": "^4.7.0" } }, "sha512-FxEMIkJKnodyA1OaCUoEvbYRkoZlLZ4d/eXFu9Fh8CbBBgP5EmZxrfTRyN0qpXZ4vOvqnE5YdRdcrmUUXuU+dA=="],
385
377 "@esbuild/aix-ppc64": ["@esbuild/aix-ppc64@0.27.0", "", { "os": "aix", "cpu": "ppc64" }, "sha512-KuZrd2hRjz01y5JK9mEBSD3Vj3mbCvemhT466rSuJYeE/hjuBrHfjjcjMdTm/sz7au+++sdbJZJmuBwQLuw68A=="],386 "@esbuild/aix-ppc64": ["@esbuild/aix-ppc64@0.27.0", "", { "os": "aix", "cpu": "ppc64" }, "sha512-KuZrd2hRjz01y5JK9mEBSD3Vj3mbCvemhT466rSuJYeE/hjuBrHfjjcjMdTm/sz7au+++sdbJZJmuBwQLuw68A=="],
378 387
379 "@esbuild/android-arm": ["@esbuild/android-arm@0.27.0", "", { "os": "android", "cpu": "arm" }, "sha512-j67aezrPNYWJEOHUNLPj9maeJte7uSMM6gMoxfPC9hOg8N02JuQi/T7ewumf4tNvJadFkvLZMlAq73b9uwdMyQ=="],388 "@esbuild/android-arm": ["@esbuild/android-arm@0.27.0", "", { "os": "android", "cpu": "arm" }, "sha512-j67aezrPNYWJEOHUNLPj9maeJte7uSMM6gMoxfPC9hOg8N02JuQi/T7ewumf4tNvJadFkvLZMlAq73b9uwdMyQ=="],
@@ -1034,6 +1043,8 @@ · 654 unmodified lines
1034 1043
1035 "buffer-crc32": ["buffer-crc32@0.2.13", "", {}, "sha512-VO9Ht/+p3SN7SKWqcrgEzjGbRSJYTx+Q1pTQC0wrWqHx0vpJraQ6GtHx8tvcg1rlK1byhU5gccxgOgj7B0TDkQ=="],1044 "buffer-crc32": ["buffer-crc32@0.2.13", "", {}, "sha512-VO9Ht/+p3SN7SKWqcrgEzjGbRSJYTx+Q1pTQC0wrWqHx0vpJraQ6GtHx8tvcg1rlK1byhU5gccxgOgj7B0TDkQ=="],
1036 1045
1046 "buffer-from": ["buffer-from@1.1.2", "", {}, "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ=="],
1047
1037 "bun-types": ["bun-types@1.3.9", "", { "dependencies": { "@types/node": "*" } }, "sha512-+UBWWOakIP4Tswh0Bt0QD0alpTY8cb5hvgiYeWCMet9YukHbzuruIEeXC2D7nMJPB12kbh8C7XJykSexEqGKJg=="],1048 "bun-types": ["bun-types@1.3.9", "", { "dependencies": { "@types/node": "*" } }, "sha512-+UBWWOakIP4Tswh0Bt0QD0alpTY8cb5hvgiYeWCMet9YukHbzuruIEeXC2D7nMJPB12kbh8C7XJykSexEqGKJg=="],
1038 1049
1039 "bytes": ["bytes@3.1.2", "", {}, "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg=="],1050 "bytes": ["bytes@3.1.2", "", {}, "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg=="],
@@ -1184,6 +1195,8 @@ · 144 unmodified lines
1184 1195
1185 "domutils": ["domutils@3.2.2", "", { "dependencies": { "dom-serializer": "^2.0.0", "domelementtype": "^2.3.0", "domhandler": "^5.0.3" } }, "sha512-6kZKyUajlDuqlHKVX1w7gyslj9MPIXzIFiz/rGu35uC1wMi+kMhQwGhl4lt9unC9Vb9INnY9Z3/ZA3+FhASLaw=="],1196 "domutils": ["domutils@3.2.2", "", { "dependencies": { "dom-serializer": "^2.0.0", "domelementtype": "^2.3.0", "domhandler": "^5.0.3" } }, "sha512-6kZKyUajlDuqlHKVX1w7gyslj9MPIXzIFiz/rGu35uC1wMi+kMhQwGhl4lt9unC9Vb9INnY9Z3/ZA3+FhASLaw=="],
1186 1197
1198 "drizzle-kit": ["drizzle-kit@0.31.9", "", { "dependencies": { "@drizzle-team/brocli": "^0.10.2", "@esbuild-kit/esm-loader": "^2.5.5", "esbuild": "^0.25.4", "esbuild-register": "^3.5.0" }, "bin": { "drizzle-kit": "bin.cjs" } }, "sha512-GViD3IgsXn7trFyBUUHyTFBpH/FsHTxYJ66qdbVggxef4UBPHRYxQaRzYLTuekYnk9i5FIEL9pbBIwMqX/Uwrg=="],
1199
1187 "drizzle-orm": ["drizzle-orm@0.44.7", "", { "peerDependencies": { "@aws-sdk/client-rds-data": ">=3", "@cloudflare/workers-types": ">=4", "@electric-sql/pglite": ">=0.2.0", "@libsql/client": ">=0.10.0", "@libsql/client-wasm": ">=0.10.0", "@neondatabase/serverless": ">=0.10.0", "@op-engineering/op-sqlite": ">=2", "@opentelemetry/api": "^1.4.1", "@planetscale/database": ">=1.13", "@prisma/client": "*", "@tidbcloud/serverless": "*", "@types/better-sqlite3": "*", "@types/pg": "*", "@types/sql.js": "*", "@upstash/redis": ">=1.34.7", "@vercel/postgres": ">=0.8.0", "@xata.io/client": "*", "better-sqlite3": ">=7", "bun-types": "*", "expo-sqlite": ">=14.0.0", "gel": ">=2", "knex": "*", "kysely": "*", "mysql2": ">=2", "pg": ">=8", "postgres": ">=3", "sql.js": ">=1", "sqlite3": ">=5" }, "optionalPeers": ["@aws-sdk/client-rds-data", "@cloudflare/workers-types", "@electric-sql/pglite", "@libsql/client", "@libsql/client-wasm", "@neondatabase/serverless", "@op-engineering/op-sqlite", "@opentelemetry/api", "@planetscale/database", "@prisma/client", "@tidbcloud/serverless", "@types/better-sqlite3", "@types/pg", "@types/sql.js", "@upstash/redis", "@vercel/postgres", "@xata.io/client", "better-sqlite3", "bun-types", "expo-sqlite", "gel", "knex", "kysely", "mysql2", "pg", "postgres", "sql.js", "sqlite3"] }, "sha512-quIpnYznjU9lHshEOAYLoZ9s3jweleHlZIAWR/jX9gAWNg/JhQ1wj0KGRf7/Zm+obRrYd9GjPVJg790QY9N5AQ=="],1200 "drizzle-orm": ["drizzle-orm@0.44.7", "", { "peerDependencies": { "@aws-sdk/client-rds-data": ">=3", "@cloudflare/workers-types": ">=4", "@electric-sql/pglite": ">=0.2.0", "@libsql/client": ">=0.10.0", "@libsql/client-wasm": ">=0.10.0", "@neondatabase/serverless": ">=0.10.0", "@op-engineering/op-sqlite": ">=2", "@opentelemetry/api": "^1.4.1", "@planetscale/database": ">=1.13", "@prisma/client": "*", "@tidbcloud/serverless": "*", "@types/better-sqlite3": "*", "@types/pg": "*", "@types/sql.js": "*", "@upstash/redis": ">=1.34.7", "@vercel/postgres": ">=0.8.0", "@xata.io/client": "*", "better-sqlite3": ">=7", "bun-types": "*", "expo-sqlite": ">=14.0.0", "gel": ">=2", "knex": "*", "kysely": "*", "mysql2": ">=2", "pg": ">=8", "postgres": ">=3", "sql.js": ">=1", "sqlite3": ">=5" }, "optionalPeers": ["@aws-sdk/client-rds-data", "@cloudflare/workers-types", "@electric-sql/pglite", "@libsql/client", "@libsql/client-wasm", "@neondatabase/serverless", "@op-engineering/op-sqlite", "@opentelemetry/api", "@planetscale/database", "@prisma/client", "@tidbcloud/serverless", "@types/better-sqlite3", "@types/pg", "@types/sql.js", "@upstash/redis", "@vercel/postgres", "@xata.io/client", "better-sqlite3", "bun-types", "expo-sqlite", "gel", "knex", "kysely", "mysql2", "pg", "postgres", "sql.js", "sqlite3"] }, "sha512-quIpnYznjU9lHshEOAYLoZ9s3jweleHlZIAWR/jX9gAWNg/JhQ1wj0KGRf7/Zm+obRrYd9GjPVJg790QY9N5AQ=="],
1188 1201
1189 "dset": ["dset@3.1.4", "", {}, "sha512-2QF/g9/zTaPDc3BjNcVTGoBbXBgYfMTTceLaYcFJ/W9kggFUkhxD/hMEeuLKbugyef9SqAx8cpgwlIP/jinUTA=="],1202 "dset": ["dset@3.1.4", "", {}, "sha512-2QF/g9/zTaPDc3BjNcVTGoBbXBgYfMTTceLaYcFJ/W9kggFUkhxD/hMEeuLKbugyef9SqAx8cpgwlIP/jinUTA=="],
@@ -1224,6 +1237,8 @@ · 34 unmodified lines
1224 1237
1225 "esbuild": ["esbuild@0.27.0", "", { "optionalDependencies": { "@esbuild/aix-ppc64": "0.27.0", "@esbuild/android-arm": "0.27.0", "@esbuild/android-arm64": "0.27.0", "@esbuild/android-x64": "0.27.0", "@esbuild/darwin-arm64": "0.27.0", "@esbuild/darwin-x64": "0.27.0", "@esbuild/freebsd-arm64": "0.27.0", "@esbuild/freebsd-x64": "0.27.0", "@esbuild/linux-arm": "0.27.0", "@esbuild/linux-arm64": "0.27.0", "@esbuild/linux-ia32": "0.27.0", "@esbuild/linux-loong64": "0.27.0", "@esbuild/linux-mips64el": "0.27.0", "@esbuild/linux-ppc64": "0.27.0", "@esbuild/linux-riscv64": "0.27.0", "@esbuild/linux-s390x": "0.27.0", "@esbuild/linux-x64": "0.27.0", "@esbuild/netbsd-arm64": "0.27.0", "@esbuild/netbsd-x64": "0.27.0", "@esbuild/openbsd-arm64": "0.27.0", "@esbuild/openbsd-x64": "0.27.0", "@esbuild/openharmony-arm64": "0.27.0", "@esbuild/sunos-x64": "0.27.0", "@esbuild/win32-arm64": "0.27.0", "@esbuild/win32-ia32": "0.27.0", "@esbuild/win32-x64": "0.27.0" }, "bin": { "esbuild": "bin/esbuild" } }, "sha512-jd0f4NHbD6cALCyGElNpGAOtWxSq46l9X/sWB0Nzd5er4Kz2YTm+Vl0qKFT9KUJvD8+fiO8AvoHhFvEatfVixA=="],1238 "esbuild": ["esbuild@0.27.0", "", { "optionalDependencies": { "@esbuild/aix-ppc64": "0.27.0", "@esbuild/android-arm": "0.27.0", "@esbuild/android-arm64": "0.27.0", "@esbuild/android-x64": "0.27.0", "@esbuild/darwin-arm64": "0.27.0", "@esbuild/darwin-x64": "0.27.0", "@esbuild/freebsd-arm64": "0.27.0", "@esbuild/freebsd-x64": "0.27.0", "@esbuild/linux-arm": "0.27.0", "@esbuild/linux-arm64": "0.27.0", "@esbuild/linux-ia32": "0.27.0", "@esbuild/linux-loong64": "0.27.0", "@esbuild/linux-mips64el": "0.27.0", "@esbuild/linux-ppc64": "0.27.0", "@esbuild/linux-riscv64": "0.27.0", "@esbuild/linux-s390x": "0.27.0", "@esbuild/linux-x64": "0.27.0", "@esbuild/netbsd-arm64": "0.27.0", "@esbuild/netbsd-x64": "0.27.0", "@esbuild/openbsd-arm64": "0.27.0", "@esbuild/openbsd-x64": "0.27.0", "@esbuild/openharmony-arm64": "0.27.0", "@esbuild/sunos-x64": "0.27.0", "@esbuild/win32-arm64": "0.27.0", "@esbuild/win32-ia32": "0.27.0", "@esbuild/win32-x64": "0.27.0" }, "bin": { "esbuild": "bin/esbuild" } }, "sha512-jd0f4NHbD6cALCyGElNpGAOtWxSq46l9X/sWB0Nzd5er4Kz2YTm+Vl0qKFT9KUJvD8+fiO8AvoHhFvEatfVixA=="],
1226 1239
1240 "esbuild-register": ["esbuild-register@3.6.0", "", { "dependencies": { "debug": "^4.3.4" }, "peerDependencies": { "esbuild": ">=0.12 <1" } }, "sha512-H2/S7Pm8a9CL1uhp9OvjwrBh5Pvx0H8qVOxNu8Wed9Y7qv56MPtq+GGM8RJpq6glYJn9Wspr8uw7l55uyinNeg=="],
1241
1227 "escalade": ["escalade@3.2.0", "", {}, "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA=="],1242 "escalade": ["escalade@3.2.0", "", {}, "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA=="],
1228 1243
1229 "escape-html": ["escape-html@1.0.3", "", {}, "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow=="],1244 "escape-html": ["escape-html@1.0.3", "", {}, "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow=="],
@@ -1972,6 +1987,8 @@ · 742 unmodified lines
1972 1987
1973 "source-map-js": ["source-map-js@1.2.1", "", {}, "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA=="],1988 "source-map-js": ["source-map-js@1.2.1", "", {}, "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA=="],
1974 1989
1990 "source-map-support": ["source-map-support@0.5.21", "", { "dependencies": { "buffer-from": "^1.0.0", "source-map": "^0.6.0" } }, "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w=="],
1991
1975 "space-separated-tokens": ["space-separated-tokens@2.0.2", "", {}, "sha512-PEGlAwrG8yXGXRjW32fGbg66JAlOAwbObuqVoJpv/mRgoWDQfgH1wDPvtzWyUSNAXBGSk8h755YDbbcEy3SH2Q=="],1992 "space-separated-tokens": ["space-separated-tokens@2.0.2", "", {}, "sha512-PEGlAwrG8yXGXRjW32fGbg66JAlOAwbObuqVoJpv/mRgoWDQfgH1wDPvtzWyUSNAXBGSk8h755YDbbcEy3SH2Q=="],
1976 1993
1977 "srvx": ["srvx@0.8.9", "", { "dependencies": { "cookie-es": "^2.0.0" }, "bin": { "srvx": "bin/srvx.mjs" } }, "sha512-wYc3VLZHRzwYrWJhkEqkhLb31TI0SOkfYZDkUhXdp3NoCnNS0FqajiQszZZjfow/VYEuc6Q5sZh9nM6kPy2NBQ=="],1994 "srvx": ["srvx@0.8.9", "", { "dependencies": { "cookie-es": "^2.0.0" }, "bin": { "srvx": "bin/srvx.mjs" } }, "sha512-wYc3VLZHRzwYrWJhkEqkhLb31TI0SOkfYZDkUhXdp3NoCnNS0FqajiQszZZjfow/VYEuc6Q5sZh9nM6kPy2NBQ=="],
@@ -2298,6 +2315,8 @@ · 320 unmodified lines
2298 2315
2299 "@cspotcode/source-map-support/@jridgewell/trace-mapping": ["@jridgewell/trace-mapping@0.3.9", "", { "dependencies": { "@jridgewell/resolve-uri": "^3.0.3", "@jridgewell/sourcemap-codec": "^1.4.10" } }, "sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ=="],2316 "@cspotcode/source-map-support/@jridgewell/trace-mapping": ["@jridgewell/trace-mapping@0.3.9", "", { "dependencies": { "@jridgewell/resolve-uri": "^3.0.3", "@jridgewell/sourcemap-codec": "^1.4.10" } }, "sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ=="],
2300 2317
2318 "@esbuild-kit/core-utils/esbuild": ["esbuild@0.18.20", "", { "optionalDependencies": { "@esbuild/android-arm": "0.18.20", "@esbuild/android-arm64": "0.18.20", "@esbuild/android-x64": "0.18.20", "@esbuild/darwin-arm64": "0.18.20", "@esbuild/darwin-x64": "0.18.20", "@esbuild/freebsd-arm64": "0.18.20", "@esbuild/freebsd-x64": "0.18.20", "@esbuild/linux-arm": "0.18.20", "@esbuild/linux-arm64": "0.18.20", "@esbuild/linux-ia32": "0.18.20", "@esbuild/linux-loong64": "0.18.20", "@esbuild/linux-mips64el": "0.18.20", "@esbuild/linux-ppc64": "0.18.20", "@esbuild/linux-riscv64": "0.18.20", "@esbuild/linux-s390x": "0.18.20", "@esbuild/linux-x64": "0.18.20", "@esbuild/netbsd-x64": "0.18.20", "@esbuild/openbsd-x64": "0.18.20", "@esbuild/sunos-x64": "0.18.20", "@esbuild/win32-arm64": "0.18.20", "@esbuild/win32-ia32": "0.18.20", "@esbuild/win32-x64": "0.18.20" }, "bin": { "esbuild": "bin/esbuild" } }, "sha512-ceqxoedUrcayh7Y7ZX6NdbbDzGROiyVBgC4PriJThBKSVPWnnFHZAkfI1lJT8QFkOwH4qOS2SJkS4wvpGl8BpA=="],
2319
2301 "@executor-v2/app-www/tailwindcss": ["tailwindcss@3.4.19", "", { "dependencies": { "@alloc/quick-lru": "^5.2.0", "arg": "^5.0.2", "chokidar": "^3.6.0", "didyoumean": "^1.2.2", "dlv": "^1.1.3", "fast-glob": "^3.3.2", "glob-parent": "^6.0.2", "is-glob": "^4.0.3", "jiti": "^1.21.7", "lilconfig": "^3.1.3", "micromatch": "^4.0.8", "normalize-path": "^3.0.0", "object-hash": "^3.0.0", "picocolors": "^1.1.1", "postcss": "^8.4.47", "postcss-import": "^15.1.0", "postcss-js": "^4.0.1", "postcss-load-config": "^4.0.2 || ^5.0 || ^6.0", "postcss-nested": "^6.2.0", "postcss-selector-parser": "^6.1.2", "resolve": "^1.22.8", "sucrase": "^3.35.0" }, "bin": { "tailwind": "lib/cli.js", "tailwindcss": "lib/cli.js" } }, "sha512-3ofp+LL8E+pK/JuPLPggVAIaEuhvIz4qNcf3nA1Xn2o/7fb7s/TYpHhwGDv1ZU3PkBluUVaF8PyCHcm48cKLWQ=="],2320 "@executor-v2/app-www/tailwindcss": ["tailwindcss@3.4.19", "", { "dependencies": { "@alloc/quick-lru": "^5.2.0", "arg": "^5.0.2", "chokidar": "^3.6.0", "didyoumean": "^1.2.2", "dlv": "^1.1.3", "fast-glob": "^3.3.2", "glob-parent": "^6.0.2", "is-glob": "^4.0.3", "jiti": "^1.21.7", "lilconfig": "^3.1.3", "micromatch": "^4.0.8", "normalize-path": "^3.0.0", "object-hash": "^3.0.0", "picocolors": "^1.1.1", "postcss": "^8.4.47", "postcss-import": "^15.1.0", "postcss-js": "^4.0.1", "postcss-load-config": "^4.0.2 || ^5.0 || ^6.0", "postcss-nested": "^6.2.0", "postcss-selector-parser": "^6.1.2", "resolve": "^1.22.8", "sucrase": "^3.35.0" }, "bin": { "tailwind": "lib/cli.js", "tailwindcss": "lib/cli.js" } }, "sha512-3ofp+LL8E+pK/JuPLPggVAIaEuhvIz4qNcf3nA1Xn2o/7fb7s/TYpHhwGDv1ZU3PkBluUVaF8PyCHcm48cKLWQ=="],
2302 2321
2303 "@mapbox/node-pre-gyp/node-fetch": ["node-fetch@2.7.0", "", { "dependencies": { "whatwg-url": "^5.0.0" }, "peerDependencies": { "encoding": "^0.1.0" }, "optionalPeers": ["encoding"] }, "sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A=="],2322 "@mapbox/node-pre-gyp/node-fetch": ["node-fetch@2.7.0", "", { "dependencies": { "whatwg-url": "^5.0.0" }, "peerDependencies": { "encoding": "^0.1.0" }, "optionalPeers": ["encoding"] }, "sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A=="],
@@ -2406,6 +2425,8 @@ · 102 unmodified lines
2406 2425
2407 "dom-serializer/entities": ["entities@4.5.0", "", {}, "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw=="],2426 "dom-serializer/entities": ["entities@4.5.0", "", {}, "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw=="],
2408 2427
2428 "drizzle-kit/esbuild": ["esbuild@0.25.12", "", { "optionalDependencies": { "@esbuild/aix-ppc64": "0.25.12", "@esbuild/android-arm": "0.25.12", "@esbuild/android-arm64": "0.25.12", "@esbuild/android-x64": "0.25.12", "@esbuild/darwin-arm64": "0.25.12", "@esbuild/darwin-x64": "0.25.12", "@esbuild/freebsd-arm64": "0.25.12", "@esbuild/freebsd-x64": "0.25.12", "@esbuild/linux-arm": "0.25.12", "@esbuild/linux-arm64": "0.25.12", "@esbuild/linux-ia32": "0.25.12", "@esbuild/linux-loong64": "0.25.12", "@esbuild/linux-mips64el": "0.25.12", "@esbuild/linux-ppc64": "0.25.12", "@esbuild/linux-riscv64": "0.25.12", "@esbuild/linux-s390x": "0.25.12", "@esbuild/linux-x64": "0.25.12", "@esbuild/netbsd-arm64": "0.25.12", "@esbuild/netbsd-x64": "0.25.12", "@esbuild/openbsd-arm64": "0.25.12", "@esbuild/openbsd-x64": "0.25.12", "@esbuild/openharmony-arm64": "0.25.12", "@esbuild/sunos-x64": "0.25.12", "@esbuild/win32-arm64": "0.25.12", "@esbuild/win32-ia32": "0.25.12", "@esbuild/win32-x64": "0.25.12" }, "bin": { "esbuild": "bin/esbuild" } }, "sha512-bbPBYYrtZbkt6Os6FiTLCTFxvq4tt3JKall1vRwshA3fdVztsLAatFaZobhkBC8/BrPetoa0oksYoKXoG4ryJg=="],
2429
2409 "edge-runtime/async-listen": ["async-listen@3.0.1", "", {}, "sha512-cWMaNwUJnf37C/S5TfCkk/15MwbPRwVYALA2jtjkbHjCmAPiDXyNJy2q3p1KAZzDLHAWyarUWSujUoHR4pEgrA=="],2430 "edge-runtime/async-listen": ["async-listen@3.0.1", "", {}, "sha512-cWMaNwUJnf37C/S5TfCkk/15MwbPRwVYALA2jtjkbHjCmAPiDXyNJy2q3p1KAZzDLHAWyarUWSujUoHR4pEgrA=="],
2410 2431
2411 "edge-runtime/picocolors": ["picocolors@1.0.0", "", {}, "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ=="],2432 "edge-runtime/picocolors": ["picocolors@1.0.0", "", {}, "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ=="],
@@ -2494,6 +2515,50 @@ · 82 unmodified lines
2494 2515
2495 "@babel/helper-compilation-targets/lru-cache/yallist": ["yallist@3.1.1", "", {}, "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g=="],2516 "@babel/helper-compilation-targets/lru-cache/yallist": ["yallist@3.1.1", "", {}, "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g=="],
2496 2517
2518 "@esbuild-kit/core-utils/esbuild/@esbuild/android-arm": ["@esbuild/android-arm@0.18.20", "", { "os": "android", "cpu": "arm" }, "sha512-fyi7TDI/ijKKNZTUJAQqiG5T7YjJXgnzkURqmGj13C6dCqckZBLdl4h7bkhHt/t0WP+zO9/zwroDvANaOqO5Sw=="],
2519
2520 "@esbuild-kit/core-utils/esbuild/@esbuild/android-arm64": ["@esbuild/android-arm64@0.18.20", "", { "os": "android", "cpu": "arm64" }, "sha512-Nz4rJcchGDtENV0eMKUNa6L12zz2zBDXuhj/Vjh18zGqB44Bi7MBMSXjgunJgjRhCmKOjnPuZp4Mb6OKqtMHLQ=="],
2521
2522 "@esbuild-kit/core-utils/esbuild/@esbuild/android-x64": ["@esbuild/android-x64@0.18.20", "", { "os": "android", "cpu": "x64" }, "sha512-8GDdlePJA8D6zlZYJV/jnrRAi6rOiNaCC/JclcXpB+KIuvfBN4owLtgzY2bsxnx666XjJx2kDPUmnTtR8qKQUg=="],
2523
2524 "@esbuild-kit/core-utils/esbuild/@esbuild/darwin-arm64": ["@esbuild/darwin-arm64@0.18.20", "", { "os": "darwin", "cpu": "arm64" }, "sha512-bxRHW5kHU38zS2lPTPOyuyTm+S+eobPUnTNkdJEfAddYgEcll4xkT8DB9d2008DtTbl7uJag2HuE5NZAZgnNEA=="],
2525
2526 "@esbuild-kit/core-utils/esbuild/@esbuild/darwin-x64": ["@esbuild/darwin-x64@0.18.20", "", { "os": "darwin", "cpu": "x64" }, "sha512-pc5gxlMDxzm513qPGbCbDukOdsGtKhfxD1zJKXjCCcU7ju50O7MeAZ8c4krSJcOIJGFR+qx21yMMVYwiQvyTyQ=="],
2527
2528 "@esbuild-kit/core-utils/esbuild/@esbuild/freebsd-arm64": ["@esbuild/freebsd-arm64@0.18.20", "", { "os": "freebsd", "cpu": "arm64" }, "sha512-yqDQHy4QHevpMAaxhhIwYPMv1NECwOvIpGCZkECn8w2WFHXjEwrBn3CeNIYsibZ/iZEUemj++M26W3cNR5h+Tw=="],
2529
2530 "@esbuild-kit/core-utils/esbuild/@esbuild/freebsd-x64": ["@esbuild/freebsd-x64@0.18.20", "", { "os": "freebsd", "cpu": "x64" }, "sha512-tgWRPPuQsd3RmBZwarGVHZQvtzfEBOreNuxEMKFcd5DaDn2PbBxfwLcj4+aenoh7ctXcbXmOQIn8HI6mCSw5MQ=="],
2531
2532 "@esbuild-kit/core-utils/esbuild/@esbuild/linux-arm": ["@esbuild/linux-arm@0.18.20", "", { "os": "linux", "cpu": "arm" }, "sha512-/5bHkMWnq1EgKr1V+Ybz3s1hWXok7mDFUMQ4cG10AfW3wL02PSZi5kFpYKrptDsgb2WAJIvRcDm+qIvXf/apvg=="],
2533
2534 "@esbuild-kit/core-utils/esbuild/@esbuild/linux-arm64": ["@esbuild/linux-arm64@0.18.20", "", { "os": "linux", "cpu": "arm64" }, "sha512-2YbscF+UL7SQAVIpnWvYwM+3LskyDmPhe31pE7/aoTMFKKzIc9lLbyGUpmmb8a8AixOL61sQ/mFh3jEjHYFvdA=="],
2535
2536 "@esbuild-kit/core-utils/esbuild/@esbuild/linux-ia32": ["@esbuild/linux-ia32@0.18.20", "", { "os": "linux", "cpu": "ia32" }, "sha512-P4etWwq6IsReT0E1KHU40bOnzMHoH73aXp96Fs8TIT6z9Hu8G6+0SHSw9i2isWrD2nbx2qo5yUqACgdfVGx7TA=="],
2537
2538 "@esbuild-kit/core-utils/esbuild/@esbuild/linux-loong64": ["@esbuild/linux-loong64@0.18.20", "", { "os": "linux", "cpu": "none" }, "sha512-nXW8nqBTrOpDLPgPY9uV+/1DjxoQ7DoB2N8eocyq8I9XuqJ7BiAMDMf9n1xZM9TgW0J8zrquIb/A7s3BJv7rjg=="],
2539
2540 "@esbuild-kit/core-utils/esbuild/@esbuild/linux-mips64el": ["@esbuild/linux-mips64el@0.18.20", "", { "os": "linux", "cpu": "none" }, "sha512-d5NeaXZcHp8PzYy5VnXV3VSd2D328Zb+9dEq5HE6bw6+N86JVPExrA6O68OPwobntbNJ0pzCpUFZTo3w0GyetQ=="],
2541
2542 "@esbuild-kit/core-utils/esbuild/@esbuild/linux-ppc64": ["@esbuild/linux-ppc64@0.18.20", "", { "os": "linux", "cpu": "ppc64" }, "sha512-WHPyeScRNcmANnLQkq6AfyXRFr5D6N2sKgkFo2FqguP44Nw2eyDlbTdZwd9GYk98DZG9QItIiTlFLHJHjxP3FA=="],
2543
2544 "@esbuild-kit/core-utils/esbuild/@esbuild/linux-riscv64": ["@esbuild/linux-riscv64@0.18.20", "", { "os": "linux", "cpu": "none" }, "sha512-WSxo6h5ecI5XH34KC7w5veNnKkju3zBRLEQNY7mv5mtBmrP/MjNBCAlsM2u5hDBlS3NGcTQpoBvRzqBcRtpq1A=="],
2545
2546 "@esbuild-kit/core-utils/esbuild/@esbuild/linux-s390x": ["@esbuild/linux-s390x@0.18.20", "", { "os": "linux", "cpu": "s390x" }, "sha512-+8231GMs3mAEth6Ja1iK0a1sQ3ohfcpzpRLH8uuc5/KVDFneH6jtAJLFGafpzpMRO6DzJ6AvXKze9LfFMrIHVQ=="],
2547
2548 "@esbuild-kit/core-utils/esbuild/@esbuild/linux-x64": ["@esbuild/linux-x64@0.18.20", "", { "os": "linux", "cpu": "x64" }, "sha512-UYqiqemphJcNsFEskc73jQ7B9jgwjWrSayxawS6UVFZGWrAAtkzjxSqnoclCXxWtfwLdzU+vTpcNYhpn43uP1w=="],
2549
2550 "@esbuild-kit/core-utils/esbuild/@esbuild/netbsd-x64": ["@esbuild/netbsd-x64@0.18.20", "", { "os": "none", "cpu": "x64" }, "sha512-iO1c++VP6xUBUmltHZoMtCUdPlnPGdBom6IrO4gyKPFFVBKioIImVooR5I83nTew5UOYrk3gIJhbZh8X44y06A=="],
2551
2552 "@esbuild-kit/core-utils/esbuild/@esbuild/openbsd-x64": ["@esbuild/openbsd-x64@0.18.20", "", { "os": "openbsd", "cpu": "x64" }, "sha512-e5e4YSsuQfX4cxcygw/UCPIEP6wbIL+se3sxPdCiMbFLBWu0eiZOJ7WoD+ptCLrmjZBK1Wk7I6D/I3NglUGOxg=="],
2553
2554 "@esbuild-kit/core-utils/esbuild/@esbuild/sunos-x64": ["@esbuild/sunos-x64@0.18.20", "", { "os": "sunos", "cpu": "x64" }, "sha512-kDbFRFp0YpTQVVrqUd5FTYmWo45zGaXe0X8E1G/LKFC0v8x0vWrhOWSLITcCn63lmZIxfOMXtCfti/RxN/0wnQ=="],
2555
2556 "@esbuild-kit/core-utils/esbuild/@esbuild/win32-arm64": ["@esbuild/win32-arm64@0.18.20", "", { "os": "win32", "cpu": "arm64" }, "sha512-ddYFR6ItYgoaq4v4JmQQaAI5s7npztfV4Ag6NrhiaW0RrnOXqBkgwZLofVTlq1daVTQNhtI5oieTvkRPfZrePg=="],
2557
2558 "@esbuild-kit/core-utils/esbuild/@esbuild/win32-ia32": ["@esbuild/win32-ia32@0.18.20", "", { "os": "win32", "cpu": "ia32" }, "sha512-Wv7QBi3ID/rROT08SABTS7eV4hX26sVduqDOTe1MvGMjNd3EjOz4b7zeexIR62GTIEKrfJXKL9LFxTYgkyeu7g=="],
2559
2560 "@esbuild-kit/core-utils/esbuild/@esbuild/win32-x64": ["@esbuild/win32-x64@0.18.20", "", { "os": "win32", "cpu": "x64" }, "sha512-kTdfRcSiDfQca/y9QIkng02avJ+NCaQvrMejlsB3RRv5sE9rRoeBPISaZpKxHELzRxZyLvNts1P27W3wV+8geQ=="],
2561
2497 "@executor-v2/app-www/tailwindcss/chokidar": ["chokidar@3.6.0", "", { "dependencies": { "anymatch": "~3.1.2", "braces": "~3.0.2", "glob-parent": "~5.1.2", "is-binary-path": "~2.1.0", "is-glob": "~4.0.1", "normalize-path": "~3.0.0", "readdirp": "~3.6.0" }, "optionalDependencies": { "fsevents": "~2.3.2" } }, "sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw=="],2562 "@executor-v2/app-www/tailwindcss/chokidar": ["chokidar@3.6.0", "", { "dependencies": { "anymatch": "~3.1.2", "braces": "~3.0.2", "glob-parent": "~5.1.2", "is-binary-path": "~2.1.0", "is-glob": "~4.0.1", "normalize-path": "~3.0.0", "readdirp": "~3.6.0" }, "optionalDependencies": { "fsevents": "~2.3.2" } }, "sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw=="],
2498 2563
2499 "@ts-morph/common/minimatch/brace-expansion": ["brace-expansion@1.1.12", "", { "dependencies": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" } }, "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg=="],2564 "@ts-morph/common/minimatch/brace-expansion": ["brace-expansion@1.1.12", "", { "dependencies": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" } }, "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg=="],
@@ -2584,6 +2649,58 @@ · 84 unmodified lines
2584 2649
2585 "csso/css-tree/mdn-data": ["mdn-data@2.0.28", "", {}, "sha512-aylIc7Z9y4yzHYAJNuESG3hfhC+0Ibp/MAMiaOZgNv4pmEdFyfZhhhny4MNiAfWdBQ1RQ2mfDWmM1x8SvGyp8g=="],2650 "csso/css-tree/mdn-data": ["mdn-data@2.0.28", "", {}, "sha512-aylIc7Z9y4yzHYAJNuESG3hfhC+0Ibp/MAMiaOZgNv4pmEdFyfZhhhny4MNiAfWdBQ1RQ2mfDWmM1x8SvGyp8g=="],
2586 2651
2652 "drizzle-kit/esbuild/@esbuild/aix-ppc64": ["@esbuild/aix-ppc64@0.25.12", "", { "os": "aix", "cpu": "ppc64" }, "sha512-Hhmwd6CInZ3dwpuGTF8fJG6yoWmsToE+vYgD4nytZVxcu1ulHpUQRAB1UJ8+N1Am3Mz4+xOByoQoSZf4D+CpkA=="],
2653
2654 "drizzle-kit/esbuild/@esbuild/android-arm": ["@esbuild/android-arm@0.25.12", "", { "os": "android", "cpu": "arm" }, "sha512-VJ+sKvNA/GE7Ccacc9Cha7bpS8nyzVv0jdVgwNDaR4gDMC/2TTRc33Ip8qrNYUcpkOHUT5OZ0bUcNNVZQ9RLlg=="],
2655
2656 "drizzle-kit/esbuild/@esbuild/android-arm64": ["@esbuild/android-arm64@0.25.12", "", { "os": "android", "cpu": "arm64" }, "sha512-6AAmLG7zwD1Z159jCKPvAxZd4y/VTO0VkprYy+3N2FtJ8+BQWFXU+OxARIwA46c5tdD9SsKGZ/1ocqBS/gAKHg=="],
2657
2658 "drizzle-kit/esbuild/@esbuild/android-x64": ["@esbuild/android-x64@0.25.12", "", { "os": "android", "cpu": "x64" }, "sha512-5jbb+2hhDHx5phYR2By8GTWEzn6I9UqR11Kwf22iKbNpYrsmRB18aX/9ivc5cabcUiAT/wM+YIZ6SG9QO6a8kg=="],
2659
2660 "drizzle-kit/esbuild/@esbuild/darwin-arm64": ["@esbuild/darwin-arm64@0.25.12", "", { "os": "darwin", "cpu": "arm64" }, "sha512-N3zl+lxHCifgIlcMUP5016ESkeQjLj/959RxxNYIthIg+CQHInujFuXeWbWMgnTo4cp5XVHqFPmpyu9J65C1Yg=="],
2661
2662 "drizzle-kit/esbuild/@esbuild/darwin-x64": ["@esbuild/darwin-x64@0.25.12", "", { "os": "darwin", "cpu": "x64" }, "sha512-HQ9ka4Kx21qHXwtlTUVbKJOAnmG1ipXhdWTmNXiPzPfWKpXqASVcWdnf2bnL73wgjNrFXAa3yYvBSd9pzfEIpA=="],
2663
2664 "drizzle-kit/esbuild/@esbuild/freebsd-arm64": ["@esbuild/freebsd-arm64@0.25.12", "", { "os": "freebsd", "cpu": "arm64" }, "sha512-gA0Bx759+7Jve03K1S0vkOu5Lg/85dou3EseOGUes8flVOGxbhDDh/iZaoek11Y8mtyKPGF3vP8XhnkDEAmzeg=="],
2665
2666 "drizzle-kit/esbuild/@esbuild/freebsd-x64": ["@esbuild/freebsd-x64@0.25.12", "", { "os": "freebsd", "cpu": "x64" }, "sha512-TGbO26Yw2xsHzxtbVFGEXBFH0FRAP7gtcPE7P5yP7wGy7cXK2oO7RyOhL5NLiqTlBh47XhmIUXuGciXEqYFfBQ=="],
2667
2668 "drizzle-kit/esbuild/@esbuild/linux-arm": ["@esbuild/linux-arm@0.25.12", "", { "os": "linux", "cpu": "arm" }, "sha512-lPDGyC1JPDou8kGcywY0YILzWlhhnRjdof3UlcoqYmS9El818LLfJJc3PXXgZHrHCAKs/Z2SeZtDJr5MrkxtOw=="],
2669
2670 "drizzle-kit/esbuild/@esbuild/linux-arm64": ["@esbuild/linux-arm64@0.25.12", "", { "os": "linux", "cpu": "arm64" }, "sha512-8bwX7a8FghIgrupcxb4aUmYDLp8pX06rGh5HqDT7bB+8Rdells6mHvrFHHW2JAOPZUbnjUpKTLg6ECyzvas2AQ=="],
2671
2672 "drizzle-kit/esbuild/@esbuild/linux-ia32": ["@esbuild/linux-ia32@0.25.12", "", { "os": "linux", "cpu": "ia32" }, "sha512-0y9KrdVnbMM2/vG8KfU0byhUN+EFCny9+8g202gYqSSVMonbsCfLjUO+rCci7pM0WBEtz+oK/PIwHkzxkyharA=="],
2673
2674 "drizzle-kit/esbuild/@esbuild/linux-loong64": ["@esbuild/linux-loong64@0.25.12", "", { "os": "linux", "cpu": "none" }, "sha512-h///Lr5a9rib/v1GGqXVGzjL4TMvVTv+s1DPoxQdz7l/AYv6LDSxdIwzxkrPW438oUXiDtwM10o9PmwS/6Z0Ng=="],
2675
2676 "drizzle-kit/esbuild/@esbuild/linux-mips64el": ["@esbuild/linux-mips64el@0.25.12", "", { "os": "linux", "cpu": "none" }, "sha512-iyRrM1Pzy9GFMDLsXn1iHUm18nhKnNMWscjmp4+hpafcZjrr2WbT//d20xaGljXDBYHqRcl8HnxbX6uaA/eGVw=="],
2677
2678 "drizzle-kit/esbuild/@esbuild/linux-ppc64": ["@esbuild/linux-ppc64@0.25.12", "", { "os": "linux", "cpu": "ppc64" }, "sha512-9meM/lRXxMi5PSUqEXRCtVjEZBGwB7P/D4yT8UG/mwIdze2aV4Vo6U5gD3+RsoHXKkHCfSxZKzmDssVlRj1QQA=="],
2679
2680 "drizzle-kit/esbuild/@esbuild/linux-riscv64": ["@esbuild/linux-riscv64@0.25.12", "", { "os": "linux", "cpu": "none" }, "sha512-Zr7KR4hgKUpWAwb1f3o5ygT04MzqVrGEGXGLnj15YQDJErYu/BGg+wmFlIDOdJp0PmB0lLvxFIOXZgFRrdjR0w=="],
2681
2682 "drizzle-kit/esbuild/@esbuild/linux-s390x": ["@esbuild/linux-s390x@0.25.12", "", { "os": "linux", "cpu": "s390x" }, "sha512-MsKncOcgTNvdtiISc/jZs/Zf8d0cl/t3gYWX8J9ubBnVOwlk65UIEEvgBORTiljloIWnBzLs4qhzPkJcitIzIg=="],
2683
2684 "drizzle-kit/esbuild/@esbuild/linux-x64": ["@esbuild/linux-x64@0.25.12", "", { "os": "linux", "cpu": "x64" }, "sha512-uqZMTLr/zR/ed4jIGnwSLkaHmPjOjJvnm6TVVitAa08SLS9Z0VM8wIRx7gWbJB5/J54YuIMInDquWyYvQLZkgw=="],
2685
2686 "drizzle-kit/esbuild/@esbuild/netbsd-arm64": ["@esbuild/netbsd-arm64@0.25.12", "", { "os": "none", "cpu": "arm64" }, "sha512-xXwcTq4GhRM7J9A8Gv5boanHhRa/Q9KLVmcyXHCTaM4wKfIpWkdXiMog/KsnxzJ0A1+nD+zoecuzqPmCRyBGjg=="],
2687
2688 "drizzle-kit/esbuild/@esbuild/netbsd-x64": ["@esbuild/netbsd-x64@0.25.12", "", { "os": "none", "cpu": "x64" }, "sha512-Ld5pTlzPy3YwGec4OuHh1aCVCRvOXdH8DgRjfDy/oumVovmuSzWfnSJg+VtakB9Cm0gxNO9BzWkj6mtO1FMXkQ=="],
2689
2690 "drizzle-kit/esbuild/@esbuild/openbsd-arm64": ["@esbuild/openbsd-arm64@0.25.12", "", { "os": "openbsd", "cpu": "arm64" }, "sha512-fF96T6KsBo/pkQI950FARU9apGNTSlZGsv1jZBAlcLL1MLjLNIWPBkj5NlSz8aAzYKg+eNqknrUJ24QBybeR5A=="],
2691
2692 "drizzle-kit/esbuild/@esbuild/openbsd-x64": ["@esbuild/openbsd-x64@0.25.12", "", { "os": "openbsd", "cpu": "x64" }, "sha512-MZyXUkZHjQxUvzK7rN8DJ3SRmrVrke8ZyRusHlP+kuwqTcfWLyqMOE3sScPPyeIXN/mDJIfGXvcMqCgYKekoQw=="],
2693
2694 "drizzle-kit/esbuild/@esbuild/openharmony-arm64": ["@esbuild/openharmony-arm64@0.25.12", "", { "os": "none", "cpu": "arm64" }, "sha512-rm0YWsqUSRrjncSXGA7Zv78Nbnw4XL6/dzr20cyrQf7ZmRcsovpcRBdhD43Nuk3y7XIoW2OxMVvwuRvk9XdASg=="],
2695
2696 "drizzle-kit/esbuild/@esbuild/sunos-x64": ["@esbuild/sunos-x64@0.25.12", "", { "os": "sunos", "cpu": "x64" }, "sha512-3wGSCDyuTHQUzt0nV7bocDy72r2lI33QL3gkDNGkod22EsYl04sMf0qLb8luNKTOmgF/eDEDP5BFNwoBKH441w=="],
2697
2698 "drizzle-kit/esbuild/@esbuild/win32-arm64": ["@esbuild/win32-arm64@0.25.12", "", { "os": "win32", "cpu": "arm64" }, "sha512-rMmLrur64A7+DKlnSuwqUdRKyd3UE7oPJZmnljqEptesKM8wx9J8gx5u0+9Pq0fQQW8vqeKebwNXdfOyP+8Bsg=="],
2699
2700 "drizzle-kit/esbuild/@esbuild/win32-ia32": ["@esbuild/win32-ia32@0.25.12", "", { "os": "win32", "cpu": "ia32" }, "sha512-HkqnmmBoCbCwxUKKNPBixiWDGCpQGVsrQfJoVGYLPT41XWF8lHuE5N6WhVia2n4o5QK5M4tYr21827fNhi4byQ=="],
2701
2702 "drizzle-kit/esbuild/@esbuild/win32-x64": ["@esbuild/win32-x64@0.25.12", "", { "os": "win32", "cpu": "x64" }, "sha512-alJC0uCZpTFrSL0CCDjcgleBXPnCrEAhTBILpeAp7M/OFgoqtAetfBzX0xM00MUsVVPpVjlPuMbREqnZCXaTnA=="],
2703
2587 "express/mime-types/mime-db": ["mime-db@1.54.0", "", {}, "sha512-aU5EJuIN2WDemCcAp2vFBfp/m4EAhWJnUNSSw0ixs7/kXbd6Pg64EmwJkNdFhB8aWt1sH2CTXrLxo/iAGV3oPQ=="],2704 "express/mime-types/mime-db": ["mime-db@1.54.0", "", {}, "sha512-aU5EJuIN2WDemCcAp2vFBfp/m4EAhWJnUNSSw0ixs7/kXbd6Pg64EmwJkNdFhB8aWt1sH2CTXrLxo/iAGV3oPQ=="],
2588 2705
2589 "micro/raw-body/bytes": ["bytes@3.1.0", "", {}, "sha512-zauLjrfCG+xvoyaqLoV8bLVXXNGC4JqlxFCutSDWA6fJrTo2ZuvLYTqZ7aHBLZSMOopbzwv8f+wZcVzfVTI2Dg=="],2706 "micro/raw-body/bytes": ["bytes@3.1.0", "", {}, "sha512-zauLjrfCG+xvoyaqLoV8bLVXXNGC4JqlxFCutSDWA6fJrTo2ZuvLYTqZ7aHBLZSMOopbzwv8f+wZcVzfVTI2Dg=="],
packages/persistence-sql/drizzle.config.pg.ts+14−0
@@ -0,0 +1,14 @@
1import { defineConfig } from "drizzle-kit";
2
3const databaseUrl = process.env.DATABASE_URL ?? "postgres://localhost:5432/executor_v2";
4
5export default defineConfig({
6 dialect: "postgresql",
7 schema: "./src/schema-pg.ts",
8 out: "./drizzle/postgres",
9 dbCredentials: {
10 url: databaseUrl,
11 },
12 strict: true,
13 verbose: true,
14});
packages/persistence-sql/drizzle.config.ts+12−0
@@ -0,0 +1,12 @@
1import { defineConfig } from "drizzle-kit";
2
3export default defineConfig({
4 dialect: "sqlite",
5 schema: "./src/schema.ts",
6 out: "./drizzle/sqlite",
7 dbCredentials: {
8 url: "./.executor-v2/control-plane.sqlite",
9 },
10 strict: true,
11 verbose: true,
12});
packages/persistence-sql/drizzle/0000_initial_schema.sql+0−139
@@ -1,139 +0,0 @@
1CREATE TABLE IF NOT EXISTS profile (
2 id BIGINT PRIMARY KEY,
3 schema_version BIGINT NOT NULL,
4 generated_at BIGINT NOT NULL,
5 profile_json TEXT NOT NULL,
6 updated_at BIGINT NOT NULL,
7 CHECK (id = 1)
8);
9--> statement-breakpoint
10
11CREATE TABLE IF NOT EXISTS organizations (
12 id TEXT PRIMARY KEY,
13 payload_json TEXT NOT NULL,
14 updated_at BIGINT NOT NULL
15);
16--> statement-breakpoint
17
18CREATE TABLE IF NOT EXISTS organization_memberships (
19 id TEXT PRIMARY KEY,
20 workspace_id TEXT NULL,
21 payload_json TEXT NOT NULL,
22 updated_at BIGINT NOT NULL
23);
24--> statement-breakpoint
25
26CREATE TABLE IF NOT EXISTS workspaces (
27 id TEXT PRIMARY KEY,
28 workspace_id TEXT NULL,
29 payload_json TEXT NOT NULL,
30 updated_at BIGINT NOT NULL
31);
32--> statement-breakpoint
33
34CREATE TABLE IF NOT EXISTS sources (
35 workspace_id TEXT NOT NULL,
36 source_id TEXT NOT NULL,
37 name TEXT NOT NULL,
38 payload_json TEXT NOT NULL,
39 updated_at BIGINT NOT NULL,
40 PRIMARY KEY (workspace_id, source_id)
41);
42--> statement-breakpoint
43
44CREATE INDEX IF NOT EXISTS sources_workspace_name_idx
45ON sources (workspace_id, name);
46--> statement-breakpoint
47
48CREATE TABLE IF NOT EXISTS tool_artifacts (
49 workspace_id TEXT NOT NULL,
50 source_id TEXT NOT NULL,
51 payload_json TEXT NOT NULL,
52 updated_at BIGINT NOT NULL,
53 PRIMARY KEY (workspace_id, source_id)
54);
55--> statement-breakpoint
56
57CREATE TABLE IF NOT EXISTS auth_connections (
58 id TEXT PRIMARY KEY,
59 workspace_id TEXT NULL,
60 payload_json TEXT NOT NULL,
61 updated_at BIGINT NOT NULL
62);
63--> statement-breakpoint
64
65CREATE TABLE IF NOT EXISTS source_auth_bindings (
66 id TEXT PRIMARY KEY,
67 workspace_id TEXT NULL,
68 payload_json TEXT NOT NULL,
69 updated_at BIGINT NOT NULL
70);
71--> statement-breakpoint
72
73CREATE TABLE IF NOT EXISTS auth_materials (
74 id TEXT PRIMARY KEY,
75 workspace_id TEXT NULL,
76 payload_json TEXT NOT NULL,
77 updated_at BIGINT NOT NULL
78);
79--> statement-breakpoint
80
81CREATE TABLE IF NOT EXISTS oauth_states (
82 id TEXT PRIMARY KEY,
83 workspace_id TEXT NULL,
84 payload_json TEXT NOT NULL,
85 updated_at BIGINT NOT NULL
86);
87--> statement-breakpoint
88
89CREATE TABLE IF NOT EXISTS policies (
90 id TEXT PRIMARY KEY,
91 workspace_id TEXT NULL,
92 payload_json TEXT NOT NULL,
93 updated_at BIGINT NOT NULL
94);
95--> statement-breakpoint
96
97CREATE TABLE IF NOT EXISTS approvals (
98 id TEXT PRIMARY KEY,
99 workspace_id TEXT NULL,
100 payload_json TEXT NOT NULL,
101 updated_at BIGINT NOT NULL
102);
103--> statement-breakpoint
104
105CREATE TABLE IF NOT EXISTS task_runs (
106 id TEXT PRIMARY KEY,
107 workspace_id TEXT NULL,
108 payload_json TEXT NOT NULL,
109 updated_at BIGINT NOT NULL
110);
111--> statement-breakpoint
112
113CREATE TABLE IF NOT EXISTS storage_instances (
114 id TEXT PRIMARY KEY,
115 workspace_id TEXT NULL,
116 payload_json TEXT NOT NULL,
117 updated_at BIGINT NOT NULL
118);
119--> statement-breakpoint
120
121CREATE TABLE IF NOT EXISTS sync_states (
122 id TEXT PRIMARY KEY,
123 workspace_id TEXT NULL,
124 payload_json TEXT NOT NULL,
125 updated_at BIGINT NOT NULL
126);
127--> statement-breakpoint
128
129CREATE TABLE IF NOT EXISTS events (
130 id TEXT PRIMARY KEY,
131 workspace_id TEXT NOT NULL,
132 sequence BIGINT NOT NULL,
133 event_json TEXT NOT NULL,
134 created_at BIGINT NOT NULL
135);
136--> statement-breakpoint
137
138CREATE UNIQUE INDEX IF NOT EXISTS events_workspace_sequence_idx
139ON events (workspace_id, sequence);
packages/persistence-sql/drizzle/meta/_journal.json+0−13
@@ -1,13 +0,0 @@
1{
2 "version": "1",
3 "dialect": "sqlite",
4 "entries": [
5 {
6 "idx": 0,
7 "version": "1",
8 "when": 1700000000000,
9 "tag": "0000_initial_schema",
10 "breakpoints": true
11 }
12 ]
13}
packages/persistence-sql/drizzle/postgres/0000_spicy_barracuda.sql+224−0
@@ -0,0 +1,224 @@
1CREATE TABLE "approvals" (
2 "id" text PRIMARY KEY NOT NULL,
3 "workspace_id" text NOT NULL,
4 "task_run_id" text NOT NULL,
5 "call_id" text NOT NULL,
6 "tool_path" text NOT NULL,
7 "status" text NOT NULL,
8 "input_preview_json" text NOT NULL,
9 "reason" text,
10 "requested_at" bigint NOT NULL,
11 "resolved_at" bigint
12);
13--> statement-breakpoint
14CREATE TABLE "auth_connections" (
15 "id" text PRIMARY KEY NOT NULL,
16 "organization_id" text NOT NULL,
17 "workspace_id" text,
18 "account_id" text,
19 "owner_type" text NOT NULL,
20 "strategy" text NOT NULL,
21 "display_name" text NOT NULL,
22 "status" text NOT NULL,
23 "status_reason" text,
24 "last_auth_error_class" text,
25 "metadata_json" text,
26 "additional_headers_json" text,
27 "created_by_account_id" text,
28 "created_at" bigint NOT NULL,
29 "updated_at" bigint NOT NULL,
30 "last_used_at" bigint
31);
32--> statement-breakpoint
33CREATE TABLE "auth_materials" (
34 "id" text PRIMARY KEY NOT NULL,
35 "connection_id" text NOT NULL,
36 "ciphertext" text NOT NULL,
37 "key_version" text NOT NULL,
38 "created_at" bigint NOT NULL,
39 "updated_at" bigint NOT NULL
40);
41--> statement-breakpoint
42CREATE TABLE "oauth_states" (
43 "id" text PRIMARY KEY NOT NULL,
44 "connection_id" text NOT NULL,
45 "access_token_ciphertext" text NOT NULL,
46 "refresh_token_ciphertext" text,
47 "key_version" text NOT NULL,
48 "expires_at" bigint,
49 "scope" text,
50 "token_type" text,
51 "issuer" text,
52 "refresh_config_json" text,
53 "token_version" bigint NOT NULL,
54 "lease_holder" text,
55 "lease_expires_at" bigint,
56 "lease_fence" bigint NOT NULL,
57 "last_refresh_at" bigint,
58 "last_refresh_error_class" text,
59 "last_refresh_error" text,
60 "reauth_required_at" bigint,
61 "created_at" bigint NOT NULL,
62 "updated_at" bigint NOT NULL
63);
64--> statement-breakpoint
65CREATE TABLE "organization_memberships" (
66 "id" text PRIMARY KEY NOT NULL,
67 "organization_id" text NOT NULL,
68 "account_id" text NOT NULL,
69 "role" text NOT NULL,
70 "status" text NOT NULL,
71 "billable" boolean NOT NULL,
72 "invited_by_account_id" text,
73 "joined_at" bigint,
74 "created_at" bigint NOT NULL,
75 "updated_at" bigint NOT NULL
76);
77--> statement-breakpoint
78CREATE TABLE "organizations" (
79 "id" text PRIMARY KEY NOT NULL,
80 "slug" text NOT NULL,
81 "name" text NOT NULL,
82 "status" text NOT NULL,
83 "created_by_account_id" text,
84 "created_at" bigint NOT NULL,
85 "updated_at" bigint NOT NULL
86);
87--> statement-breakpoint
88CREATE TABLE "policies" (
89 "id" text PRIMARY KEY NOT NULL,
90 "workspace_id" text NOT NULL,
91 "tool_path_pattern" text NOT NULL,
92 "decision" text NOT NULL,
93 "created_at" bigint NOT NULL,
94 "updated_at" bigint NOT NULL
95);
96--> statement-breakpoint
97CREATE TABLE "profile" (
98 "id" text PRIMARY KEY NOT NULL,
99 "default_workspace_id" text,
100 "display_name" text NOT NULL,
101 "runtime_mode" text NOT NULL,
102 "created_at" bigint NOT NULL,
103 "updated_at" bigint NOT NULL
104);
105--> statement-breakpoint
106CREATE TABLE "source_auth_bindings" (
107 "id" text PRIMARY KEY NOT NULL,
108 "source_id" text NOT NULL,
109 "connection_id" text NOT NULL,
110 "organization_id" text NOT NULL,
111 "workspace_id" text,
112 "account_id" text,
113 "scope_type" text NOT NULL,
114 "selector" text,
115 "enabled" boolean NOT NULL,
116 "created_at" bigint NOT NULL,
117 "updated_at" bigint NOT NULL
118);
119--> statement-breakpoint
120CREATE TABLE "sources" (
121 "workspace_id" text NOT NULL,
122 "source_id" text NOT NULL,
123 "name" text NOT NULL,
124 "kind" text NOT NULL,
125 "endpoint" text NOT NULL,
126 "status" text NOT NULL,
127 "enabled" boolean NOT NULL,
128 "config_json" text NOT NULL,
129 "source_hash" text,
130 "last_error" text,
131 "created_at" bigint NOT NULL,
132 "updated_at" bigint NOT NULL,
133 CONSTRAINT "sources_workspace_id_source_id_pk" PRIMARY KEY("workspace_id","source_id")
134);
135--> statement-breakpoint
136CREATE TABLE "storage_instances" (
137 "id" text PRIMARY KEY NOT NULL,
138 "scope_type" text NOT NULL,
139 "durability" text NOT NULL,
140 "status" text NOT NULL,
141 "provider" text NOT NULL,
142 "backend_key" text NOT NULL,
143 "organization_id" text NOT NULL,
144 "workspace_id" text,
145 "account_id" text,
146 "created_by_account_id" text,
147 "purpose" text,
148 "size_bytes" bigint,
149 "file_count" bigint,
150 "created_at" bigint NOT NULL,
151 "updated_at" bigint NOT NULL,
152 "last_seen_at" bigint NOT NULL,
153 "closed_at" bigint,
154 "expires_at" bigint
155);
156--> statement-breakpoint
157CREATE TABLE "sync_states" (
158 "id" text PRIMARY KEY NOT NULL,
159 "workspace_id" text NOT NULL,
160 "target" text NOT NULL,
161 "target_url" text NOT NULL,
162 "linked_subject" text,
163 "cursor" text,
164 "last_sync_at" bigint,
165 "updated_at" bigint NOT NULL
166);
167--> statement-breakpoint
168CREATE TABLE "task_runs" (
169 "id" text PRIMARY KEY NOT NULL,
170 "workspace_id" text NOT NULL,
171 "account_id" text NOT NULL,
172 "session_id" text NOT NULL,
173 "runtime_id" text NOT NULL,
174 "code_hash" text NOT NULL,
175 "status" text NOT NULL,
176 "started_at" bigint,
177 "completed_at" bigint,
178 "exit_code" bigint,
179 "error" text
180);
181--> statement-breakpoint
182CREATE TABLE "tool_artifacts" (
183 "id" text NOT NULL,
184 "workspace_id" text NOT NULL,
185 "source_id" text NOT NULL,
186 "source_hash" text NOT NULL,
187 "tool_count" bigint NOT NULL,
188 "manifest_json" text NOT NULL,
189 "created_at" bigint NOT NULL,
190 "updated_at" bigint NOT NULL,
191 CONSTRAINT "tool_artifacts_workspace_id_source_id_pk" PRIMARY KEY("workspace_id","source_id")
192);
193--> statement-breakpoint
194CREATE TABLE "workspaces" (
195 "id" text PRIMARY KEY NOT NULL,
196 "organization_id" text NOT NULL,
197 "name" text NOT NULL,
198 "created_by_account_id" text,
199 "created_at" bigint NOT NULL,
200 "updated_at" bigint NOT NULL
201);
202--> statement-breakpoint
203CREATE INDEX "approvals_workspace_idx" ON "approvals" USING btree ("workspace_id");--> statement-breakpoint
204CREATE INDEX "approvals_task_run_idx" ON "approvals" USING btree ("task_run_id");--> statement-breakpoint
205CREATE INDEX "auth_connections_org_idx" ON "auth_connections" USING btree ("organization_id");--> statement-breakpoint
206CREATE INDEX "auth_connections_workspace_idx" ON "auth_connections" USING btree ("workspace_id");--> statement-breakpoint
207CREATE INDEX "auth_connections_account_idx" ON "auth_connections" USING btree ("account_id");--> statement-breakpoint
208CREATE INDEX "auth_materials_connection_idx" ON "auth_materials" USING btree ("connection_id");--> statement-breakpoint
209CREATE INDEX "oauth_states_connection_idx" ON "oauth_states" USING btree ("connection_id");--> statement-breakpoint
210CREATE INDEX "organization_memberships_org_idx" ON "organization_memberships" USING btree ("organization_id");--> statement-breakpoint
211CREATE INDEX "organization_memberships_account_idx" ON "organization_memberships" USING btree ("account_id");--> statement-breakpoint
212CREATE INDEX "policies_workspace_idx" ON "policies" USING btree ("workspace_id");--> statement-breakpoint
213CREATE INDEX "source_auth_bindings_source_idx" ON "source_auth_bindings" USING btree ("source_id");--> statement-breakpoint
214CREATE INDEX "source_auth_bindings_connection_idx" ON "source_auth_bindings" USING btree ("connection_id");--> statement-breakpoint
215CREATE INDEX "source_auth_bindings_org_idx" ON "source_auth_bindings" USING btree ("organization_id");--> statement-breakpoint
216CREATE INDEX "source_auth_bindings_workspace_idx" ON "source_auth_bindings" USING btree ("workspace_id");--> statement-breakpoint
217CREATE INDEX "source_auth_bindings_account_idx" ON "source_auth_bindings" USING btree ("account_id");--> statement-breakpoint
218CREATE INDEX "sources_workspace_name_idx" ON "sources" USING btree ("workspace_id","name");--> statement-breakpoint
219CREATE INDEX "storage_instances_org_idx" ON "storage_instances" USING btree ("organization_id");--> statement-breakpoint
220CREATE INDEX "storage_instances_workspace_idx" ON "storage_instances" USING btree ("workspace_id");--> statement-breakpoint
221CREATE INDEX "sync_states_workspace_idx" ON "sync_states" USING btree ("workspace_id");--> statement-breakpoint
222CREATE INDEX "task_runs_workspace_idx" ON "task_runs" USING btree ("workspace_id");--> statement-breakpoint
223CREATE UNIQUE INDEX "tool_artifacts_id_idx" ON "tool_artifacts" USING btree ("id");--> statement-breakpoint
224CREATE INDEX "workspaces_org_idx" ON "workspaces" USING btree ("organization_id");
packages/persistence-sql/drizzle/postgres/meta/0000_snapshot.json+1509−0
@@ -0,0 +1,1509 @@
1{
2 "id": "5ce8d2a0-b31c-4d34-bd01-c638ca0d5d87",
3 "prevId": "00000000-0000-0000-0000-000000000000",
4 "version": "7",
5 "dialect": "postgresql",
6 "tables": {
7 "public.approvals": {
8 "name": "approvals",
9 "schema": "",
10 "columns": {
11 "id": {
12 "name": "id",
13 "type": "text",
14 "primaryKey": true,
15 "notNull": true
16 },
17 "workspace_id": {
18 "name": "workspace_id",
19 "type": "text",
20 "primaryKey": false,
21 "notNull": true
22 },
23 "task_run_id": {
24 "name": "task_run_id",
25 "type": "text",
26 "primaryKey": false,
27 "notNull": true
28 },
29 "call_id": {
30 "name": "call_id",
31 "type": "text",
32 "primaryKey": false,
33 "notNull": true
34 },
35 "tool_path": {
36 "name": "tool_path",
37 "type": "text",
38 "primaryKey": false,
39 "notNull": true
40 },
41 "status": {
42 "name": "status",
43 "type": "text",
44 "primaryKey": false,
45 "notNull": true
46 },
47 "input_preview_json": {
48 "name": "input_preview_json",
49 "type": "text",
50 "primaryKey": false,
51 "notNull": true
52 },
53 "reason": {
54 "name": "reason",
55 "type": "text",
56 "primaryKey": false,
57 "notNull": false
58 },
59 "requested_at": {
60 "name": "requested_at",
61 "type": "bigint",
62 "primaryKey": false,
63 "notNull": true
64 },
65 "resolved_at": {
66 "name": "resolved_at",
67 "type": "bigint",
68 "primaryKey": false,
69 "notNull": false
70 }
71 },
72 "indexes": {
73 "approvals_workspace_idx": {
74 "name": "approvals_workspace_idx",
75 "columns": [
76 {
77 "expression": "workspace_id",
78 "isExpression": false,
79 "asc": true,
80 "nulls": "last"
81 }
82 ],
83 "isUnique": false,
84 "concurrently": false,
85 "method": "btree",
86 "with": {}
87 },
88 "approvals_task_run_idx": {
89 "name": "approvals_task_run_idx",
90 "columns": [
91 {
92 "expression": "task_run_id",
93 "isExpression": false,
94 "asc": true,
95 "nulls": "last"
96 }
97 ],
98 "isUnique": false,
99 "concurrently": false,
100 "method": "btree",
101 "with": {}
102 }
103 },
104 "foreignKeys": {},
105 "compositePrimaryKeys": {},
106 "uniqueConstraints": {},
107 "policies": {},
108 "checkConstraints": {},
109 "isRLSEnabled": false
110 },
111 "public.auth_connections": {
112 "name": "auth_connections",
113 "schema": "",
114 "columns": {
115 "id": {
116 "name": "id",
117 "type": "text",
118 "primaryKey": true,
119 "notNull": true
120 },
121 "organization_id": {
122 "name": "organization_id",
123 "type": "text",
124 "primaryKey": false,
125 "notNull": true
126 },
127 "workspace_id": {
128 "name": "workspace_id",
129 "type": "text",
130 "primaryKey": false,
131 "notNull": false
132 },
133 "account_id": {
134 "name": "account_id",
135 "type": "text",
136 "primaryKey": false,
137 "notNull": false
138 },
139 "owner_type": {
140 "name": "owner_type",
141 "type": "text",
142 "primaryKey": false,
143 "notNull": true
144 },
145 "strategy": {
146 "name": "strategy",
147 "type": "text",
148 "primaryKey": false,
149 "notNull": true
150 },
151 "display_name": {
152 "name": "display_name",
153 "type": "text",
154 "primaryKey": false,
155 "notNull": true
156 },
157 "status": {
158 "name": "status",
159 "type": "text",
160 "primaryKey": false,
161 "notNull": true
162 },
163 "status_reason": {
164 "name": "status_reason",
165 "type": "text",
166 "primaryKey": false,
167 "notNull": false
168 },
169 "last_auth_error_class": {
170 "name": "last_auth_error_class",
171 "type": "text",
172 "primaryKey": false,
173 "notNull": false
174 },
175 "metadata_json": {
176 "name": "metadata_json",
177 "type": "text",
178 "primaryKey": false,
179 "notNull": false
180 },
181 "additional_headers_json": {
182 "name": "additional_headers_json",
183 "type": "text",
184 "primaryKey": false,
185 "notNull": false
186 },
187 "created_by_account_id": {
188 "name": "created_by_account_id",
189 "type": "text",
190 "primaryKey": false,
191 "notNull": false
192 },
193 "created_at": {
194 "name": "created_at",
195 "type": "bigint",
196 "primaryKey": false,
197 "notNull": true
198 },
199 "updated_at": {
200 "name": "updated_at",
201 "type": "bigint",
202 "primaryKey": false,
203 "notNull": true
204 },
205 "last_used_at": {
206 "name": "last_used_at",
207 "type": "bigint",
208 "primaryKey": false,
209 "notNull": false
210 }
211 },
212 "indexes": {
213 "auth_connections_org_idx": {
214 "name": "auth_connections_org_idx",
215 "columns": [
216 {
217 "expression": "organization_id",
218 "isExpression": false,
219 "asc": true,
220 "nulls": "last"
221 }
222 ],
223 "isUnique": false,
224 "concurrently": false,
225 "method": "btree",
226 "with": {}
227 },
228 "auth_connections_workspace_idx": {
229 "name": "auth_connections_workspace_idx",
230 "columns": [
231 {
232 "expression": "workspace_id",
233 "isExpression": false,
234 "asc": true,
235 "nulls": "last"
236 }
237 ],
238 "isUnique": false,
239 "concurrently": false,
240 "method": "btree",
241 "with": {}
242 },
243 "auth_connections_account_idx": {
244 "name": "auth_connections_account_idx",
245 "columns": [
246 {
247 "expression": "account_id",
248 "isExpression": false,
249 "asc": true,
250 "nulls": "last"
251 }
252 ],
253 "isUnique": false,
254 "concurrently": false,
255 "method": "btree",
256 "with": {}
257 }
258 },
259 "foreignKeys": {},
260 "compositePrimaryKeys": {},
261 "uniqueConstraints": {},
262 "policies": {},
263 "checkConstraints": {},
264 "isRLSEnabled": false
265 },
266 "public.auth_materials": {
267 "name": "auth_materials",
268 "schema": "",
269 "columns": {
270 "id": {
271 "name": "id",
272 "type": "text",
273 "primaryKey": true,
274 "notNull": true
275 },
276 "connection_id": {
277 "name": "connection_id",
278 "type": "text",
279 "primaryKey": false,
280 "notNull": true
281 },
282 "ciphertext": {
283 "name": "ciphertext",
284 "type": "text",
285 "primaryKey": false,
286 "notNull": true
287 },
288 "key_version": {
289 "name": "key_version",
290 "type": "text",
291 "primaryKey": false,
292 "notNull": true
293 },
294 "created_at": {
295 "name": "created_at",
296 "type": "bigint",
297 "primaryKey": false,
298 "notNull": true
299 },
300 "updated_at": {
301 "name": "updated_at",
302 "type": "bigint",
303 "primaryKey": false,
304 "notNull": true
305 }
306 },
307 "indexes": {
308 "auth_materials_connection_idx": {
309 "name": "auth_materials_connection_idx",
310 "columns": [
311 {
312 "expression": "connection_id",
313 "isExpression": false,
314 "asc": true,
315 "nulls": "last"
316 }
317 ],
318 "isUnique": false,
319 "concurrently": false,
320 "method": "btree",
321 "with": {}
322 }
323 },
324 "foreignKeys": {},
325 "compositePrimaryKeys": {},
326 "uniqueConstraints": {},
327 "policies": {},
328 "checkConstraints": {},
329 "isRLSEnabled": false
330 },
331 "public.oauth_states": {
332 "name": "oauth_states",
333 "schema": "",
334 "columns": {
335 "id": {
336 "name": "id",
337 "type": "text",
338 "primaryKey": true,
339 "notNull": true
340 },
341 "connection_id": {
342 "name": "connection_id",
343 "type": "text",
344 "primaryKey": false,
345 "notNull": true
346 },
347 "access_token_ciphertext": {
348 "name": "access_token_ciphertext",
349 "type": "text",
350 "primaryKey": false,
351 "notNull": true
352 },
353 "refresh_token_ciphertext": {
354 "name": "refresh_token_ciphertext",
355 "type": "text",
356 "primaryKey": false,
357 "notNull": false
358 },
359 "key_version": {
360 "name": "key_version",
361 "type": "text",
362 "primaryKey": false,
363 "notNull": true
364 },
365 "expires_at": {
366 "name": "expires_at",
367 "type": "bigint",
368 "primaryKey": false,
369 "notNull": false
370 },
371 "scope": {
372 "name": "scope",
373 "type": "text",
374 "primaryKey": false,
375 "notNull": false
376 },
377 "token_type": {
378 "name": "token_type",
379 "type": "text",
380 "primaryKey": false,
381 "notNull": false
382 },
383 "issuer": {
384 "name": "issuer",
385 "type": "text",
386 "primaryKey": false,
387 "notNull": false
388 },
389 "refresh_config_json": {
390 "name": "refresh_config_json",
391 "type": "text",
392 "primaryKey": false,
393 "notNull": false
394 },
395 "token_version": {
396 "name": "token_version",
397 "type": "bigint",
398 "primaryKey": false,
399 "notNull": true
400 },
401 "lease_holder": {
402 "name": "lease_holder",
403 "type": "text",
404 "primaryKey": false,
405 "notNull": false
406 },
407 "lease_expires_at": {
408 "name": "lease_expires_at",
409 "type": "bigint",
410 "primaryKey": false,
411 "notNull": false
412 },
413 "lease_fence": {
414 "name": "lease_fence",
415 "type": "bigint",
416 "primaryKey": false,
417 "notNull": true
418 },
419 "last_refresh_at": {
420 "name": "last_refresh_at",
421 "type": "bigint",
422 "primaryKey": false,
423 "notNull": false
424 },
425 "last_refresh_error_class": {
426 "name": "last_refresh_error_class",
427 "type": "text",
428 "primaryKey": false,
429 "notNull": false
430 },
431 "last_refresh_error": {
432 "name": "last_refresh_error",
433 "type": "text",
434 "primaryKey": false,
435 "notNull": false
436 },
437 "reauth_required_at": {
438 "name": "reauth_required_at",
439 "type": "bigint",
440 "primaryKey": false,
441 "notNull": false
442 },
443 "created_at": {
444 "name": "created_at",
445 "type": "bigint",
446 "primaryKey": false,
447 "notNull": true
448 },
449 "updated_at": {
450 "name": "updated_at",
451 "type": "bigint",
452 "primaryKey": false,
453 "notNull": true
454 }
455 },
456 "indexes": {
457 "oauth_states_connection_idx": {
458 "name": "oauth_states_connection_idx",
459 "columns": [
460 {
461 "expression": "connection_id",
462 "isExpression": false,
463 "asc": true,
464 "nulls": "last"
465 }
466 ],
467 "isUnique": false,
468 "concurrently": false,
469 "method": "btree",
470 "with": {}
471 }
472 },
473 "foreignKeys": {},
474 "compositePrimaryKeys": {},
475 "uniqueConstraints": {},
476 "policies": {},
477 "checkConstraints": {},
478 "isRLSEnabled": false
479 },
480 "public.organization_memberships": {
481 "name": "organization_memberships",
482 "schema": "",
483 "columns": {
484 "id": {
485 "name": "id",
486 "type": "text",
487 "primaryKey": true,
488 "notNull": true
489 },
490 "organization_id": {
491 "name": "organization_id",
492 "type": "text",
493 "primaryKey": false,
494 "notNull": true
495 },
496 "account_id": {
497 "name": "account_id",
498 "type": "text",
499 "primaryKey": false,
500 "notNull": true
501 },
502 "role": {
503 "name": "role",
504 "type": "text",
505 "primaryKey": false,
506 "notNull": true
507 },
508 "status": {
509 "name": "status",
510 "type": "text",
511 "primaryKey": false,
512 "notNull": true
513 },
514 "billable": {
515 "name": "billable",
516 "type": "boolean",
517 "primaryKey": false,
518 "notNull": true
519 },
520 "invited_by_account_id": {
521 "name": "invited_by_account_id",
522 "type": "text",
523 "primaryKey": false,
524 "notNull": false
525 },
526 "joined_at": {
527 "name": "joined_at",
528 "type": "bigint",
529 "primaryKey": false,
530 "notNull": false
531 },
532 "created_at": {
533 "name": "created_at",
534 "type": "bigint",
535 "primaryKey": false,
536 "notNull": true
537 },
538 "updated_at": {
539 "name": "updated_at",
540 "type": "bigint",
541 "primaryKey": false,
542 "notNull": true
543 }
544 },
545 "indexes": {
546 "organization_memberships_org_idx": {
547 "name": "organization_memberships_org_idx",
548 "columns": [
549 {
550 "expression": "organization_id",
551 "isExpression": false,
552 "asc": true,
553 "nulls": "last"
554 }
555 ],
556 "isUnique": false,
557 "concurrently": false,
558 "method": "btree",
559 "with": {}
560 },
561 "organization_memberships_account_idx": {
562 "name": "organization_memberships_account_idx",
563 "columns": [
564 {
565 "expression": "account_id",
566 "isExpression": false,
567 "asc": true,
568 "nulls": "last"
569 }
570 ],
571 "isUnique": false,
572 "concurrently": false,
573 "method": "btree",
574 "with": {}
575 }
576 },
577 "foreignKeys": {},
578 "compositePrimaryKeys": {},
579 "uniqueConstraints": {},
580 "policies": {},
581 "checkConstraints": {},
582 "isRLSEnabled": false
583 },
584 "public.organizations": {
585 "name": "organizations",
586 "schema": "",
587 "columns": {
588 "id": {
589 "name": "id",
590 "type": "text",
591 "primaryKey": true,
592 "notNull": true
593 },
594 "slug": {
595 "name": "slug",
596 "type": "text",
597 "primaryKey": false,
598 "notNull": true
599 },
600 "name": {
601 "name": "name",
602 "type": "text",
603 "primaryKey": false,
604 "notNull": true
605 },
606 "status": {
607 "name": "status",
608 "type": "text",
609 "primaryKey": false,
610 "notNull": true
611 },
612 "created_by_account_id": {
613 "name": "created_by_account_id",
614 "type": "text",
615 "primaryKey": false,
616 "notNull": false
617 },
618 "created_at": {
619 "name": "created_at",
620 "type": "bigint",
621 "primaryKey": false,
622 "notNull": true
623 },
624 "updated_at": {
625 "name": "updated_at",
626 "type": "bigint",
627 "primaryKey": false,
628 "notNull": true
629 }
630 },
631 "indexes": {},
632 "foreignKeys": {},
633 "compositePrimaryKeys": {},
634 "uniqueConstraints": {},
635 "policies": {},
636 "checkConstraints": {},
637 "isRLSEnabled": false
638 },
639 "public.policies": {
640 "name": "policies",
641 "schema": "",
642 "columns": {
643 "id": {
644 "name": "id",
645 "type": "text",
646 "primaryKey": true,
647 "notNull": true
648 },
649 "workspace_id": {
650 "name": "workspace_id",
651 "type": "text",
652 "primaryKey": false,
653 "notNull": true
654 },
655 "tool_path_pattern": {
656 "name": "tool_path_pattern",
657 "type": "text",
658 "primaryKey": false,
659 "notNull": true
660 },
661 "decision": {
662 "name": "decision",
663 "type": "text",
664 "primaryKey": false,
665 "notNull": true
666 },
667 "created_at": {
668 "name": "created_at",
669 "type": "bigint",
670 "primaryKey": false,
671 "notNull": true
672 },
673 "updated_at": {
674 "name": "updated_at",
675 "type": "bigint",
676 "primaryKey": false,
677 "notNull": true
678 }
679 },
680 "indexes": {
681 "policies_workspace_idx": {
682 "name": "policies_workspace_idx",
683 "columns": [
684 {
685 "expression": "workspace_id",
686 "isExpression": false,
687 "asc": true,
688 "nulls": "last"
689 }
690 ],
691 "isUnique": false,
692 "concurrently": false,
693 "method": "btree",
694 "with": {}
695 }
696 },
697 "foreignKeys": {},
698 "compositePrimaryKeys": {},
699 "uniqueConstraints": {},
700 "policies": {},
701 "checkConstraints": {},
702 "isRLSEnabled": false
703 },
704 "public.profile": {
705 "name": "profile",
706 "schema": "",
707 "columns": {
708 "id": {
709 "name": "id",
710 "type": "text",
711 "primaryKey": true,
712 "notNull": true
713 },
714 "default_workspace_id": {
715 "name": "default_workspace_id",
716 "type": "text",
717 "primaryKey": false,
718 "notNull": false
719 },
720 "display_name": {
721 "name": "display_name",
722 "type": "text",
723 "primaryKey": false,
724 "notNull": true
725 },
726 "runtime_mode": {
727 "name": "runtime_mode",
728 "type": "text",
729 "primaryKey": false,
730 "notNull": true
731 },
732 "created_at": {
733 "name": "created_at",
734 "type": "bigint",
735 "primaryKey": false,
736 "notNull": true
737 },
738 "updated_at": {
739 "name": "updated_at",
740 "type": "bigint",
741 "primaryKey": false,
742 "notNull": true
743 }
744 },
745 "indexes": {},
746 "foreignKeys": {},
747 "compositePrimaryKeys": {},
748 "uniqueConstraints": {},
749 "policies": {},
750 "checkConstraints": {},
751 "isRLSEnabled": false
752 },
753 "public.source_auth_bindings": {
754 "name": "source_auth_bindings",
755 "schema": "",
756 "columns": {
757 "id": {
758 "name": "id",
759 "type": "text",
760 "primaryKey": true,
761 "notNull": true
762 },
763 "source_id": {
764 "name": "source_id",
765 "type": "text",
766 "primaryKey": false,
767 "notNull": true
768 },
769 "connection_id": {
770 "name": "connection_id",
771 "type": "text",
772 "primaryKey": false,
773 "notNull": true
774 },
775 "organization_id": {
776 "name": "organization_id",
777 "type": "text",
778 "primaryKey": false,
779 "notNull": true
780 },
781 "workspace_id": {
782 "name": "workspace_id",
783 "type": "text",
784 "primaryKey": false,
785 "notNull": false
786 },
787 "account_id": {
788 "name": "account_id",
789 "type": "text",
790 "primaryKey": false,
791 "notNull": false
792 },
793 "scope_type": {
794 "name": "scope_type",
795 "type": "text",
796 "primaryKey": false,
797 "notNull": true
798 },
799 "selector": {
800 "name": "selector",
801 "type": "text",
802 "primaryKey": false,
803 "notNull": false
804 },
805 "enabled": {
806 "name": "enabled",
807 "type": "boolean",
808 "primaryKey": false,
809 "notNull": true
810 },
811 "created_at": {
812 "name": "created_at",
813 "type": "bigint",
814 "primaryKey": false,
815 "notNull": true
816 },
817 "updated_at": {
818 "name": "updated_at",
819 "type": "bigint",
820 "primaryKey": false,
821 "notNull": true
822 }
823 },
824 "indexes": {
825 "source_auth_bindings_source_idx": {
826 "name": "source_auth_bindings_source_idx",
827 "columns": [
828 {
829 "expression": "source_id",
830 "isExpression": false,
831 "asc": true,
832 "nulls": "last"
833 }
834 ],
835 "isUnique": false,
836 "concurrently": false,
837 "method": "btree",
838 "with": {}
839 },
840 "source_auth_bindings_connection_idx": {
841 "name": "source_auth_bindings_connection_idx",
842 "columns": [
843 {
844 "expression": "connection_id",
845 "isExpression": false,
846 "asc": true,
847 "nulls": "last"
848 }
849 ],
850 "isUnique": false,
851 "concurrently": false,
852 "method": "btree",
853 "with": {}
854 },
855 "source_auth_bindings_org_idx": {
856 "name": "source_auth_bindings_org_idx",
857 "columns": [
858 {
859 "expression": "organization_id",
860 "isExpression": false,
861 "asc": true,
862 "nulls": "last"
863 }
864 ],
865 "isUnique": false,
866 "concurrently": false,
867 "method": "btree",
868 "with": {}
869 },
870 "source_auth_bindings_workspace_idx": {
871 "name": "source_auth_bindings_workspace_idx",
872 "columns": [
873 {
874 "expression": "workspace_id",
875 "isExpression": false,
876 "asc": true,
877 "nulls": "last"
878 }
879 ],
880 "isUnique": false,
881 "concurrently": false,
882 "method": "btree",
883 "with": {}
884 },
885 "source_auth_bindings_account_idx": {
886 "name": "source_auth_bindings_account_idx",
887 "columns": [
888 {
889 "expression": "account_id",
890 "isExpression": false,
891 "asc": true,
892 "nulls": "last"
893 }
894 ],
895 "isUnique": false,
896 "concurrently": false,
897 "method": "btree",
898 "with": {}
899 }
900 },
901 "foreignKeys": {},
902 "compositePrimaryKeys": {},
903 "uniqueConstraints": {},
904 "policies": {},
905 "checkConstraints": {},
906 "isRLSEnabled": false
907 },
908 "public.sources": {
909 "name": "sources",
910 "schema": "",
911 "columns": {
912 "workspace_id": {
913 "name": "workspace_id",
914 "type": "text",
915 "primaryKey": false,
916 "notNull": true
917 },
918 "source_id": {
919 "name": "source_id",
920 "type": "text",
921 "primaryKey": false,
922 "notNull": true
923 },
924 "name": {
925 "name": "name",
926 "type": "text",
927 "primaryKey": false,
928 "notNull": true
929 },
930 "kind": {
931 "name": "kind",
932 "type": "text",
933 "primaryKey": false,
934 "notNull": true
935 },
936 "endpoint": {
937 "name": "endpoint",
938 "type": "text",
939 "primaryKey": false,
940 "notNull": true
941 },
942 "status": {
943 "name": "status",
944 "type": "text",
945 "primaryKey": false,
946 "notNull": true
947 },
948 "enabled": {
949 "name": "enabled",
950 "type": "boolean",
951 "primaryKey": false,
952 "notNull": true
953 },
954 "config_json": {
955 "name": "config_json",
956 "type": "text",
957 "primaryKey": false,
958 "notNull": true
959 },
960 "source_hash": {
961 "name": "source_hash",
962 "type": "text",
963 "primaryKey": false,
964 "notNull": false
965 },
966 "last_error": {
967 "name": "last_error",
968 "type": "text",
969 "primaryKey": false,
970 "notNull": false
971 },
972 "created_at": {
973 "name": "created_at",
974 "type": "bigint",
975 "primaryKey": false,
976 "notNull": true
977 },
978 "updated_at": {
979 "name": "updated_at",
980 "type": "bigint",
981 "primaryKey": false,
982 "notNull": true
983 }
984 },
985 "indexes": {
986 "sources_workspace_name_idx": {
987 "name": "sources_workspace_name_idx",
988 "columns": [
989 {
990 "expression": "workspace_id",
991 "isExpression": false,
992 "asc": true,
993 "nulls": "last"
994 },
995 {
996 "expression": "name",
997 "isExpression": false,
998 "asc": true,
999 "nulls": "last"
1000 }
1001 ],
1002 "isUnique": false,
1003 "concurrently": false,
1004 "method": "btree",
1005 "with": {}
1006 }
1007 },
1008 "foreignKeys": {},
1009 "compositePrimaryKeys": {
1010 "sources_workspace_id_source_id_pk": {
1011 "name": "sources_workspace_id_source_id_pk",
1012 "columns": [
1013 "workspace_id",
1014 "source_id"
1015 ]
1016 }
1017 },
1018 "uniqueConstraints": {},
1019 "policies": {},
1020 "checkConstraints": {},
1021 "isRLSEnabled": false
1022 },
1023 "public.storage_instances": {
1024 "name": "storage_instances",
1025 "schema": "",
1026 "columns": {
1027 "id": {
1028 "name": "id",
1029 "type": "text",
1030 "primaryKey": true,
1031 "notNull": true
1032 },
1033 "scope_type": {
1034 "name": "scope_type",
1035 "type": "text",
1036 "primaryKey": false,
1037 "notNull": true
1038 },
1039 "durability": {
1040 "name": "durability",
1041 "type": "text",
1042 "primaryKey": false,
1043 "notNull": true
1044 },
1045 "status": {
1046 "name": "status",
1047 "type": "text",
1048 "primaryKey": false,
1049 "notNull": true
1050 },
1051 "provider": {
1052 "name": "provider",
1053 "type": "text",
1054 "primaryKey": false,
1055 "notNull": true
1056 },
1057 "backend_key": {
1058 "name": "backend_key",
1059 "type": "text",
1060 "primaryKey": false,
1061 "notNull": true
1062 },
1063 "organization_id": {
1064 "name": "organization_id",
1065 "type": "text",
1066 "primaryKey": false,
1067 "notNull": true
1068 },
1069 "workspace_id": {
1070 "name": "workspace_id",
1071 "type": "text",
1072 "primaryKey": false,
1073 "notNull": false
1074 },
1075 "account_id": {
1076 "name": "account_id",
1077 "type": "text",
1078 "primaryKey": false,
1079 "notNull": false
1080 },
1081 "created_by_account_id": {
1082 "name": "created_by_account_id",
1083 "type": "text",
1084 "primaryKey": false,
1085 "notNull": false
1086 },
1087 "purpose": {
1088 "name": "purpose",
1089 "type": "text",
1090 "primaryKey": false,
1091 "notNull": false
1092 },
1093 "size_bytes": {
1094 "name": "size_bytes",
1095 "type": "bigint",
1096 "primaryKey": false,
1097 "notNull": false
1098 },
1099 "file_count": {
1100 "name": "file_count",
1101 "type": "bigint",
1102 "primaryKey": false,
1103 "notNull": false
1104 },
1105 "created_at": {
1106 "name": "created_at",
1107 "type": "bigint",
1108 "primaryKey": false,
1109 "notNull": true
1110 },
1111 "updated_at": {
1112 "name": "updated_at",
1113 "type": "bigint",
1114 "primaryKey": false,
1115 "notNull": true
1116 },
1117 "last_seen_at": {
1118 "name": "last_seen_at",
1119 "type": "bigint",
1120 "primaryKey": false,
1121 "notNull": true
1122 },
1123 "closed_at": {
1124 "name": "closed_at",
1125 "type": "bigint",
1126 "primaryKey": false,
1127 "notNull": false
1128 },
1129 "expires_at": {
1130 "name": "expires_at",
1131 "type": "bigint",
1132 "primaryKey": false,
1133 "notNull": false
1134 }
1135 },
1136 "indexes": {
1137 "storage_instances_org_idx": {
1138 "name": "storage_instances_org_idx",
1139 "columns": [
1140 {
1141 "expression": "organization_id",
1142 "isExpression": false,
1143 "asc": true,
1144 "nulls": "last"
1145 }
1146 ],
1147 "isUnique": false,
1148 "concurrently": false,
1149 "method": "btree",
1150 "with": {}
1151 },
1152 "storage_instances_workspace_idx": {
1153 "name": "storage_instances_workspace_idx",
1154 "columns": [
1155 {
1156 "expression": "workspace_id",
1157 "isExpression": false,
1158 "asc": true,
1159 "nulls": "last"
1160 }
1161 ],
1162 "isUnique": false,
1163 "concurrently": false,
1164 "method": "btree",
1165 "with": {}
1166 }
1167 },
1168 "foreignKeys": {},
1169 "compositePrimaryKeys": {},
1170 "uniqueConstraints": {},
1171 "policies": {},
1172 "checkConstraints": {},
1173 "isRLSEnabled": false
1174 },
1175 "public.sync_states": {
1176 "name": "sync_states",
1177 "schema": "",
1178 "columns": {
1179 "id": {
1180 "name": "id",
1181 "type": "text",
1182 "primaryKey": true,
1183 "notNull": true
1184 },
1185 "workspace_id": {
1186 "name": "workspace_id",
1187 "type": "text",
1188 "primaryKey": false,
1189 "notNull": true
1190 },
1191 "target": {
1192 "name": "target",
1193 "type": "text",
1194 "primaryKey": false,
1195 "notNull": true
1196 },
1197 "target_url": {
1198 "name": "target_url",
1199 "type": "text",
1200 "primaryKey": false,
1201 "notNull": true
1202 },
1203 "linked_subject": {
1204 "name": "linked_subject",
1205 "type": "text",
1206 "primaryKey": false,
1207 "notNull": false
1208 },
1209 "cursor": {
1210 "name": "cursor",
1211 "type": "text",
1212 "primaryKey": false,
1213 "notNull": false
1214 },
1215 "last_sync_at": {
1216 "name": "last_sync_at",
1217 "type": "bigint",
1218 "primaryKey": false,
1219 "notNull": false
1220 },
1221 "updated_at": {
1222 "name": "updated_at",
1223 "type": "bigint",
1224 "primaryKey": false,
1225 "notNull": true
1226 }
1227 },
1228 "indexes": {
1229 "sync_states_workspace_idx": {
1230 "name": "sync_states_workspace_idx",
1231 "columns": [
1232 {
1233 "expression": "workspace_id",
1234 "isExpression": false,
1235 "asc": true,
1236 "nulls": "last"
1237 }
1238 ],
1239 "isUnique": false,
1240 "concurrently": false,
1241 "method": "btree",
1242 "with": {}
1243 }
1244 },
1245 "foreignKeys": {},
1246 "compositePrimaryKeys": {},
1247 "uniqueConstraints": {},
1248 "policies": {},
1249 "checkConstraints": {},
1250 "isRLSEnabled": false
1251 },
1252 "public.task_runs": {
1253 "name": "task_runs",
1254 "schema": "",
1255 "columns": {
1256 "id": {
1257 "name": "id",
1258 "type": "text",
1259 "primaryKey": true,
1260 "notNull": true
1261 },
1262 "workspace_id": {
1263 "name": "workspace_id",
1264 "type": "text",
1265 "primaryKey": false,
1266 "notNull": true
1267 },
1268 "account_id": {
1269 "name": "account_id",
1270 "type": "text",
1271 "primaryKey": false,
1272 "notNull": true
1273 },
1274 "session_id": {
1275 "name": "session_id",
1276 "type": "text",
1277 "primaryKey": false,
1278 "notNull": true
1279 },
1280 "runtime_id": {
1281 "name": "runtime_id",
1282 "type": "text",
1283 "primaryKey": false,
1284 "notNull": true
1285 },
1286 "code_hash": {
1287 "name": "code_hash",
1288 "type": "text",
1289 "primaryKey": false,
1290 "notNull": true
1291 },
1292 "status": {
1293 "name": "status",
1294 "type": "text",
1295 "primaryKey": false,
1296 "notNull": true
1297 },
1298 "started_at": {
1299 "name": "started_at",
1300 "type": "bigint",
1301 "primaryKey": false,
1302 "notNull": false
1303 },
1304 "completed_at": {
1305 "name": "completed_at",
1306 "type": "bigint",
1307 "primaryKey": false,
1308 "notNull": false
1309 },
1310 "exit_code": {
1311 "name": "exit_code",
1312 "type": "bigint",
1313 "primaryKey": false,
1314 "notNull": false
1315 },
1316 "error": {
1317 "name": "error",
1318 "type": "text",
1319 "primaryKey": false,
1320 "notNull": false
1321 }
1322 },
1323 "indexes": {
1324 "task_runs_workspace_idx": {
1325 "name": "task_runs_workspace_idx",
1326 "columns": [
1327 {
1328 "expression": "workspace_id",
1329 "isExpression": false,
1330 "asc": true,
1331 "nulls": "last"
1332 }
1333 ],
1334 "isUnique": false,
1335 "concurrently": false,
1336 "method": "btree",
1337 "with": {}
1338 }
1339 },
1340 "foreignKeys": {},
1341 "compositePrimaryKeys": {},
1342 "uniqueConstraints": {},
1343 "policies": {},
1344 "checkConstraints": {},
1345 "isRLSEnabled": false
1346 },
1347 "public.tool_artifacts": {
1348 "name": "tool_artifacts",
1349 "schema": "",
1350 "columns": {
1351 "id": {
1352 "name": "id",
1353 "type": "text",
1354 "primaryKey": false,
1355 "notNull": true
1356 },
1357 "workspace_id": {
1358 "name": "workspace_id",
1359 "type": "text",
1360 "primaryKey": false,
1361 "notNull": true
1362 },
1363 "source_id": {
1364 "name": "source_id",
1365 "type": "text",
1366 "primaryKey": false,
1367 "notNull": true
1368 },
1369 "source_hash": {
1370 "name": "source_hash",
1371 "type": "text",
1372 "primaryKey": false,
1373 "notNull": true
1374 },
1375 "tool_count": {
1376 "name": "tool_count",
1377 "type": "bigint",
1378 "primaryKey": false,
1379 "notNull": true
1380 },
1381 "manifest_json": {
1382 "name": "manifest_json",
1383 "type": "text",
1384 "primaryKey": false,
1385 "notNull": true
1386 },
1387 "created_at": {
1388 "name": "created_at",
1389 "type": "bigint",
1390 "primaryKey": false,
1391 "notNull": true
1392 },
1393 "updated_at": {
1394 "name": "updated_at",
1395 "type": "bigint",
1396 "primaryKey": false,
1397 "notNull": true
1398 }
1399 },
1400 "indexes": {
1401 "tool_artifacts_id_idx": {
1402 "name": "tool_artifacts_id_idx",
1403 "columns": [
1404 {
1405 "expression": "id",
1406 "isExpression": false,
1407 "asc": true,
1408 "nulls": "last"
1409 }
1410 ],
1411 "isUnique": true,
1412 "concurrently": false,
1413 "method": "btree",
1414 "with": {}
1415 }
1416 },
1417 "foreignKeys": {},
1418 "compositePrimaryKeys": {
1419 "tool_artifacts_workspace_id_source_id_pk": {
1420 "name": "tool_artifacts_workspace_id_source_id_pk",
1421 "columns": [
1422 "workspace_id",
1423 "source_id"
1424 ]
1425 }
1426 },
1427 "uniqueConstraints": {},
1428 "policies": {},
1429 "checkConstraints": {},
1430 "isRLSEnabled": false
1431 },
1432 "public.workspaces": {
1433 "name": "workspaces",
1434 "schema": "",
1435 "columns": {
1436 "id": {
1437 "name": "id",
1438 "type": "text",
1439 "primaryKey": true,
1440 "notNull": true
1441 },
1442 "organization_id": {
1443 "name": "organization_id",
1444 "type": "text",
1445 "primaryKey": false,
1446 "notNull": true
1447 },
1448 "name": {
1449 "name": "name",
1450 "type": "text",
1451 "primaryKey": false,
1452 "notNull": true
1453 },
1454 "created_by_account_id": {
1455 "name": "created_by_account_id",
1456 "type": "text",
1457 "primaryKey": false,
1458 "notNull": false
1459 },
1460 "created_at": {
1461 "name": "created_at",
1462 "type": "bigint",
1463 "primaryKey": false,
1464 "notNull": true
1465 },
1466 "updated_at": {
1467 "name": "updated_at",
1468 "type": "bigint",
1469 "primaryKey": false,
1470 "notNull": true
1471 }
1472 },
1473 "indexes": {
1474 "workspaces_org_idx": {
1475 "name": "workspaces_org_idx",
1476 "columns": [
1477 {
1478 "expression": "organization_id",
1479 "isExpression": false,
1480 "asc": true,
1481 "nulls": "last"
1482 }
1483 ],
1484 "isUnique": false,
1485 "concurrently": false,
1486 "method": "btree",
1487 "with": {}
1488 }
1489 },
1490 "foreignKeys": {},
1491 "compositePrimaryKeys": {},
1492 "uniqueConstraints": {},
1493 "policies": {},
1494 "checkConstraints": {},
1495 "isRLSEnabled": false
1496 }
1497 },
1498 "enums": {},
1499 "schemas": {},
1500 "sequences": {},
1501 "roles": {},
1502 "policies": {},
1503 "views": {},
1504 "_meta": {
1505 "columns": {},
1506 "schemas": {},
1507 "tables": {}
1508 }
1509}
packages/persistence-sql/drizzle/postgres/meta/_journal.json+13−0
@@ -0,0 +1,13 @@
1{
2 "version": "7",
3 "dialect": "postgresql",
4 "entries": [
5 {
6 "idx": 0,
7 "version": "7",
8 "when": 1772506152805,
9 "tag": "0000_spicy_barracuda",
10 "breakpoints": true
11 }
12 ]
13}
packages/persistence-sql/drizzle/sqlite/0000_curved_raider.sql+224−0
@@ -0,0 +1,224 @@
1CREATE TABLE `approvals` (
2 `id` text PRIMARY KEY NOT NULL,
3 `workspace_id` text NOT NULL,
4 `task_run_id` text NOT NULL,
5 `call_id` text NOT NULL,
6 `tool_path` text NOT NULL,
7 `status` text NOT NULL,
8 `input_preview_json` text NOT NULL,
9 `reason` text,
10 `requested_at` integer NOT NULL,
11 `resolved_at` integer
12);
13--> statement-breakpoint
14CREATE INDEX `approvals_workspace_idx` ON `approvals` (`workspace_id`);--> statement-breakpoint
15CREATE INDEX `approvals_task_run_idx` ON `approvals` (`task_run_id`);--> statement-breakpoint
16CREATE TABLE `auth_connections` (
17 `id` text PRIMARY KEY NOT NULL,
18 `organization_id` text NOT NULL,
19 `workspace_id` text,
20 `account_id` text,
21 `owner_type` text NOT NULL,
22 `strategy` text NOT NULL,
23 `display_name` text NOT NULL,
24 `status` text NOT NULL,
25 `status_reason` text,
26 `last_auth_error_class` text,
27 `metadata_json` text,
28 `additional_headers_json` text,
29 `created_by_account_id` text,
30 `created_at` integer NOT NULL,
31 `updated_at` integer NOT NULL,
32 `last_used_at` integer
33);
34--> statement-breakpoint
35CREATE INDEX `auth_connections_org_idx` ON `auth_connections` (`organization_id`);--> statement-breakpoint
36CREATE INDEX `auth_connections_workspace_idx` ON `auth_connections` (`workspace_id`);--> statement-breakpoint
37CREATE INDEX `auth_connections_account_idx` ON `auth_connections` (`account_id`);--> statement-breakpoint
38CREATE TABLE `auth_materials` (
39 `id` text PRIMARY KEY NOT NULL,
40 `connection_id` text NOT NULL,
41 `ciphertext` text NOT NULL,
42 `key_version` text NOT NULL,
43 `created_at` integer NOT NULL,
44 `updated_at` integer NOT NULL
45);
46--> statement-breakpoint
47CREATE INDEX `auth_materials_connection_idx` ON `auth_materials` (`connection_id`);--> statement-breakpoint
48CREATE TABLE `oauth_states` (
49 `id` text PRIMARY KEY NOT NULL,
50 `connection_id` text NOT NULL,
51 `access_token_ciphertext` text NOT NULL,
52 `refresh_token_ciphertext` text,
53 `key_version` text NOT NULL,
54 `expires_at` integer,
55 `scope` text,
56 `token_type` text,
57 `issuer` text,
58 `refresh_config_json` text,
59 `token_version` integer NOT NULL,
60 `lease_holder` text,
61 `lease_expires_at` integer,
62 `lease_fence` integer NOT NULL,
63 `last_refresh_at` integer,
64 `last_refresh_error_class` text,
65 `last_refresh_error` text,
66 `reauth_required_at` integer,
67 `created_at` integer NOT NULL,
68 `updated_at` integer NOT NULL
69);
70--> statement-breakpoint
71CREATE INDEX `oauth_states_connection_idx` ON `oauth_states` (`connection_id`);--> statement-breakpoint
72CREATE TABLE `organization_memberships` (
73 `id` text PRIMARY KEY NOT NULL,
74 `organization_id` text NOT NULL,
75 `account_id` text NOT NULL,
76 `role` text NOT NULL,
77 `status` text NOT NULL,
78 `billable` integer NOT NULL,
79 `invited_by_account_id` text,
80 `joined_at` integer,
81 `created_at` integer NOT NULL,
82 `updated_at` integer NOT NULL
83);
84--> statement-breakpoint
85CREATE INDEX `organization_memberships_org_idx` ON `organization_memberships` (`organization_id`);--> statement-breakpoint
86CREATE INDEX `organization_memberships_account_idx` ON `organization_memberships` (`account_id`);--> statement-breakpoint
87CREATE TABLE `organizations` (
88 `id` text PRIMARY KEY NOT NULL,
89 `slug` text NOT NULL,
90 `name` text NOT NULL,
91 `status` text NOT NULL,
92 `created_by_account_id` text,
93 `created_at` integer NOT NULL,
94 `updated_at` integer NOT NULL
95);
96--> statement-breakpoint
97CREATE TABLE `policies` (
98 `id` text PRIMARY KEY NOT NULL,
99 `workspace_id` text NOT NULL,
100 `tool_path_pattern` text NOT NULL,
101 `decision` text NOT NULL,
102 `created_at` integer NOT NULL,
103 `updated_at` integer NOT NULL
104);
105--> statement-breakpoint
106CREATE INDEX `policies_workspace_idx` ON `policies` (`workspace_id`);--> statement-breakpoint
107CREATE TABLE `profile` (
108 `id` text PRIMARY KEY NOT NULL,
109 `default_workspace_id` text,
110 `display_name` text NOT NULL,
111 `runtime_mode` text NOT NULL,
112 `created_at` integer NOT NULL,
113 `updated_at` integer NOT NULL
114);
115--> statement-breakpoint
116CREATE TABLE `source_auth_bindings` (
117 `id` text PRIMARY KEY NOT NULL,
118 `source_id` text NOT NULL,
119 `connection_id` text NOT NULL,
120 `organization_id` text NOT NULL,
121 `workspace_id` text,
122 `account_id` text,
123 `scope_type` text NOT NULL,
124 `selector` text,
125 `enabled` integer NOT NULL,
126 `created_at` integer NOT NULL,
127 `updated_at` integer NOT NULL
128);
129--> statement-breakpoint
130CREATE INDEX `source_auth_bindings_source_idx` ON `source_auth_bindings` (`source_id`);--> statement-breakpoint
131CREATE INDEX `source_auth_bindings_connection_idx` ON `source_auth_bindings` (`connection_id`);--> statement-breakpoint
132CREATE INDEX `source_auth_bindings_org_idx` ON `source_auth_bindings` (`organization_id`);--> statement-breakpoint
133CREATE INDEX `source_auth_bindings_workspace_idx` ON `source_auth_bindings` (`workspace_id`);--> statement-breakpoint
134CREATE INDEX `source_auth_bindings_account_idx` ON `source_auth_bindings` (`account_id`);--> statement-breakpoint
135CREATE TABLE `sources` (
136 `workspace_id` text NOT NULL,
137 `source_id` text NOT NULL,
138 `name` text NOT NULL,
139 `kind` text NOT NULL,
140 `endpoint` text NOT NULL,
141 `status` text NOT NULL,
142 `enabled` integer NOT NULL,
143 `config_json` text NOT NULL,
144 `source_hash` text,
145 `last_error` text,
146 `created_at` integer NOT NULL,
147 `updated_at` integer NOT NULL,
148 PRIMARY KEY(`workspace_id`, `source_id`)
149);
150--> statement-breakpoint
151CREATE INDEX `sources_workspace_name_idx` ON `sources` (`workspace_id`,`name`);--> statement-breakpoint
152CREATE TABLE `storage_instances` (
153 `id` text PRIMARY KEY NOT NULL,
154 `scope_type` text NOT NULL,
155 `durability` text NOT NULL,
156 `status` text NOT NULL,
157 `provider` text NOT NULL,
158 `backend_key` text NOT NULL,
159 `organization_id` text NOT NULL,
160 `workspace_id` text,
161 `account_id` text,
162 `created_by_account_id` text,
163 `purpose` text,
164 `size_bytes` integer,
165 `file_count` integer,
166 `created_at` integer NOT NULL,
167 `updated_at` integer NOT NULL,
168 `last_seen_at` integer NOT NULL,
169 `closed_at` integer,
170 `expires_at` integer
171);
172--> statement-breakpoint
173CREATE INDEX `storage_instances_org_idx` ON `storage_instances` (`organization_id`);--> statement-breakpoint
174CREATE INDEX `storage_instances_workspace_idx` ON `storage_instances` (`workspace_id`);--> statement-breakpoint
175CREATE TABLE `sync_states` (
176 `id` text PRIMARY KEY NOT NULL,
177 `workspace_id` text NOT NULL,
178 `target` text NOT NULL,
179 `target_url` text NOT NULL,
180 `linked_subject` text,
181 `cursor` text,
182 `last_sync_at` integer,
183 `updated_at` integer NOT NULL
184);
185--> statement-breakpoint
186CREATE INDEX `sync_states_workspace_idx` ON `sync_states` (`workspace_id`);--> statement-breakpoint
187CREATE TABLE `task_runs` (
188 `id` text PRIMARY KEY NOT NULL,
189 `workspace_id` text NOT NULL,
190 `account_id` text NOT NULL,
191 `session_id` text NOT NULL,
192 `runtime_id` text NOT NULL,
193 `code_hash` text NOT NULL,
194 `status` text NOT NULL,
195 `started_at` integer,
196 `completed_at` integer,
197 `exit_code` integer,
198 `error` text
199);
200--> statement-breakpoint
201CREATE INDEX `task_runs_workspace_idx` ON `task_runs` (`workspace_id`);--> statement-breakpoint
202CREATE TABLE `tool_artifacts` (
203 `id` text NOT NULL,
204 `workspace_id` text NOT NULL,
205 `source_id` text NOT NULL,
206 `source_hash` text NOT NULL,
207 `tool_count` integer NOT NULL,
208 `manifest_json` text NOT NULL,
209 `created_at` integer NOT NULL,
210 `updated_at` integer NOT NULL,
211 PRIMARY KEY(`workspace_id`, `source_id`)
212);
213--> statement-breakpoint
214CREATE UNIQUE INDEX `tool_artifacts_id_idx` ON `tool_artifacts` (`id`);--> statement-breakpoint
215CREATE TABLE `workspaces` (
216 `id` text PRIMARY KEY NOT NULL,
217 `organization_id` text NOT NULL,
218 `name` text NOT NULL,
219 `created_by_account_id` text,
220 `created_at` integer NOT NULL,
221 `updated_at` integer NOT NULL
222);
223--> statement-breakpoint
224CREATE INDEX `workspaces_org_idx` ON `workspaces` (`organization_id`);
packages/persistence-sql/drizzle/sqlite/meta/0000_snapshot.json+1437−0
@@ -0,0 +1,1437 @@
1{
2 "version": "6",
3 "dialect": "sqlite",
4 "id": "012495d1-d78e-4f31-a64f-7328fdf970c0",
5 "prevId": "00000000-0000-0000-0000-000000000000",
6 "tables": {
7 "approvals": {
8 "name": "approvals",
9 "columns": {
10 "id": {
11 "name": "id",
12 "type": "text",
13 "primaryKey": true,
14 "notNull": true,
15 "autoincrement": false
16 },
17 "workspace_id": {
18 "name": "workspace_id",
19 "type": "text",
20 "primaryKey": false,
21 "notNull": true,
22 "autoincrement": false
23 },
24 "task_run_id": {
25 "name": "task_run_id",
26 "type": "text",
27 "primaryKey": false,
28 "notNull": true,
29 "autoincrement": false
30 },
31 "call_id": {
32 "name": "call_id",
33 "type": "text",
34 "primaryKey": false,
35 "notNull": true,
36 "autoincrement": false
37 },
38 "tool_path": {
39 "name": "tool_path",
40 "type": "text",
41 "primaryKey": false,
42 "notNull": true,
43 "autoincrement": false
44 },
45 "status": {
46 "name": "status",
47 "type": "text",
48 "primaryKey": false,
49 "notNull": true,
50 "autoincrement": false
51 },
52 "input_preview_json": {
53 "name": "input_preview_json",
54 "type": "text",
55 "primaryKey": false,
56 "notNull": true,
57 "autoincrement": false
58 },
59 "reason": {
60 "name": "reason",
61 "type": "text",
62 "primaryKey": false,
63 "notNull": false,
64 "autoincrement": false
65 },
66 "requested_at": {
67 "name": "requested_at",
68 "type": "integer",
69 "primaryKey": false,
70 "notNull": true,
71 "autoincrement": false
72 },
73 "resolved_at": {
74 "name": "resolved_at",
75 "type": "integer",
76 "primaryKey": false,
77 "notNull": false,
78 "autoincrement": false
79 }
80 },
81 "indexes": {
82 "approvals_workspace_idx": {
83 "name": "approvals_workspace_idx",
84 "columns": [
85 "workspace_id"
86 ],
87 "isUnique": false
88 },
89 "approvals_task_run_idx": {
90 "name": "approvals_task_run_idx",
91 "columns": [
92 "task_run_id"
93 ],
94 "isUnique": false
95 }
96 },
97 "foreignKeys": {},
98 "compositePrimaryKeys": {},
99 "uniqueConstraints": {},
100 "checkConstraints": {}
101 },
102 "auth_connections": {
103 "name": "auth_connections",
104 "columns": {
105 "id": {
106 "name": "id",
107 "type": "text",
108 "primaryKey": true,
109 "notNull": true,
110 "autoincrement": false
111 },
112 "organization_id": {
113 "name": "organization_id",
114 "type": "text",
115 "primaryKey": false,
116 "notNull": true,
117 "autoincrement": false
118 },
119 "workspace_id": {
120 "name": "workspace_id",
121 "type": "text",
122 "primaryKey": false,
123 "notNull": false,
124 "autoincrement": false
125 },
126 "account_id": {
127 "name": "account_id",
128 "type": "text",
129 "primaryKey": false,
130 "notNull": false,
131 "autoincrement": false
132 },
133 "owner_type": {
134 "name": "owner_type",
135 "type": "text",
136 "primaryKey": false,
137 "notNull": true,
138 "autoincrement": false
139 },
140 "strategy": {
141 "name": "strategy",
142 "type": "text",
143 "primaryKey": false,
144 "notNull": true,
145 "autoincrement": false
146 },
147 "display_name": {
148 "name": "display_name",
149 "type": "text",
150 "primaryKey": false,
151 "notNull": true,
152 "autoincrement": false
153 },
154 "status": {
155 "name": "status",
156 "type": "text",
157 "primaryKey": false,
158 "notNull": true,
159 "autoincrement": false
160 },
161 "status_reason": {
162 "name": "status_reason",
163 "type": "text",
164 "primaryKey": false,
165 "notNull": false,
166 "autoincrement": false
167 },
168 "last_auth_error_class": {
169 "name": "last_auth_error_class",
170 "type": "text",
171 "primaryKey": false,
172 "notNull": false,
173 "autoincrement": false
174 },
175 "metadata_json": {
176 "name": "metadata_json",
177 "type": "text",
178 "primaryKey": false,
179 "notNull": false,
180 "autoincrement": false
181 },
182 "additional_headers_json": {
183 "name": "additional_headers_json",
184 "type": "text",
185 "primaryKey": false,
186 "notNull": false,
187 "autoincrement": false
188 },
189 "created_by_account_id": {
190 "name": "created_by_account_id",
191 "type": "text",
192 "primaryKey": false,
193 "notNull": false,
194 "autoincrement": false
195 },
196 "created_at": {
197 "name": "created_at",
198 "type": "integer",
199 "primaryKey": false,
200 "notNull": true,
201 "autoincrement": false
202 },
203 "updated_at": {
204 "name": "updated_at",
205 "type": "integer",
206 "primaryKey": false,
207 "notNull": true,
208 "autoincrement": false
209 },
210 "last_used_at": {
211 "name": "last_used_at",
212 "type": "integer",
213 "primaryKey": false,
214 "notNull": false,
215 "autoincrement": false
216 }
217 },
218 "indexes": {
219 "auth_connections_org_idx": {
220 "name": "auth_connections_org_idx",
221 "columns": [
222 "organization_id"
223 ],
224 "isUnique": false
225 },
226 "auth_connections_workspace_idx": {
227 "name": "auth_connections_workspace_idx",
228 "columns": [
229 "workspace_id"
230 ],
231 "isUnique": false
232 },
233 "auth_connections_account_idx": {
234 "name": "auth_connections_account_idx",
235 "columns": [
236 "account_id"
237 ],
238 "isUnique": false
239 }
240 },
241 "foreignKeys": {},
242 "compositePrimaryKeys": {},
243 "uniqueConstraints": {},
244 "checkConstraints": {}
245 },
246 "auth_materials": {
247 "name": "auth_materials",
248 "columns": {
249 "id": {
250 "name": "id",
251 "type": "text",
252 "primaryKey": true,
253 "notNull": true,
254 "autoincrement": false
255 },
256 "connection_id": {
257 "name": "connection_id",
258 "type": "text",
259 "primaryKey": false,
260 "notNull": true,
261 "autoincrement": false
262 },
263 "ciphertext": {
264 "name": "ciphertext",
265 "type": "text",
266 "primaryKey": false,
267 "notNull": true,
268 "autoincrement": false
269 },
270 "key_version": {
271 "name": "key_version",
272 "type": "text",
273 "primaryKey": false,
274 "notNull": true,
275 "autoincrement": false
276 },
277 "created_at": {
278 "name": "created_at",
279 "type": "integer",
280 "primaryKey": false,
281 "notNull": true,
282 "autoincrement": false
283 },
284 "updated_at": {
285 "name": "updated_at",
286 "type": "integer",
287 "primaryKey": false,
288 "notNull": true,
289 "autoincrement": false
290 }
291 },
292 "indexes": {
293 "auth_materials_connection_idx": {
294 "name": "auth_materials_connection_idx",
295 "columns": [
296 "connection_id"
297 ],
298 "isUnique": false
299 }
300 },
301 "foreignKeys": {},
302 "compositePrimaryKeys": {},
303 "uniqueConstraints": {},
304 "checkConstraints": {}
305 },
306 "oauth_states": {
307 "name": "oauth_states",
308 "columns": {
309 "id": {
310 "name": "id",
311 "type": "text",
312 "primaryKey": true,
313 "notNull": true,
314 "autoincrement": false
315 },
316 "connection_id": {
317 "name": "connection_id",
318 "type": "text",
319 "primaryKey": false,
320 "notNull": true,
321 "autoincrement": false
322 },
323 "access_token_ciphertext": {
324 "name": "access_token_ciphertext",
325 "type": "text",
326 "primaryKey": false,
327 "notNull": true,
328 "autoincrement": false
329 },
330 "refresh_token_ciphertext": {
331 "name": "refresh_token_ciphertext",
332 "type": "text",
333 "primaryKey": false,
334 "notNull": false,
335 "autoincrement": false
336 },
337 "key_version": {
338 "name": "key_version",
339 "type": "text",
340 "primaryKey": false,
341 "notNull": true,
342 "autoincrement": false
343 },
344 "expires_at": {
345 "name": "expires_at",
346 "type": "integer",
347 "primaryKey": false,
348 "notNull": false,
349 "autoincrement": false
350 },
351 "scope": {
352 "name": "scope",
353 "type": "text",
354 "primaryKey": false,
355 "notNull": false,
356 "autoincrement": false
357 },
358 "token_type": {
359 "name": "token_type",
360 "type": "text",
361 "primaryKey": false,
362 "notNull": false,
363 "autoincrement": false
364 },
365 "issuer": {
366 "name": "issuer",
367 "type": "text",
368 "primaryKey": false,
369 "notNull": false,
370 "autoincrement": false
371 },
372 "refresh_config_json": {
373 "name": "refresh_config_json",
374 "type": "text",
375 "primaryKey": false,
376 "notNull": false,
377 "autoincrement": false
378 },
379 "token_version": {
380 "name": "token_version",
381 "type": "integer",
382 "primaryKey": false,
383 "notNull": true,
384 "autoincrement": false
385 },
386 "lease_holder": {
387 "name": "lease_holder",
388 "type": "text",
389 "primaryKey": false,
390 "notNull": false,
391 "autoincrement": false
392 },
393 "lease_expires_at": {
394 "name": "lease_expires_at",
395 "type": "integer",
396 "primaryKey": false,
397 "notNull": false,
398 "autoincrement": false
399 },
400 "lease_fence": {
401 "name": "lease_fence",
402 "type": "integer",
403 "primaryKey": false,
404 "notNull": true,
405 "autoincrement": false
406 },
407 "last_refresh_at": {
408 "name": "last_refresh_at",
409 "type": "integer",
410 "primaryKey": false,
411 "notNull": false,
412 "autoincrement": false
413 },
414 "last_refresh_error_class": {
415 "name": "last_refresh_error_class",
416 "type": "text",
417 "primaryKey": false,
418 "notNull": false,
419 "autoincrement": false
420 },
421 "last_refresh_error": {
422 "name": "last_refresh_error",
423 "type": "text",
424 "primaryKey": false,
425 "notNull": false,
426 "autoincrement": false
427 },
428 "reauth_required_at": {
429 "name": "reauth_required_at",
430 "type": "integer",
431 "primaryKey": false,
432 "notNull": false,
433 "autoincrement": false
434 },
435 "created_at": {
436 "name": "created_at",
437 "type": "integer",
438 "primaryKey": false,
439 "notNull": true,
440 "autoincrement": false
441 },
442 "updated_at": {
443 "name": "updated_at",
444 "type": "integer",
445 "primaryKey": false,
446 "notNull": true,
447 "autoincrement": false
448 }
449 },
450 "indexes": {
451 "oauth_states_connection_idx": {
452 "name": "oauth_states_connection_idx",
453 "columns": [
454 "connection_id"
455 ],
456 "isUnique": false
457 }
458 },
459 "foreignKeys": {},
460 "compositePrimaryKeys": {},
461 "uniqueConstraints": {},
462 "checkConstraints": {}
463 },
464 "organization_memberships": {
465 "name": "organization_memberships",
466 "columns": {
467 "id": {
468 "name": "id",
469 "type": "text",
470 "primaryKey": true,
471 "notNull": true,
472 "autoincrement": false
473 },
474 "organization_id": {
475 "name": "organization_id",
476 "type": "text",
477 "primaryKey": false,
478 "notNull": true,
479 "autoincrement": false
480 },
481 "account_id": {
482 "name": "account_id",
483 "type": "text",
484 "primaryKey": false,
485 "notNull": true,
486 "autoincrement": false
487 },
488 "role": {
489 "name": "role",
490 "type": "text",
491 "primaryKey": false,
492 "notNull": true,
493 "autoincrement": false
494 },
495 "status": {
496 "name": "status",
497 "type": "text",
498 "primaryKey": false,
499 "notNull": true,
500 "autoincrement": false
501 },
502 "billable": {
503 "name": "billable",
504 "type": "integer",
505 "primaryKey": false,
506 "notNull": true,
507 "autoincrement": false
508 },
509 "invited_by_account_id": {
510 "name": "invited_by_account_id",
511 "type": "text",
512 "primaryKey": false,
513 "notNull": false,
514 "autoincrement": false
515 },
516 "joined_at": {
517 "name": "joined_at",
518 "type": "integer",
519 "primaryKey": false,
520 "notNull": false,
521 "autoincrement": false
522 },
523 "created_at": {
524 "name": "created_at",
525 "type": "integer",
526 "primaryKey": false,
527 "notNull": true,
528 "autoincrement": false
529 },
530 "updated_at": {
531 "name": "updated_at",
532 "type": "integer",
533 "primaryKey": false,
534 "notNull": true,
535 "autoincrement": false
536 }
537 },
538 "indexes": {
539 "organization_memberships_org_idx": {
540 "name": "organization_memberships_org_idx",
541 "columns": [
542 "organization_id"
543 ],
544 "isUnique": false
545 },
546 "organization_memberships_account_idx": {
547 "name": "organization_memberships_account_idx",
548 "columns": [
549 "account_id"
550 ],
551 "isUnique": false
552 }
553 },
554 "foreignKeys": {},
555 "compositePrimaryKeys": {},
556 "uniqueConstraints": {},
557 "checkConstraints": {}
558 },
559 "organizations": {
560 "name": "organizations",
561 "columns": {
562 "id": {
563 "name": "id",
564 "type": "text",
565 "primaryKey": true,
566 "notNull": true,
567 "autoincrement": false
568 },
569 "slug": {
570 "name": "slug",
571 "type": "text",
572 "primaryKey": false,
573 "notNull": true,
574 "autoincrement": false
575 },
576 "name": {
577 "name": "name",
578 "type": "text",
579 "primaryKey": false,
580 "notNull": true,
581 "autoincrement": false
582 },
583 "status": {
584 "name": "status",
585 "type": "text",
586 "primaryKey": false,
587 "notNull": true,
588 "autoincrement": false
589 },
590 "created_by_account_id": {
591 "name": "created_by_account_id",
592 "type": "text",
593 "primaryKey": false,
594 "notNull": false,
595 "autoincrement": false
596 },
597 "created_at": {
598 "name": "created_at",
599 "type": "integer",
600 "primaryKey": false,
601 "notNull": true,
602 "autoincrement": false
603 },
604 "updated_at": {
605 "name": "updated_at",
606 "type": "integer",
607 "primaryKey": false,
608 "notNull": true,
609 "autoincrement": false
610 }
611 },
612 "indexes": {},
613 "foreignKeys": {},
614 "compositePrimaryKeys": {},
615 "uniqueConstraints": {},
616 "checkConstraints": {}
617 },
618 "policies": {
619 "name": "policies",
620 "columns": {
621 "id": {
622 "name": "id",
623 "type": "text",
624 "primaryKey": true,
625 "notNull": true,
626 "autoincrement": false
627 },
628 "workspace_id": {
629 "name": "workspace_id",
630 "type": "text",
631 "primaryKey": false,
632 "notNull": true,
633 "autoincrement": false
634 },
635 "tool_path_pattern": {
636 "name": "tool_path_pattern",
637 "type": "text",
638 "primaryKey": false,
639 "notNull": true,
640 "autoincrement": false
641 },
642 "decision": {
643 "name": "decision",
644 "type": "text",
645 "primaryKey": false,
646 "notNull": true,
647 "autoincrement": false
648 },
649 "created_at": {
650 "name": "created_at",
651 "type": "integer",
652 "primaryKey": false,
653 "notNull": true,
654 "autoincrement": false
655 },
656 "updated_at": {
657 "name": "updated_at",
658 "type": "integer",
659 "primaryKey": false,
660 "notNull": true,
661 "autoincrement": false
662 }
663 },
664 "indexes": {
665 "policies_workspace_idx": {
666 "name": "policies_workspace_idx",
667 "columns": [
668 "workspace_id"
669 ],
670 "isUnique": false
671 }
672 },
673 "foreignKeys": {},
674 "compositePrimaryKeys": {},
675 "uniqueConstraints": {},
676 "checkConstraints": {}
677 },
678 "profile": {
679 "name": "profile",
680 "columns": {
681 "id": {
682 "name": "id",
683 "type": "text",
684 "primaryKey": true,
685 "notNull": true,
686 "autoincrement": false
687 },
688 "default_workspace_id": {
689 "name": "default_workspace_id",
690 "type": "text",
691 "primaryKey": false,
692 "notNull": false,
693 "autoincrement": false
694 },
695 "display_name": {
696 "name": "display_name",
697 "type": "text",
698 "primaryKey": false,
699 "notNull": true,
700 "autoincrement": false
701 },
702 "runtime_mode": {
703 "name": "runtime_mode",
704 "type": "text",
705 "primaryKey": false,
706 "notNull": true,
707 "autoincrement": false
708 },
709 "created_at": {
710 "name": "created_at",
711 "type": "integer",
712 "primaryKey": false,
713 "notNull": true,
714 "autoincrement": false
715 },
716 "updated_at": {
717 "name": "updated_at",
718 "type": "integer",
719 "primaryKey": false,
720 "notNull": true,
721 "autoincrement": false
722 }
723 },
724 "indexes": {},
725 "foreignKeys": {},
726 "compositePrimaryKeys": {},
727 "uniqueConstraints": {},
728 "checkConstraints": {}
729 },
730 "source_auth_bindings": {
731 "name": "source_auth_bindings",
732 "columns": {
733 "id": {
734 "name": "id",
735 "type": "text",
736 "primaryKey": true,
737 "notNull": true,
738 "autoincrement": false
739 },
740 "source_id": {
741 "name": "source_id",
742 "type": "text",
743 "primaryKey": false,
744 "notNull": true,
745 "autoincrement": false
746 },
747 "connection_id": {
748 "name": "connection_id",
749 "type": "text",
750 "primaryKey": false,
751 "notNull": true,
752 "autoincrement": false
753 },
754 "organization_id": {
755 "name": "organization_id",
756 "type": "text",
757 "primaryKey": false,
758 "notNull": true,
759 "autoincrement": false
760 },
761 "workspace_id": {
762 "name": "workspace_id",
763 "type": "text",
764 "primaryKey": false,
765 "notNull": false,
766 "autoincrement": false
767 },
768 "account_id": {
769 "name": "account_id",
770 "type": "text",
771 "primaryKey": false,
772 "notNull": false,
773 "autoincrement": false
774 },
775 "scope_type": {
776 "name": "scope_type",
777 "type": "text",
778 "primaryKey": false,
779 "notNull": true,
780 "autoincrement": false
781 },
782 "selector": {
783 "name": "selector",
784 "type": "text",
785 "primaryKey": false,
786 "notNull": false,
787 "autoincrement": false
788 },
789 "enabled": {
790 "name": "enabled",
791 "type": "integer",
792 "primaryKey": false,
793 "notNull": true,
794 "autoincrement": false
795 },
796 "created_at": {
797 "name": "created_at",
798 "type": "integer",
799 "primaryKey": false,
800 "notNull": true,
801 "autoincrement": false
802 },
803 "updated_at": {
804 "name": "updated_at",
805 "type": "integer",
806 "primaryKey": false,
807 "notNull": true,
808 "autoincrement": false
809 }
810 },
811 "indexes": {
812 "source_auth_bindings_source_idx": {
813 "name": "source_auth_bindings_source_idx",
814 "columns": [
815 "source_id"
816 ],
817 "isUnique": false
818 },
819 "source_auth_bindings_connection_idx": {
820 "name": "source_auth_bindings_connection_idx",
821 "columns": [
822 "connection_id"
823 ],
824 "isUnique": false
825 },
826 "source_auth_bindings_org_idx": {
827 "name": "source_auth_bindings_org_idx",
828 "columns": [
829 "organization_id"
830 ],
831 "isUnique": false
832 },
833 "source_auth_bindings_workspace_idx": {
834 "name": "source_auth_bindings_workspace_idx",
835 "columns": [
836 "workspace_id"
837 ],
838 "isUnique": false
839 },
840 "source_auth_bindings_account_idx": {
841 "name": "source_auth_bindings_account_idx",
842 "columns": [
843 "account_id"
844 ],
845 "isUnique": false
846 }
847 },
848 "foreignKeys": {},
849 "compositePrimaryKeys": {},
850 "uniqueConstraints": {},
851 "checkConstraints": {}
852 },
853 "sources": {
854 "name": "sources",
855 "columns": {
856 "workspace_id": {
857 "name": "workspace_id",
858 "type": "text",
859 "primaryKey": false,
860 "notNull": true,
861 "autoincrement": false
862 },
863 "source_id": {
864 "name": "source_id",
865 "type": "text",
866 "primaryKey": false,
867 "notNull": true,
868 "autoincrement": false
869 },
870 "name": {
871 "name": "name",
872 "type": "text",
873 "primaryKey": false,
874 "notNull": true,
875 "autoincrement": false
876 },
877 "kind": {
878 "name": "kind",
879 "type": "text",
880 "primaryKey": false,
881 "notNull": true,
882 "autoincrement": false
883 },
884 "endpoint": {
885 "name": "endpoint",
886 "type": "text",
887 "primaryKey": false,
888 "notNull": true,
889 "autoincrement": false
890 },
891 "status": {
892 "name": "status",
893 "type": "text",
894 "primaryKey": false,
895 "notNull": true,
896 "autoincrement": false
897 },
898 "enabled": {
899 "name": "enabled",
900 "type": "integer",
901 "primaryKey": false,
902 "notNull": true,
903 "autoincrement": false
904 },
905 "config_json": {
906 "name": "config_json",
907 "type": "text",
908 "primaryKey": false,
909 "notNull": true,
910 "autoincrement": false
911 },
912 "source_hash": {
913 "name": "source_hash",
914 "type": "text",
915 "primaryKey": false,
916 "notNull": false,
917 "autoincrement": false
918 },
919 "last_error": {
920 "name": "last_error",
921 "type": "text",
922 "primaryKey": false,
923 "notNull": false,
924 "autoincrement": false
925 },
926 "created_at": {
927 "name": "created_at",
928 "type": "integer",
929 "primaryKey": false,
930 "notNull": true,
931 "autoincrement": false
932 },
933 "updated_at": {
934 "name": "updated_at",
935 "type": "integer",
936 "primaryKey": false,
937 "notNull": true,
938 "autoincrement": false
939 }
940 },
941 "indexes": {
942 "sources_workspace_name_idx": {
943 "name": "sources_workspace_name_idx",
944 "columns": [
945 "workspace_id",
946 "name"
947 ],
948 "isUnique": false
949 }
950 },
951 "foreignKeys": {},
952 "compositePrimaryKeys": {
953 "sources_workspace_id_source_id_pk": {
954 "columns": [
955 "workspace_id",
956 "source_id"
957 ],
958 "name": "sources_workspace_id_source_id_pk"
959 }
960 },
961 "uniqueConstraints": {},
962 "checkConstraints": {}
963 },
964 "storage_instances": {
965 "name": "storage_instances",
966 "columns": {
967 "id": {
968 "name": "id",
969 "type": "text",
970 "primaryKey": true,
971 "notNull": true,
972 "autoincrement": false
973 },
974 "scope_type": {
975 "name": "scope_type",
976 "type": "text",
977 "primaryKey": false,
978 "notNull": true,
979 "autoincrement": false
980 },
981 "durability": {
982 "name": "durability",
983 "type": "text",
984 "primaryKey": false,
985 "notNull": true,
986 "autoincrement": false
987 },
988 "status": {
989 "name": "status",
990 "type": "text",
991 "primaryKey": false,
992 "notNull": true,
993 "autoincrement": false
994 },
995 "provider": {
996 "name": "provider",
997 "type": "text",
998 "primaryKey": false,
999 "notNull": true,
1000 "autoincrement": false
1001 },
1002 "backend_key": {
1003 "name": "backend_key",
1004 "type": "text",
1005 "primaryKey": false,
1006 "notNull": true,
1007 "autoincrement": false
1008 },
1009 "organization_id": {
1010 "name": "organization_id",
1011 "type": "text",
1012 "primaryKey": false,
1013 "notNull": true,
1014 "autoincrement": false
1015 },
1016 "workspace_id": {
1017 "name": "workspace_id",
1018 "type": "text",
1019 "primaryKey": false,
1020 "notNull": false,
1021 "autoincrement": false
1022 },
1023 "account_id": {
1024 "name": "account_id",
1025 "type": "text",
1026 "primaryKey": false,
1027 "notNull": false,
1028 "autoincrement": false
1029 },
1030 "created_by_account_id": {
1031 "name": "created_by_account_id",
1032 "type": "text",
1033 "primaryKey": false,
1034 "notNull": false,
1035 "autoincrement": false
1036 },
1037 "purpose": {
1038 "name": "purpose",
1039 "type": "text",
1040 "primaryKey": false,
1041 "notNull": false,
1042 "autoincrement": false
1043 },
1044 "size_bytes": {
1045 "name": "size_bytes",
1046 "type": "integer",
1047 "primaryKey": false,
1048 "notNull": false,
1049 "autoincrement": false
1050 },
1051 "file_count": {
1052 "name": "file_count",
1053 "type": "integer",
1054 "primaryKey": false,
1055 "notNull": false,
1056 "autoincrement": false
1057 },
1058 "created_at": {
1059 "name": "created_at",
1060 "type": "integer",
1061 "primaryKey": false,
1062 "notNull": true,
1063 "autoincrement": false
1064 },
1065 "updated_at": {
1066 "name": "updated_at",
1067 "type": "integer",
1068 "primaryKey": false,
1069 "notNull": true,
1070 "autoincrement": false
1071 },
1072 "last_seen_at": {
1073 "name": "last_seen_at",
1074 "type": "integer",
1075 "primaryKey": false,
1076 "notNull": true,
1077 "autoincrement": false
1078 },
1079 "closed_at": {
1080 "name": "closed_at",
1081 "type": "integer",
1082 "primaryKey": false,
1083 "notNull": false,
1084 "autoincrement": false
1085 },
1086 "expires_at": {
1087 "name": "expires_at",
1088 "type": "integer",
1089 "primaryKey": false,
1090 "notNull": false,
1091 "autoincrement": false
1092 }
1093 },
1094 "indexes": {
1095 "storage_instances_org_idx": {
1096 "name": "storage_instances_org_idx",
1097 "columns": [
1098 "organization_id"
1099 ],
1100 "isUnique": false
1101 },
1102 "storage_instances_workspace_idx": {
1103 "name": "storage_instances_workspace_idx",
1104 "columns": [
1105 "workspace_id"
1106 ],
1107 "isUnique": false
1108 }
1109 },
1110 "foreignKeys": {},
1111 "compositePrimaryKeys": {},
1112 "uniqueConstraints": {},
1113 "checkConstraints": {}
1114 },
1115 "sync_states": {
1116 "name": "sync_states",
1117 "columns": {
1118 "id": {
1119 "name": "id",
1120 "type": "text",
1121 "primaryKey": true,
1122 "notNull": true,
1123 "autoincrement": false
1124 },
1125 "workspace_id": {
1126 "name": "workspace_id",
1127 "type": "text",
1128 "primaryKey": false,
1129 "notNull": true,
1130 "autoincrement": false
1131 },
1132 "target": {
1133 "name": "target",
1134 "type": "text",
1135 "primaryKey": false,
1136 "notNull": true,
1137 "autoincrement": false
1138 },
1139 "target_url": {
1140 "name": "target_url",
1141 "type": "text",
1142 "primaryKey": false,
1143 "notNull": true,
1144 "autoincrement": false
1145 },
1146 "linked_subject": {
1147 "name": "linked_subject",
1148 "type": "text",
1149 "primaryKey": false,
1150 "notNull": false,
1151 "autoincrement": false
1152 },
1153 "cursor": {
1154 "name": "cursor",
1155 "type": "text",
1156 "primaryKey": false,
1157 "notNull": false,
1158 "autoincrement": false
1159 },
1160 "last_sync_at": {
1161 "name": "last_sync_at",
1162 "type": "integer",
1163 "primaryKey": false,
1164 "notNull": false,
1165 "autoincrement": false
1166 },
1167 "updated_at": {
1168 "name": "updated_at",
1169 "type": "integer",
1170 "primaryKey": false,
1171 "notNull": true,
1172 "autoincrement": false
1173 }
1174 },
1175 "indexes": {
1176 "sync_states_workspace_idx": {
1177 "name": "sync_states_workspace_idx",
1178 "columns": [
1179 "workspace_id"
1180 ],
1181 "isUnique": false
1182 }
1183 },
1184 "foreignKeys": {},
1185 "compositePrimaryKeys": {},
1186 "uniqueConstraints": {},
1187 "checkConstraints": {}
1188 },
1189 "task_runs": {
1190 "name": "task_runs",
1191 "columns": {
1192 "id": {
1193 "name": "id",
1194 "type": "text",
1195 "primaryKey": true,
1196 "notNull": true,
1197 "autoincrement": false
1198 },
1199 "workspace_id": {
1200 "name": "workspace_id",
1201 "type": "text",
1202 "primaryKey": false,
1203 "notNull": true,
1204 "autoincrement": false
1205 },
1206 "account_id": {
1207 "name": "account_id",
1208 "type": "text",
1209 "primaryKey": false,
1210 "notNull": true,
1211 "autoincrement": false
1212 },
1213 "session_id": {
1214 "name": "session_id",
1215 "type": "text",
1216 "primaryKey": false,
1217 "notNull": true,
1218 "autoincrement": false
1219 },
1220 "runtime_id": {
1221 "name": "runtime_id",
1222 "type": "text",
1223 "primaryKey": false,
1224 "notNull": true,
1225 "autoincrement": false
1226 },
1227 "code_hash": {
1228 "name": "code_hash",
1229 "type": "text",
1230 "primaryKey": false,
1231 "notNull": true,
1232 "autoincrement": false
1233 },
1234 "status": {
1235 "name": "status",
1236 "type": "text",
1237 "primaryKey": false,
1238 "notNull": true,
1239 "autoincrement": false
1240 },
1241 "started_at": {
1242 "name": "started_at",
1243 "type": "integer",
1244 "primaryKey": false,
1245 "notNull": false,
1246 "autoincrement": false
1247 },
1248 "completed_at": {
1249 "name": "completed_at",
1250 "type": "integer",
1251 "primaryKey": false,
1252 "notNull": false,
1253 "autoincrement": false
1254 },
1255 "exit_code": {
1256 "name": "exit_code",
1257 "type": "integer",
1258 "primaryKey": false,
1259 "notNull": false,
1260 "autoincrement": false
1261 },
1262 "error": {
1263 "name": "error",
1264 "type": "text",
1265 "primaryKey": false,
1266 "notNull": false,
1267 "autoincrement": false
1268 }
1269 },
1270 "indexes": {
1271 "task_runs_workspace_idx": {
1272 "name": "task_runs_workspace_idx",
1273 "columns": [
1274 "workspace_id"
1275 ],
1276 "isUnique": false
1277 }
1278 },
1279 "foreignKeys": {},
1280 "compositePrimaryKeys": {},
1281 "uniqueConstraints": {},
1282 "checkConstraints": {}
1283 },
1284 "tool_artifacts": {
1285 "name": "tool_artifacts",
1286 "columns": {
1287 "id": {
1288 "name": "id",
1289 "type": "text",
1290 "primaryKey": false,
1291 "notNull": true,
1292 "autoincrement": false
1293 },
1294 "workspace_id": {
1295 "name": "workspace_id",
1296 "type": "text",
1297 "primaryKey": false,
1298 "notNull": true,
1299 "autoincrement": false
1300 },
1301 "source_id": {
1302 "name": "source_id",
1303 "type": "text",
1304 "primaryKey": false,
1305 "notNull": true,
1306 "autoincrement": false
1307 },
1308 "source_hash": {
1309 "name": "source_hash",
1310 "type": "text",
1311 "primaryKey": false,
1312 "notNull": true,
1313 "autoincrement": false
1314 },
1315 "tool_count": {
1316 "name": "tool_count",
1317 "type": "integer",
1318 "primaryKey": false,
1319 "notNull": true,
1320 "autoincrement": false
1321 },
1322 "manifest_json": {
1323 "name": "manifest_json",
1324 "type": "text",
1325 "primaryKey": false,
1326 "notNull": true,
1327 "autoincrement": false
1328 },
1329 "created_at": {
1330 "name": "created_at",
1331 "type": "integer",
1332 "primaryKey": false,
1333 "notNull": true,
1334 "autoincrement": false
1335 },
1336 "updated_at": {
1337 "name": "updated_at",
1338 "type": "integer",
1339 "primaryKey": false,
1340 "notNull": true,
1341 "autoincrement": false
1342 }
1343 },
1344 "indexes": {
1345 "tool_artifacts_id_idx": {
1346 "name": "tool_artifacts_id_idx",
1347 "columns": [
1348 "id"
1349 ],
1350 "isUnique": true
1351 }
1352 },
1353 "foreignKeys": {},
1354 "compositePrimaryKeys": {
1355 "tool_artifacts_workspace_id_source_id_pk": {
1356 "columns": [
1357 "workspace_id",
1358 "source_id"
1359 ],
1360 "name": "tool_artifacts_workspace_id_source_id_pk"
1361 }
1362 },
1363 "uniqueConstraints": {},
1364 "checkConstraints": {}
1365 },
1366 "workspaces": {
1367 "name": "workspaces",
1368 "columns": {
1369 "id": {
1370 "name": "id",
1371 "type": "text",
1372 "primaryKey": true,
1373 "notNull": true,
1374 "autoincrement": false
1375 },
1376 "organization_id": {
1377 "name": "organization_id",
1378 "type": "text",
1379 "primaryKey": false,
1380 "notNull": true,
1381 "autoincrement": false
1382 },
1383 "name": {
1384 "name": "name",
1385 "type": "text",
1386 "primaryKey": false,
1387 "notNull": true,
1388 "autoincrement": false
1389 },
1390 "created_by_account_id": {
1391 "name": "created_by_account_id",
1392 "type": "text",
1393 "primaryKey": false,
1394 "notNull": false,
1395 "autoincrement": false
1396 },
1397 "created_at": {
1398 "name": "created_at",
1399 "type": "integer",
1400 "primaryKey": false,
1401 "notNull": true,
1402 "autoincrement": false
1403 },
1404 "updated_at": {
1405 "name": "updated_at",
1406 "type": "integer",
1407 "primaryKey": false,
1408 "notNull": true,
1409 "autoincrement": false
1410 }
1411 },
1412 "indexes": {
1413 "workspaces_org_idx": {
1414 "name": "workspaces_org_idx",
1415 "columns": [
1416 "organization_id"
1417 ],
1418 "isUnique": false
1419 }
1420 },
1421 "foreignKeys": {},
1422 "compositePrimaryKeys": {},
1423 "uniqueConstraints": {},
1424 "checkConstraints": {}
1425 }
1426 },
1427 "views": {},
1428 "enums": {},
1429 "_meta": {
1430 "schemas": {},
1431 "tables": {},
1432 "columns": {}
1433 },
1434 "internal": {
1435 "indexes": {}
1436 }
1437}
packages/persistence-sql/drizzle/sqlite/meta/_journal.json+13−0
@@ -0,0 +1,13 @@
1{
2 "version": "7",
3 "dialect": "sqlite",
4 "entries": [
5 {
6 "idx": 0,
7 "version": "6",
8 "when": 1772506139541,
9 "tag": "0000_curved_raider",
10 "breakpoints": true
11 }
12 ]
13}
packages/persistence-sql/package.json+11−1
@@ -6,7 +6,14 @@ · 5 unmodified lines
6 ".": "./src/index.ts"6 ".": "./src/index.ts"
7 },7 },
8 "scripts": {8 "scripts": {
9 "typecheck": "bunx tsc --noEmit -p tsconfig.json"9 "typecheck": "bunx tsc --noEmit -p tsconfig.json",
10 "db:generate": "drizzle-kit generate --config drizzle.config.ts",
11 "db:generate:pg": "drizzle-kit generate --config drizzle.config.pg.ts",
12 "db:check": "drizzle-kit check --config drizzle.config.ts",
13 "db:check:pg": "drizzle-kit check --config drizzle.config.pg.ts",
14 "db:migrate": "drizzle-kit migrate --config drizzle.config.ts",
15 "db:migrate:pg": "drizzle-kit migrate --config drizzle.config.pg.ts",
16 "db:studio": "drizzle-kit studio --config drizzle.config.ts"
10 },17 },
11 "dependencies": {18 "dependencies": {
12 "@executor-v2/persistence-ports": "workspace:*",19 "@executor-v2/persistence-ports": "workspace:*",
@@ -14,5 +21,8 @@ · 1 unmodified line
14 "drizzle-orm": "^0.44.7",21 "drizzle-orm": "^0.44.7",
15 "effect": "catalog:",22 "effect": "catalog:",
16 "postgres": "^3.4.7"23 "postgres": "^3.4.7"
24 },
25 "devDependencies": {
26 "drizzle-kit": "^0.31.9"
17 }27 }
18}28}
packages/persistence-sql/src/persistence-codecs.ts+0−52
@@ -1,52 +0,0 @@
1import {
2 ApprovalSchema,
3 AuthConnectionSchema,
4 AuthMaterialSchema,
5 OAuthStateSchema,
6 OrganizationMembershipSchema,
7 OrganizationSchema,
8 PolicySchema,
9 ProfileSchema,
10 SourceAuthBindingSchema,
11 SourceSchema,
12 StorageInstanceSchema,
13 SyncStateSchema,
14 TaskRunSchema,
15 ToolArtifactSchema,
16 WorkspaceSchema,
17} from "@executor-v2/schema";
18import * as Schema from "effect/Schema";
19
20type JsonCodec<A> = {
21 encode: (value: A) => string;
22 decode: (value: string) => A;
23};
24
25const makeJsonCodec = <A, I>(schema: Schema.Schema<A, I, never>): JsonCodec<A> => {
26 const jsonSchema = Schema.parseJson(schema);
27
28 return {
29 encode: Schema.encodeSync(jsonSchema),
30 decode: Schema.decodeUnknownSync(jsonSchema),
31 };
32};
33
34export const ProfileJson = makeJsonCodec(ProfileSchema);
35export const OrganizationJson = makeJsonCodec(OrganizationSchema);
36export const OrganizationMembershipJson = makeJsonCodec(
37 OrganizationMembershipSchema,
38);
39export const WorkspaceJson = makeJsonCodec(WorkspaceSchema);
40export const SourceJson = makeJsonCodec(SourceSchema);
41export const ToolArtifactJson = makeJsonCodec(ToolArtifactSchema);
42export const AuthConnectionJson = makeJsonCodec(AuthConnectionSchema);
43export const SourceAuthBindingJson = makeJsonCodec(
44 SourceAuthBindingSchema,
45);
46export const AuthMaterialJson = makeJsonCodec(AuthMaterialSchema);
47export const OAuthStateJson = makeJsonCodec(OAuthStateSchema);
48export const PolicyJson = makeJsonCodec(PolicySchema);
49export const ApprovalJson = makeJsonCodec(ApprovalSchema);
50export const TaskRunJson = makeJsonCodec(TaskRunSchema);
51export const StorageInstanceJson = makeJsonCodec(StorageInstanceSchema);
52export const SyncStateJson = makeJsonCodec(SyncStateSchema);
packages/persistence-sql/src/row-operations-auth.ts+199−92
@@ -7,12 +7,11 @@ import { · 6 unmodified lines
7import { asc, eq } from "drizzle-orm";7import { asc, eq } from "drizzle-orm";
8 8
9import {9import {
10 AuthConnectionJson,10 createDrizzleContext,
11 AuthMaterialJson,11 type DrizzleDb,
12 OAuthStateJson,12 type DrizzleTables,
13 SourceAuthBindingJson,13 type SqlAdapter,
14} from "./persistence-codecs";14} from "./sql-internals";
15import { createDrizzleContext, type DrizzleDb, type DrizzleTables, type SqlAdapter } from "./sql-internals";
16 15
17type WriteLocked = <A>(run: () => Promise<A>) => Promise<A>;16type WriteLocked = <A>(run: () => Promise<A>) => Promise<A>;
18 17
@@ -23,6 +22,79 @@ type AuthOperationsInput = { · 4 unmodified lines
23 writeLocked: WriteLocked;22 writeLocked: WriteLocked;
24};23};
25 24
25const toAuthConnection = (
26 row: DrizzleTables["authConnectionsTable"]["$inferSelect"],
27): AuthConnection => ({
28 id: row.id as AuthConnection["id"],
29 organizationId: row.organizationId as AuthConnection["organizationId"],
30 workspaceId: row.workspaceId as AuthConnection["workspaceId"],
31 accountId: row.accountId as AuthConnection["accountId"],
32 ownerType: row.ownerType as AuthConnection["ownerType"],
33 strategy: row.strategy as AuthConnection["strategy"],
34 displayName: row.displayName,
35 status: row.status as AuthConnection["status"],
36 statusReason: row.statusReason,
37 lastAuthErrorClass: row.lastAuthErrorClass,
38 metadataJson: row.metadataJson,
39 additionalHeadersJson: row.additionalHeadersJson,
40 createdByAccountId: row.createdByAccountId as AuthConnection["createdByAccountId"],
41 createdAt: row.createdAt,
42 updatedAt: row.updatedAt,
43 lastUsedAt: row.lastUsedAt,
44});
45
46const toSourceAuthBinding = (
47 row: DrizzleTables["sourceAuthBindingsTable"]["$inferSelect"],
48): SourceAuthBinding => ({
49 id: row.id as SourceAuthBinding["id"],
50 sourceId: row.sourceId as SourceAuthBinding["sourceId"],
51 connectionId: row.connectionId as SourceAuthBinding["connectionId"],
52 organizationId: row.organizationId as SourceAuthBinding["organizationId"],
53 workspaceId: row.workspaceId as SourceAuthBinding["workspaceId"],
54 accountId: row.accountId as SourceAuthBinding["accountId"],
55 scopeType: row.scopeType as SourceAuthBinding["scopeType"],
56 selector: row.selector,
57 enabled: row.enabled,
58 createdAt: row.createdAt,
59 updatedAt: row.updatedAt,
60});
61
62const toAuthMaterial = (
63 row: DrizzleTables["authMaterialsTable"]["$inferSelect"],
64): AuthMaterial => ({
65 id: row.id as AuthMaterial["id"],
66 connectionId: row.connectionId as AuthMaterial["connectionId"],
67 ciphertext: row.ciphertext,
68 keyVersion: row.keyVersion,
69 createdAt: row.createdAt,
70 updatedAt: row.updatedAt,
71});
72
73const toOAuthState = (
74 row: DrizzleTables["oauthStatesTable"]["$inferSelect"],
75): OAuthState => ({
76 id: row.id as OAuthState["id"],
77 connectionId: row.connectionId as OAuthState["connectionId"],
78 accessTokenCiphertext: row.accessTokenCiphertext,
79 refreshTokenCiphertext: row.refreshTokenCiphertext,
80 keyVersion: row.keyVersion,
81 expiresAt: row.expiresAt,
82 scope: row.scope,
83 tokenType: row.tokenType,
84 issuer: row.issuer,
85 refreshConfigJson: row.refreshConfigJson,
86 tokenVersion: row.tokenVersion,
87 leaseHolder: row.leaseHolder,
88 leaseExpiresAt: row.leaseExpiresAt,
89 leaseFence: row.leaseFence,
90 lastRefreshAt: row.lastRefreshAt,
91 lastRefreshErrorClass: row.lastRefreshErrorClass,
92 lastRefreshError: row.lastRefreshError,
93 reauthRequiredAt: row.reauthRequiredAt,
94 createdAt: row.createdAt,
95 updatedAt: row.updatedAt,
96});
97
26export const createAuthRowOperations = ({98export const createAuthRowOperations = ({
27 adapter,99 adapter,
28 db,100 db,
@@ -30,35 +102,57 @@ export const createAuthRowOperations = ({ · 1 unmodified line
30 writeLocked,102 writeLocked,
31}: AuthOperationsInput) => {103}: AuthOperationsInput) => {
32 const listAuthConnectionRows = async (): Promise<Array<AuthConnection>> => {104 const listAuthConnectionRows = async (): Promise<Array<AuthConnection>> => {
33 const rows = await db105 const rows = await db.select().from(tables.authConnectionsTable).orderBy(
34 .select({ payloadJson: tables.authConnectionsTable.payloadJson })106 asc(tables.authConnectionsTable.updatedAt),
35 .from(tables.authConnectionsTable)107 asc(tables.authConnectionsTable.id),
36 .orderBy(asc(tables.authConnectionsTable.updatedAt), asc(tables.authConnectionsTable.id));108 );
37 109
38 return rows.map((row) => AuthConnectionJson.decode(row.payloadJson));110 return rows.map(toAuthConnection);
39 };111 };
40 112
41 const upsertAuthConnectionRow = async (connection: AuthConnection): Promise<void> => {113 const upsertAuthConnectionRow = async (connection: AuthConnection): Promise<void> => {
42 await writeLocked(async () => {114 await writeLocked(async () => {
43 await adapter.transaction(async (transaction) => {115 await adapter.transaction(async (transaction) => {
44 const transactionContext = createDrizzleContext(transaction);116 const transactionContext = createDrizzleContext(transaction);
45 const payloadJson = AuthConnectionJson.encode(connection);
46 const now = Date.now();
47 117
48 await transactionContext.db118 await transactionContext.db
49 .insert(transactionContext.tables.authConnectionsTable)119 .insert(transactionContext.tables.authConnectionsTable)
50 .values({120 .values({
51 id: connection.id,121 id: connection.id,
122 organizationId: connection.organizationId,
52 workspaceId: connection.workspaceId,123 workspaceId: connection.workspaceId,
53 payloadJson,124 accountId: connection.accountId,
54 updatedAt: now,125 ownerType: connection.ownerType,
126 strategy: connection.strategy,
127 displayName: connection.displayName,
128 status: connection.status,
129 statusReason: connection.statusReason,
130 lastAuthErrorClass: connection.lastAuthErrorClass,
131 metadataJson: connection.metadataJson,
132 additionalHeadersJson: connection.additionalHeadersJson,
133 createdByAccountId: connection.createdByAccountId,
134 createdAt: connection.createdAt,
135 updatedAt: connection.updatedAt,
136 lastUsedAt: connection.lastUsedAt,
55 })137 })
56 .onConflictDoUpdate({138 .onConflictDoUpdate({
57 target: transactionContext.tables.authConnectionsTable.id,139 target: transactionContext.tables.authConnectionsTable.id,
58 set: {140 set: {
141 organizationId: connection.organizationId,
59 workspaceId: connection.workspaceId,142 workspaceId: connection.workspaceId,
60 payloadJson,143 accountId: connection.accountId,
61 updatedAt: now,144 ownerType: connection.ownerType,
145 strategy: connection.strategy,
146 displayName: connection.displayName,
147 status: connection.status,
148 statusReason: connection.statusReason,
149 lastAuthErrorClass: connection.lastAuthErrorClass,
150 metadataJson: connection.metadataJson,
151 additionalHeadersJson: connection.additionalHeadersJson,
152 createdByAccountId: connection.createdByAccountId,
153 createdAt: connection.createdAt,
154 updatedAt: connection.updatedAt,
155 lastUsedAt: connection.lastUsedAt,
62 },156 },
63 });157 });
64 });158 });
@@ -90,15 +184,12 @@ export const createAuthRowOperations = ({ · 25 unmodified lines
90 );184 );
91 185
92 const listSourceAuthBindingRows = async (): Promise<Array<SourceAuthBinding>> => {186 const listSourceAuthBindingRows = async (): Promise<Array<SourceAuthBinding>> => {
93 const rows = await db187 const rows = await db.select().from(tables.sourceAuthBindingsTable).orderBy(
94 .select({ payloadJson: tables.sourceAuthBindingsTable.payloadJson })188 asc(tables.sourceAuthBindingsTable.updatedAt),
95 .from(tables.sourceAuthBindingsTable)189 asc(tables.sourceAuthBindingsTable.id),
96 .orderBy(190 );
97 asc(tables.sourceAuthBindingsTable.updatedAt),191
98 asc(tables.sourceAuthBindingsTable.id),192 return rows.map(toSourceAuthBinding);
99 );
100
101 return rows.map((row) => SourceAuthBindingJson.decode(row.payloadJson));
102 };193 };
103 194
104 const upsertSourceAuthBindingRow = async (195 const upsertSourceAuthBindingRow = async (
@@ -107,23 +198,35 @@ export const createAuthRowOperations = ({ · 2 unmodified lines
107 await writeLocked(async () => {198 await writeLocked(async () => {
108 await adapter.transaction(async (transaction) => {199 await adapter.transaction(async (transaction) => {
109 const transactionContext = createDrizzleContext(transaction);200 const transactionContext = createDrizzleContext(transaction);
110 const payloadJson = SourceAuthBindingJson.encode(binding);
111 const now = Date.now();
112 201
113 await transactionContext.db202 await transactionContext.db
114 .insert(transactionContext.tables.sourceAuthBindingsTable)203 .insert(transactionContext.tables.sourceAuthBindingsTable)
115 .values({204 .values({
116 id: binding.id,205 id: binding.id,
206 sourceId: binding.sourceId,
207 connectionId: binding.connectionId,
208 organizationId: binding.organizationId,
117 workspaceId: binding.workspaceId,209 workspaceId: binding.workspaceId,
118 payloadJson,210 accountId: binding.accountId,
119 updatedAt: now,211 scopeType: binding.scopeType,
212 selector: binding.selector,
213 enabled: binding.enabled,
214 createdAt: binding.createdAt,
215 updatedAt: binding.updatedAt,
120 })216 })
121 .onConflictDoUpdate({217 .onConflictDoUpdate({
122 target: transactionContext.tables.sourceAuthBindingsTable.id,218 target: transactionContext.tables.sourceAuthBindingsTable.id,
123 set: {219 set: {
220 sourceId: binding.sourceId,
221 connectionId: binding.connectionId,
222 organizationId: binding.organizationId,
124 workspaceId: binding.workspaceId,223 workspaceId: binding.workspaceId,
125 payloadJson,224 accountId: binding.accountId,
126 updatedAt: now,225 scopeType: binding.scopeType,
226 selector: binding.selector,
227 enabled: binding.enabled,
228 createdAt: binding.createdAt,
229 updatedAt: binding.updatedAt,
127 },230 },
128 });231 });
129 });232 });
@@ -155,35 +258,37 @@ export const createAuthRowOperations = ({ · 25 unmodified lines
155 );258 );
156 259
157 const listAuthMaterialRows = async (): Promise<Array<AuthMaterial>> => {260 const listAuthMaterialRows = async (): Promise<Array<AuthMaterial>> => {
158 const rows = await db261 const rows = await db.select().from(tables.authMaterialsTable).orderBy(
159 .select({ payloadJson: tables.authMaterialsTable.payloadJson })262 asc(tables.authMaterialsTable.updatedAt),
160 .from(tables.authMaterialsTable)263 asc(tables.authMaterialsTable.id),
161 .orderBy(asc(tables.authMaterialsTable.updatedAt), asc(tables.authMaterialsTable.id));264 );
162 265
163 return rows.map((row) => AuthMaterialJson.decode(row.payloadJson));266 return rows.map(toAuthMaterial);
164 };267 };
165 268
166 const upsertAuthMaterialRow = async (material: AuthMaterial): Promise<void> => {269 const upsertAuthMaterialRow = async (material: AuthMaterial): Promise<void> => {
167 await writeLocked(async () => {270 await writeLocked(async () => {
168 await adapter.transaction(async (transaction) => {271 await adapter.transaction(async (transaction) => {
169 const transactionContext = createDrizzleContext(transaction);272 const transactionContext = createDrizzleContext(transaction);
170 const payloadJson = AuthMaterialJson.encode(material);
171 const now = Date.now();
172 273
173 await transactionContext.db274 await transactionContext.db
174 .insert(transactionContext.tables.authMaterialsTable)275 .insert(transactionContext.tables.authMaterialsTable)
175 .values({276 .values({
176 id: material.id,277 id: material.id,
177 workspaceId: null,278 connectionId: material.connectionId,
178 payloadJson,279 ciphertext: material.ciphertext,
179 updatedAt: now,280 keyVersion: material.keyVersion,
281 createdAt: material.createdAt,
282 updatedAt: material.updatedAt,
180 })283 })
181 .onConflictDoUpdate({284 .onConflictDoUpdate({
182 target: transactionContext.tables.authMaterialsTable.id,285 target: transactionContext.tables.authMaterialsTable.id,
183 set: {286 set: {
184 workspaceId: null,287 connectionId: material.connectionId,
185 payloadJson,288 ciphertext: material.ciphertext,
186 updatedAt: now,289 keyVersion: material.keyVersion,
290 createdAt: material.createdAt,
291 updatedAt: material.updatedAt,
187 },292 },
188 });293 });
189 });294 });
@@ -196,57 +301,73 @@ export const createAuthRowOperations = ({ · 6 unmodified lines
196 await writeLocked(async () => {301 await writeLocked(async () => {
197 await adapter.transaction(async (transaction) => {302 await adapter.transaction(async (transaction) => {
198 const transactionContext = createDrizzleContext(transaction);303 const transactionContext = createDrizzleContext(transaction);
199 const existing = await transactionContext.db304 await transactionContext.db
200 .select({305 .delete(transactionContext.tables.authMaterialsTable)
201 id: transactionContext.tables.authMaterialsTable.id,306 .where(eq(transactionContext.tables.authMaterialsTable.connectionId, connectionId));
202 payloadJson: transactionContext.tables.authMaterialsTable.payloadJson,
203 })
204 .from(transactionContext.tables.authMaterialsTable);
205
206 for (const row of existing) {
207 const material = AuthMaterialJson.decode(row.payloadJson);
208 if (material.connectionId !== connectionId) {
209 continue;
210 }
211
212 await transactionContext.db
213 .delete(transactionContext.tables.authMaterialsTable)
214 .where(eq(transactionContext.tables.authMaterialsTable.id, row.id));
215 }
216 });307 });
217 });308 });
218 };309 };
219 310
220 const listOAuthStateRows = async (): Promise<Array<OAuthState>> => {311 const listOAuthStateRows = async (): Promise<Array<OAuthState>> => {
221 const rows = await db312 const rows = await db.select().from(tables.oauthStatesTable).orderBy(
222 .select({ payloadJson: tables.oauthStatesTable.payloadJson })313 asc(tables.oauthStatesTable.updatedAt),
223 .from(tables.oauthStatesTable)314 asc(tables.oauthStatesTable.id),
224 .orderBy(asc(tables.oauthStatesTable.updatedAt), asc(tables.oauthStatesTable.id));315 );
225 316
226 return rows.map((row) => OAuthStateJson.decode(row.payloadJson));317 return rows.map(toOAuthState);
227 };318 };
228 319
229 const upsertOAuthStateRow = async (state: OAuthState): Promise<void> => {320 const upsertOAuthStateRow = async (state: OAuthState): Promise<void> => {
230 await writeLocked(async () => {321 await writeLocked(async () => {
231 await adapter.transaction(async (transaction) => {322 await adapter.transaction(async (transaction) => {
232 const transactionContext = createDrizzleContext(transaction);323 const transactionContext = createDrizzleContext(transaction);
233 const payloadJson = OAuthStateJson.encode(state);
234 const now = Date.now();
235 324
236 await transactionContext.db325 await transactionContext.db
237 .insert(transactionContext.tables.oauthStatesTable)326 .insert(transactionContext.tables.oauthStatesTable)
238 .values({327 .values({
239 id: state.id,328 id: state.id,
240 workspaceId: null,329 connectionId: state.connectionId,
241 payloadJson,330 accessTokenCiphertext: state.accessTokenCiphertext,
242 updatedAt: now,331 refreshTokenCiphertext: state.refreshTokenCiphertext,
332 keyVersion: state.keyVersion,
333 expiresAt: state.expiresAt,
334 scope: state.scope,
335 tokenType: state.tokenType,
336 issuer: state.issuer,
337 refreshConfigJson: state.refreshConfigJson,
338 tokenVersion: state.tokenVersion,
339 leaseHolder: state.leaseHolder,
340 leaseExpiresAt: state.leaseExpiresAt,
341 leaseFence: state.leaseFence,
342 lastRefreshAt: state.lastRefreshAt,
343 lastRefreshErrorClass: state.lastRefreshErrorClass,
344 lastRefreshError: state.lastRefreshError,
345 reauthRequiredAt: state.reauthRequiredAt,
346 createdAt: state.createdAt,
347 updatedAt: state.updatedAt,
243 })348 })
244 .onConflictDoUpdate({349 .onConflictDoUpdate({
245 target: transactionContext.tables.oauthStatesTable.id,350 target: transactionContext.tables.oauthStatesTable.id,
246 set: {351 set: {
247 workspaceId: null,352 connectionId: state.connectionId,
248 payloadJson,353 accessTokenCiphertext: state.accessTokenCiphertext,
249 updatedAt: now,354 refreshTokenCiphertext: state.refreshTokenCiphertext,
355 keyVersion: state.keyVersion,
356 expiresAt: state.expiresAt,
357 scope: state.scope,
358 tokenType: state.tokenType,
359 issuer: state.issuer,
360 refreshConfigJson: state.refreshConfigJson,
361 tokenVersion: state.tokenVersion,
362 leaseHolder: state.leaseHolder,
363 leaseExpiresAt: state.leaseExpiresAt,
364 leaseFence: state.leaseFence,
365 lastRefreshAt: state.lastRefreshAt,
366 lastRefreshErrorClass: state.lastRefreshErrorClass,
367 lastRefreshError: state.lastRefreshError,
368 reauthRequiredAt: state.reauthRequiredAt,
369 createdAt: state.createdAt,
370 updatedAt: state.updatedAt,
250 },371 },
251 });372 });
252 });373 });
@@ -259,23 +380,9 @@ export const createAuthRowOperations = ({ · 6 unmodified lines
259 await writeLocked(async () => {380 await writeLocked(async () => {
260 await adapter.transaction(async (transaction) => {381 await adapter.transaction(async (transaction) => {
261 const transactionContext = createDrizzleContext(transaction);382 const transactionContext = createDrizzleContext(transaction);
262 const existing = await transactionContext.db383 await transactionContext.db
263 .select({384 .delete(transactionContext.tables.oauthStatesTable)
264 id: transactionContext.tables.oauthStatesTable.id,385 .where(eq(transactionContext.tables.oauthStatesTable.connectionId, connectionId));
265 payloadJson: transactionContext.tables.oauthStatesTable.payloadJson,
266 })
267 .from(transactionContext.tables.oauthStatesTable);
268
269 for (const row of existing) {
270 const state = OAuthStateJson.decode(row.payloadJson);
271 if (state.connectionId !== connectionId) {
272 continue;
273 }
274
275 await transactionContext.db
276 .delete(transactionContext.tables.oauthStatesTable)
277 .where(eq(transactionContext.tables.oauthStatesTable.id, row.id));
278 }
279 });386 });
280 });387 });
281 };388 };
packages/persistence-sql/src/row-operations-core.ts+252−125
@@ -7,18 +7,14 @@ import { · 6 unmodified lines
7 type StorageInstance,7 type StorageInstance,
8 type Workspace,8 type Workspace,
9} from "@executor-v2/schema";9} from "@executor-v2/schema";
10import { asc, eq } from "drizzle-orm";10import { asc, desc, eq } from "drizzle-orm";
11 11
12import {12import {
13 ApprovalJson,13 createDrizzleContext,
14 OrganizationJson,14 type DrizzleDb,
15 OrganizationMembershipJson,15 type DrizzleTables,
16 PolicyJson,16 type SqlAdapter,
17 ProfileJson,17} from "./sql-internals";
18 StorageInstanceJson,
19 WorkspaceJson,
20} from "./persistence-codecs";
21import { createDrizzleContext, type DrizzleDb, type DrizzleTables, type SqlAdapter } from "./sql-internals";
22 18
23type WriteLocked = <A>(run: () => Promise<A>) => Promise<A>;19type WriteLocked = <A>(run: () => Promise<A>) => Promise<A>;
24 20
@@ -29,6 +25,103 @@ type CoreOperationsInput = { · 4 unmodified lines
29 writeLocked: WriteLocked;25 writeLocked: WriteLocked;
30};26};
31 27
28const toOrganization = (
29 row: DrizzleTables["organizationsTable"]["$inferSelect"],
30): Organization => ({
31 id: row.id as Organization["id"],
32 slug: row.slug,
33 name: row.name,
34 status: row.status as Organization["status"],
35 createdByAccountId: row.createdByAccountId as Organization["createdByAccountId"],
36 createdAt: row.createdAt,
37 updatedAt: row.updatedAt,
38});
39
40const toOrganizationMembership = (
41 row: DrizzleTables["organizationMembershipsTable"]["$inferSelect"],
42): OrganizationMembership => ({
43 id: row.id as OrganizationMembership["id"],
44 organizationId: row.organizationId as OrganizationMembership["organizationId"],
45 accountId: row.accountId as OrganizationMembership["accountId"],
46 role: row.role as OrganizationMembership["role"],
47 status: row.status as OrganizationMembership["status"],
48 billable: row.billable,
49 invitedByAccountId:
50 row.invitedByAccountId as OrganizationMembership["invitedByAccountId"],
51 joinedAt: row.joinedAt,
52 createdAt: row.createdAt,
53 updatedAt: row.updatedAt,
54});
55
56const toWorkspace = (
57 row: DrizzleTables["workspacesTable"]["$inferSelect"],
58): Workspace => ({
59 id: row.id as Workspace["id"],
60 organizationId: row.organizationId as Workspace["organizationId"],
61 name: row.name,
62 createdByAccountId: row.createdByAccountId as Workspace["createdByAccountId"],
63 createdAt: row.createdAt,
64 updatedAt: row.updatedAt,
65});
66
67const toStorageInstance = (
68 row: DrizzleTables["storageInstancesTable"]["$inferSelect"],
69): StorageInstance => ({
70 id: row.id as StorageInstance["id"],
71 scopeType: row.scopeType as StorageInstance["scopeType"],
72 durability: row.durability as StorageInstance["durability"],
73 status: row.status as StorageInstance["status"],
74 provider: row.provider as StorageInstance["provider"],
75 backendKey: row.backendKey,
76 organizationId: row.organizationId as StorageInstance["organizationId"],
77 workspaceId: row.workspaceId as StorageInstance["workspaceId"],
78 accountId: row.accountId as StorageInstance["accountId"],
79 createdByAccountId: row.createdByAccountId as StorageInstance["createdByAccountId"],
80 purpose: row.purpose,
81 sizeBytes: row.sizeBytes,
82 fileCount: row.fileCount,
83 createdAt: row.createdAt,
84 updatedAt: row.updatedAt,
85 lastSeenAt: row.lastSeenAt,
86 closedAt: row.closedAt,
87 expiresAt: row.expiresAt,
88});
89
90const toPolicy = (
91 row: DrizzleTables["policiesTable"]["$inferSelect"],
92): Policy => ({
93 id: row.id as Policy["id"],
94 workspaceId: row.workspaceId as Policy["workspaceId"],
95 toolPathPattern: row.toolPathPattern,
96 decision: row.decision as Policy["decision"],
97 createdAt: row.createdAt,
98 updatedAt: row.updatedAt,
99});
100
101const toApproval = (
102 row: DrizzleTables["approvalsTable"]["$inferSelect"],
103): Approval => ({
104 id: row.id as Approval["id"],
105 workspaceId: row.workspaceId as Approval["workspaceId"],
106 taskRunId: row.taskRunId as Approval["taskRunId"],
107 callId: row.callId,
108 toolPath: row.toolPath,
109 status: row.status as Approval["status"],
110 inputPreviewJson: row.inputPreviewJson,
111 reason: row.reason,
112 requestedAt: row.requestedAt,
113 resolvedAt: row.resolvedAt,
114});
115
116const toProfile = (row: DrizzleTables["profileTable"]["$inferSelect"]): Profile => ({
117 id: row.id as Profile["id"],
118 defaultWorkspaceId: row.defaultWorkspaceId as Profile["defaultWorkspaceId"],
119 displayName: row.displayName,
120 runtimeMode: row.runtimeMode as Profile["runtimeMode"],
121 createdAt: row.createdAt,
122 updatedAt: row.updatedAt,
123});
124
32export const createCoreRowOperations = ({125export const createCoreRowOperations = ({
33 adapter,126 adapter,
34 db,127 db,
@@ -36,38 +129,39 @@ export const createCoreRowOperations = ({ · 1 unmodified line
36 writeLocked,129 writeLocked,
37}: CoreOperationsInput) => {130}: CoreOperationsInput) => {
38 const listOrganizationsRows = async (): Promise<Array<Organization>> => {131 const listOrganizationsRows = async (): Promise<Array<Organization>> => {
39 const rows = await db132 const rows = await db.select().from(tables.organizationsTable).orderBy(
40 .select({ payloadJson: tables.organizationsTable.payloadJson })133 asc(tables.organizationsTable.updatedAt),
41 .from(tables.organizationsTable)134 asc(tables.organizationsTable.id),
42 .orderBy(135 );
43 asc(tables.organizationsTable.updatedAt),136
44 asc(tables.organizationsTable.id),137 return rows.map(toOrganization);
45 );
46
47 return rows.map((row) => OrganizationJson.decode(row.payloadJson));
48 };138 };
49 139
50 const upsertOrganizationRow = async (140 const upsertOrganizationRow = async (organization: Organization): Promise<void> => {
51 organization: Organization,
52 ): Promise<void> => {
53 await writeLocked(async () => {141 await writeLocked(async () => {
54 await adapter.transaction(async (transaction) => {142 await adapter.transaction(async (transaction) => {
55 const transactionContext = createDrizzleContext(transaction);143 const transactionContext = createDrizzleContext(transaction);
56 const payloadJson = OrganizationJson.encode(organization);
57 const now = Date.now();
58 144
59 await transactionContext.db145 await transactionContext.db
60 .insert(transactionContext.tables.organizationsTable)146 .insert(transactionContext.tables.organizationsTable)
61 .values({147 .values({
62 id: organization.id,148 id: organization.id,
63 payloadJson,149 slug: organization.slug,
64 updatedAt: now,150 name: organization.name,
151 status: organization.status,
152 createdByAccountId: organization.createdByAccountId,
153 createdAt: organization.createdAt,
154 updatedAt: organization.updatedAt,
65 })155 })
66 .onConflictDoUpdate({156 .onConflictDoUpdate({
67 target: transactionContext.tables.organizationsTable.id,157 target: transactionContext.tables.organizationsTable.id,
68 set: {158 set: {
69 payloadJson,159 slug: organization.slug,
70 updatedAt: now,160 name: organization.name,
161 status: organization.status,
162 createdByAccountId: organization.createdByAccountId,
163 createdAt: organization.createdAt,
164 updatedAt: organization.updatedAt,
71 },165 },
72 });166 });
73 });167 });
@@ -77,15 +171,12 @@ export const createCoreRowOperations = ({ · 3 unmodified lines
77 const listOrganizationMembershipRows = async (): Promise<171 const listOrganizationMembershipRows = async (): Promise<
78 Array<OrganizationMembership>172 Array<OrganizationMembership>
79 > => {173 > => {
80 const rows = await db174 const rows = await db.select().from(tables.organizationMembershipsTable).orderBy(
81 .select({ payloadJson: tables.organizationMembershipsTable.payloadJson })175 asc(tables.organizationMembershipsTable.updatedAt),
82 .from(tables.organizationMembershipsTable)176 asc(tables.organizationMembershipsTable.id),
83 .orderBy(177 );
84 asc(tables.organizationMembershipsTable.updatedAt),178
85 asc(tables.organizationMembershipsTable.id),179 return rows.map(toOrganizationMembership);
86 );
87
88 return rows.map((row) => OrganizationMembershipJson.decode(row.payloadJson));
89 };180 };
90 181
91 const upsertOrganizationMembershipRow = async (182 const upsertOrganizationMembershipRow = async (
@@ -94,23 +185,33 @@ export const createCoreRowOperations = ({ · 2 unmodified lines
94 await writeLocked(async () => {185 await writeLocked(async () => {
95 await adapter.transaction(async (transaction) => {186 await adapter.transaction(async (transaction) => {
96 const transactionContext = createDrizzleContext(transaction);187 const transactionContext = createDrizzleContext(transaction);
97 const payloadJson = OrganizationMembershipJson.encode(membership);
98 const now = Date.now();
99 188
100 await transactionContext.db189 await transactionContext.db
101 .insert(transactionContext.tables.organizationMembershipsTable)190 .insert(transactionContext.tables.organizationMembershipsTable)
102 .values({191 .values({
103 id: membership.id,192 id: membership.id,
104 workspaceId: null,193 organizationId: membership.organizationId,
105 payloadJson,194 accountId: membership.accountId,
106 updatedAt: now,195 role: membership.role,
196 status: membership.status,
197 billable: membership.billable,
198 invitedByAccountId: membership.invitedByAccountId,
199 joinedAt: membership.joinedAt,
200 createdAt: membership.createdAt,
201 updatedAt: membership.updatedAt,
107 })202 })
108 .onConflictDoUpdate({203 .onConflictDoUpdate({
109 target: transactionContext.tables.organizationMembershipsTable.id,204 target: transactionContext.tables.organizationMembershipsTable.id,
110 set: {205 set: {
111 workspaceId: null,206 organizationId: membership.organizationId,
112 payloadJson,207 accountId: membership.accountId,
113 updatedAt: now,208 role: membership.role,
209 status: membership.status,
210 billable: membership.billable,
211 invitedByAccountId: membership.invitedByAccountId,
212 joinedAt: membership.joinedAt,
213 createdAt: membership.createdAt,
214 updatedAt: membership.updatedAt,
114 },215 },
115 });216 });
116 });217 });
@@ -118,38 +219,37 @@ export const createCoreRowOperations = ({ · 1 unmodified line
118 };219 };
119 220
120 const listWorkspaceRows = async (): Promise<Array<Workspace>> => {221 const listWorkspaceRows = async (): Promise<Array<Workspace>> => {
121 const rows = await db222 const rows = await db.select().from(tables.workspacesTable).orderBy(
122 .select({ payloadJson: tables.workspacesTable.payloadJson })223 asc(tables.workspacesTable.updatedAt),
123 .from(tables.workspacesTable)224 asc(tables.workspacesTable.id),
124 .orderBy(225 );
125 asc(tables.workspacesTable.updatedAt),226
126 asc(tables.workspacesTable.id),227 return rows.map(toWorkspace);
127 );
128
129 return rows.map((row) => WorkspaceJson.decode(row.payloadJson));
130 };228 };
131 229
132 const upsertWorkspaceRow = async (workspace: Workspace): Promise<void> => {230 const upsertWorkspaceRow = async (workspace: Workspace): Promise<void> => {
133 await writeLocked(async () => {231 await writeLocked(async () => {
134 await adapter.transaction(async (transaction) => {232 await adapter.transaction(async (transaction) => {
135 const transactionContext = createDrizzleContext(transaction);233 const transactionContext = createDrizzleContext(transaction);
136 const payloadJson = WorkspaceJson.encode(workspace);
137 const now = Date.now();
138 234
139 await transactionContext.db235 await transactionContext.db
140 .insert(transactionContext.tables.workspacesTable)236 .insert(transactionContext.tables.workspacesTable)
141 .values({237 .values({
142 id: workspace.id,238 id: workspace.id,
143 workspaceId: workspace.organizationId,239 organizationId: workspace.organizationId,
144 payloadJson,240 name: workspace.name,
145 updatedAt: now,241 createdByAccountId: workspace.createdByAccountId,
242 createdAt: workspace.createdAt,
243 updatedAt: workspace.updatedAt,
146 })244 })
147 .onConflictDoUpdate({245 .onConflictDoUpdate({
148 target: transactionContext.tables.workspacesTable.id,246 target: transactionContext.tables.workspacesTable.id,
149 set: {247 set: {
150 workspaceId: workspace.organizationId,248 organizationId: workspace.organizationId,
151 payloadJson,249 name: workspace.name,
152 updatedAt: now,250 createdByAccountId: workspace.createdByAccountId,
251 createdAt: workspace.createdAt,
252 updatedAt: workspace.updatedAt,
153 },253 },
154 });254 });
155 });255 });
@@ -157,15 +257,12 @@ export const createCoreRowOperations = ({ · 1 unmodified line
157 };257 };
158 258
159 const listStorageInstanceRows = async (): Promise<Array<StorageInstance>> => {259 const listStorageInstanceRows = async (): Promise<Array<StorageInstance>> => {
160 const rows = await db260 const rows = await db.select().from(tables.storageInstancesTable).orderBy(
161 .select({ payloadJson: tables.storageInstancesTable.payloadJson })261 asc(tables.storageInstancesTable.updatedAt),
162 .from(tables.storageInstancesTable)262 asc(tables.storageInstancesTable.id),
163 .orderBy(263 );
164 asc(tables.storageInstancesTable.updatedAt),264
165 asc(tables.storageInstancesTable.id),265 return rows.map(toStorageInstance);
166 );
167
168 return rows.map((row) => StorageInstanceJson.decode(row.payloadJson));
169 };266 };
170 267
171 const upsertStorageInstanceRow = async (268 const upsertStorageInstanceRow = async (
@@ -174,23 +271,49 @@ export const createCoreRowOperations = ({ · 2 unmodified lines
174 await writeLocked(async () => {271 await writeLocked(async () => {
175 await adapter.transaction(async (transaction) => {272 await adapter.transaction(async (transaction) => {
176 const transactionContext = createDrizzleContext(transaction);273 const transactionContext = createDrizzleContext(transaction);
177 const payloadJson = StorageInstanceJson.encode(storageInstance);
178 const now = Date.now();
179 274
180 await transactionContext.db275 await transactionContext.db
181 .insert(transactionContext.tables.storageInstancesTable)276 .insert(transactionContext.tables.storageInstancesTable)
182 .values({277 .values({
183 id: storageInstance.id,278 id: storageInstance.id,
279 scopeType: storageInstance.scopeType,
280 durability: storageInstance.durability,
281 status: storageInstance.status,
282 provider: storageInstance.provider,
283 backendKey: storageInstance.backendKey,
284 organizationId: storageInstance.organizationId,
184 workspaceId: storageInstance.workspaceId,285 workspaceId: storageInstance.workspaceId,
185 payloadJson,286 accountId: storageInstance.accountId,
186 updatedAt: now,287 createdByAccountId: storageInstance.createdByAccountId,
288 purpose: storageInstance.purpose,
289 sizeBytes: storageInstance.sizeBytes,
290 fileCount: storageInstance.fileCount,
291 createdAt: storageInstance.createdAt,
292 updatedAt: storageInstance.updatedAt,
293 lastSeenAt: storageInstance.lastSeenAt,
294 closedAt: storageInstance.closedAt,
295 expiresAt: storageInstance.expiresAt,
187 })296 })
188 .onConflictDoUpdate({297 .onConflictDoUpdate({
189 target: transactionContext.tables.storageInstancesTable.id,298 target: transactionContext.tables.storageInstancesTable.id,
190 set: {299 set: {
300 scopeType: storageInstance.scopeType,
301 durability: storageInstance.durability,
302 status: storageInstance.status,
303 provider: storageInstance.provider,
304 backendKey: storageInstance.backendKey,
305 organizationId: storageInstance.organizationId,
191 workspaceId: storageInstance.workspaceId,306 workspaceId: storageInstance.workspaceId,
192 payloadJson,307 accountId: storageInstance.accountId,
193 updatedAt: now,308 createdByAccountId: storageInstance.createdByAccountId,
309 purpose: storageInstance.purpose,
310 sizeBytes: storageInstance.sizeBytes,
311 fileCount: storageInstance.fileCount,
312 createdAt: storageInstance.createdAt,
313 updatedAt: storageInstance.updatedAt,
314 lastSeenAt: storageInstance.lastSeenAt,
315 closedAt: storageInstance.closedAt,
316 expiresAt: storageInstance.expiresAt,
194 },317 },
195 });318 });
196 });319 });
@@ -222,43 +345,45 @@ export const createCoreRowOperations = ({ · 25 unmodified lines
222 );345 );
223 346
224 const listPolicyRows = async (): Promise<Array<Policy>> => {347 const listPolicyRows = async (): Promise<Array<Policy>> => {
225 const rows = await db348 const rows = await db.select().from(tables.policiesTable).orderBy(
226 .select({ payloadJson: tables.policiesTable.payloadJson })349 asc(tables.policiesTable.updatedAt),
227 .from(tables.policiesTable)350 asc(tables.policiesTable.id),
228 .orderBy(asc(tables.policiesTable.updatedAt), asc(tables.policiesTable.id));351 );
229 352
230 return rows.map((row) => PolicyJson.decode(row.payloadJson));353 return rows.map(toPolicy);
231 };354 };
232 355
233 const upsertPolicyRow = async (policy: Policy): Promise<void> => {356 const upsertPolicyRow = async (policy: Policy): Promise<void> => {
234 await writeLocked(async () => {357 await writeLocked(async () => {
235 await adapter.transaction(async (transaction) => {358 await adapter.transaction(async (transaction) => {
236 const transactionContext = createDrizzleContext(transaction);359 const transactionContext = createDrizzleContext(transaction);
237 const payloadJson = PolicyJson.encode(policy);
238 const now = Date.now();
239 360
240 await transactionContext.db361 await transactionContext.db
241 .insert(transactionContext.tables.policiesTable)362 .insert(transactionContext.tables.policiesTable)
242 .values({363 .values({
243 id: policy.id,364 id: policy.id,
244 workspaceId: policy.workspaceId,365 workspaceId: policy.workspaceId,
245 payloadJson,366 toolPathPattern: policy.toolPathPattern,
246 updatedAt: now,367 decision: policy.decision,
368 createdAt: policy.createdAt,
369 updatedAt: policy.updatedAt,
247 })370 })
248 .onConflictDoUpdate({371 .onConflictDoUpdate({
249 target: transactionContext.tables.policiesTable.id,372 target: transactionContext.tables.policiesTable.id,
250 set: {373 set: {
251 workspaceId: policy.workspaceId,374 workspaceId: policy.workspaceId,
252 payloadJson,375 toolPathPattern: policy.toolPathPattern,
253 updatedAt: now,376 decision: policy.decision,
377 createdAt: policy.createdAt,
378 updatedAt: policy.updatedAt,
254 },379 },
255 });380 });
256 });381 });
257 });382 });
258 };383 };
259 384
260 const removePolicyRowById = async (policyId: Policy["id"]): Promise<boolean> => {385 const removePolicyRowById = async (policyId: Policy["id"]): Promise<boolean> =>
261 return writeLocked(async () =>386 writeLocked(async () =>
262 adapter.transaction(async (transaction) => {387 adapter.transaction(async (transaction) => {
263 const transactionContext = createDrizzleContext(transaction);388 const transactionContext = createDrizzleContext(transaction);
264 389
@@ -279,38 +404,47 @@ export const createCoreRowOperations = ({ · 14 unmodified lines
279 return true;404 return true;
280 })405 })
281 );406 );
282 };
283 407
284 const listApprovalRows = async (): Promise<Array<Approval>> => {408 const listApprovalRows = async (): Promise<Array<Approval>> => {
285 const rows = await db409 const rows = await db.select().from(tables.approvalsTable).orderBy(
286 .select({ payloadJson: tables.approvalsTable.payloadJson })410 asc(tables.approvalsTable.requestedAt),
287 .from(tables.approvalsTable)411 asc(tables.approvalsTable.id),
288 .orderBy(asc(tables.approvalsTable.updatedAt), asc(tables.approvalsTable.id));412 );
289 413
290 return rows.map((row) => ApprovalJson.decode(row.payloadJson));414 return rows.map(toApproval);
291 };415 };
292 416
293 const upsertApprovalRow = async (approval: Approval): Promise<void> => {417 const upsertApprovalRow = async (approval: Approval): Promise<void> => {
294 await writeLocked(async () => {418 await writeLocked(async () => {
295 await adapter.transaction(async (transaction) => {419 await adapter.transaction(async (transaction) => {
296 const transactionContext = createDrizzleContext(transaction);420 const transactionContext = createDrizzleContext(transaction);
297 const payloadJson = ApprovalJson.encode(approval);
298 const now = Date.now();
299 421
300 await transactionContext.db422 await transactionContext.db
301 .insert(transactionContext.tables.approvalsTable)423 .insert(transactionContext.tables.approvalsTable)
302 .values({424 .values({
303 id: approval.id,425 id: approval.id,
304 workspaceId: approval.workspaceId,426 workspaceId: approval.workspaceId,
305 payloadJson,427 taskRunId: approval.taskRunId,
306 updatedAt: now,428 callId: approval.callId,
429 toolPath: approval.toolPath,
430 status: approval.status,
431 inputPreviewJson: approval.inputPreviewJson,
432 reason: approval.reason,
433 requestedAt: approval.requestedAt,
434 resolvedAt: approval.resolvedAt,
307 })435 })
308 .onConflictDoUpdate({436 .onConflictDoUpdate({
309 target: transactionContext.tables.approvalsTable.id,437 target: transactionContext.tables.approvalsTable.id,
310 set: {438 set: {
311 workspaceId: approval.workspaceId,439 workspaceId: approval.workspaceId,
312 payloadJson,440 taskRunId: approval.taskRunId,
313 updatedAt: now,441 callId: approval.callId,
442 toolPath: approval.toolPath,
443 status: approval.status,
444 inputPreviewJson: approval.inputPreviewJson,
445 reason: approval.reason,
446 requestedAt: approval.requestedAt,
447 resolvedAt: approval.resolvedAt,
314 },448 },
315 });449 });
316 });450 });
@@ -318,49 +452,42 @@ export const createCoreRowOperations = ({ · 1 unmodified line
318 };452 };
319 453
320 const getProfileRow = async (): Promise<Profile | null> => {454 const getProfileRow = async (): Promise<Profile | null> => {
321 const rows = await db455 const rows = await db.select().from(tables.profileTable).orderBy(
322 .select({ profileJson: tables.profileTable.profileJson })456 desc(tables.profileTable.updatedAt),
323 .from(tables.profileTable)457 asc(tables.profileTable.id),
324 .where(eq(tables.profileTable.id, 1))458 ).limit(1);
325 .limit(1);
326 459
327 const row = rows[0];460 const row = rows[0];
328 if (!row) {461 if (!row) {
329 return null;462 return null;
330 }463 }
331 464
332 return ProfileJson.decode(row.profileJson);465 return toProfile(row);
333 };466 };
334 467
335 const upsertProfileRow = async (profile: Profile): Promise<void> => {468 const upsertProfileRow = async (profile: Profile): Promise<void> => {
336 await writeLocked(async () => {469 await writeLocked(async () => {
337 await adapter.transaction(async (transaction) => {470 await adapter.transaction(async (transaction) => {
338 const transactionContext = createDrizzleContext(transaction);471 const transactionContext = createDrizzleContext(transaction);
339 const currentRows = await transactionContext.db
340 .select({ schemaVersion: transactionContext.tables.profileTable.schemaVersion })
341 .from(transactionContext.tables.profileTable)
342 .where(eq(transactionContext.tables.profileTable.id, 1))
343 .limit(1);
344
345 const schemaVersion = currentRows[0]?.schemaVersion ?? 1;
346 const now = Date.now();
347 const profileJson = ProfileJson.encode(profile);
348 472
349 await transactionContext.db473 await transactionContext.db
350 .insert(transactionContext.tables.profileTable)474 .insert(transactionContext.tables.profileTable)
351 .values({475 .values({
352 id: 1,476 id: profile.id,
353 schemaVersion,477 defaultWorkspaceId: profile.defaultWorkspaceId,
354 generatedAt: now,478 displayName: profile.displayName,
355 profileJson,479 runtimeMode: profile.runtimeMode,
356 updatedAt: now,480 createdAt: profile.createdAt,
481 updatedAt: profile.updatedAt,
357 })482 })
358 .onConflictDoUpdate({483 .onConflictDoUpdate({
359 target: transactionContext.tables.profileTable.id,484 target: transactionContext.tables.profileTable.id,
360 set: {485 set: {
361 profileJson,486 defaultWorkspaceId: profile.defaultWorkspaceId,
362 generatedAt: now,487 displayName: profile.displayName,
363 updatedAt: now,488 runtimeMode: profile.runtimeMode,
489 createdAt: profile.createdAt,
490 updatedAt: profile.updatedAt,
364 },491 },
365 });492 });
366 });493 });
packages/persistence-sql/src/rows-effect-api-auth.ts+116−0
@@ -0,0 +1,116 @@
1import {
2 type AuthConnection,
3 type AuthMaterial,
4 type OAuthState,
5 type SourceAuthBinding,
6} from "@executor-v2/schema";
7
8import { tableNames } from "./schema";
9import { type SqlBackend } from "./sql-internals";
10import {
11 type RowOperations,
12 toBooleanEffect,
13 toListEffect,
14 toVoidEffect,
15} from "./rows-effect-helpers";
16
17export const createAuthRowsEffectApi = (
18 backend: SqlBackend,
19 operations: RowOperations,
20) => ({
21 authConnections: {
22 list: () =>
23 toListEffect<AuthConnection>(
24 backend,
25 "rows.authConnections.list",
26 tableNames.authConnections,
27 operations.listAuthConnectionRows,
28 ),
29 upsert: (connection: AuthConnection) =>
30 toVoidEffect(
31 backend,
32 "rows.authConnections.upsert",
33 tableNames.authConnections,
34 () => operations.upsertAuthConnectionRow(connection),
35 ),
36 removeById: (connectionId: AuthConnection["id"]) =>
37 toBooleanEffect(
38 backend,
39 "rows.authConnections.remove",
40 tableNames.authConnections,
41 () => operations.removeAuthConnectionRowById(connectionId),
42 ),
43 },
44
45 sourceAuthBindings: {
46 list: () =>
47 toListEffect<SourceAuthBinding>(
48 backend,
49 "rows.sourceAuthBindings.list",
50 tableNames.sourceAuthBindings,
51 operations.listSourceAuthBindingRows,
52 ),
53 upsert: (binding: SourceAuthBinding) =>
54 toVoidEffect(
55 backend,
56 "rows.sourceAuthBindings.upsert",
57 tableNames.sourceAuthBindings,
58 () => operations.upsertSourceAuthBindingRow(binding),
59 ),
60 removeById: (bindingId: SourceAuthBinding["id"]) =>
61 toBooleanEffect(
62 backend,
63 "rows.sourceAuthBindings.remove",
64 tableNames.sourceAuthBindings,
65 () => operations.removeSourceAuthBindingRowById(bindingId),
66 ),
67 },
68
69 authMaterials: {
70 list: () =>
71 toListEffect<AuthMaterial>(
72 backend,
73 "rows.authMaterials.list",
74 tableNames.authMaterials,
75 operations.listAuthMaterialRows,
76 ),
77 upsert: (material: AuthMaterial) =>
78 toVoidEffect(
79 backend,
80 "rows.authMaterials.upsert",
81 tableNames.authMaterials,
82 () => operations.upsertAuthMaterialRow(material),
83 ),
84 removeByConnectionId: (connectionId: AuthMaterial["connectionId"]) =>
85 toVoidEffect(
86 backend,
87 "rows.authMaterials.remove_by_connection",
88 tableNames.authMaterials,
89 () => operations.removeAuthMaterialRowsByConnectionId(connectionId),
90 ),
91 },
92
93 oauthStates: {
94 list: () =>
95 toListEffect<OAuthState>(
96 backend,
97 "rows.oauthStates.list",
98 tableNames.oauthStates,
99 operations.listOAuthStateRows,
100 ),
101 upsert: (state: OAuthState) =>
102 toVoidEffect(
103 backend,
104 "rows.oauthStates.upsert",
105 tableNames.oauthStates,
106 () => operations.upsertOAuthStateRow(state),
107 ),
108 removeByConnectionId: (connectionId: OAuthState["connectionId"]) =>
109 toVoidEffect(
110 backend,
111 "rows.oauthStates.remove_by_connection",
112 tableNames.oauthStates,
113 () => operations.removeOAuthStateRowsByConnectionId(connectionId),
114 ),
115 },
116});
packages/persistence-sql/src/rows-effect-api-core.ts+157−0
@@ -0,0 +1,157 @@
1import {
2 type Approval,
3 type Organization,
4 type OrganizationMembership,
5 type Policy,
6 type Profile,
7 type StorageInstance,
8 type Workspace,
9} from "@executor-v2/schema";
10
11import { tableNames } from "./schema";
12import { type SqlBackend } from "./sql-internals";
13import {
14 type RowOperations,
15 toBooleanEffect,
16 toListEffect,
17 toOptionEffect,
18 toVoidEffect,
19} from "./rows-effect-helpers";
20
21export const createCoreRowsEffectApi = (
22 backend: SqlBackend,
23 operations: RowOperations,
24) => ({
25 profile: {
26 get: () =>
27 toOptionEffect<Profile>(
28 backend,
29 "rows.profile.get",
30 tableNames.profile,
31 operations.getProfileRow,
32 ),
33 upsert: (profile: Profile) =>
34 toVoidEffect(
35 backend,
36 "rows.profile.upsert",
37 tableNames.profile,
38 () => operations.upsertProfileRow(profile),
39 ),
40 },
41
42 organizations: {
43 list: () =>
44 toListEffect<Organization>(
45 backend,
46 "rows.organizations.list",
47 tableNames.organizations,
48 operations.listOrganizationsRows,
49 ),
50 upsert: (organization: Organization) =>
51 toVoidEffect(
52 backend,
53 "rows.organizations.upsert",
54 tableNames.organizations,
55 () => operations.upsertOrganizationRow(organization),
56 ),
57 },
58
59 organizationMemberships: {
60 list: () =>
61 toListEffect<OrganizationMembership>(
62 backend,
63 "rows.organizationMemberships.list",
64 tableNames.organizationMemberships,
65 operations.listOrganizationMembershipRows,
66 ),
67 upsert: (membership: OrganizationMembership) =>
68 toVoidEffect(
69 backend,
70 "rows.organizationMemberships.upsert",
71 tableNames.organizationMemberships,
72 () => operations.upsertOrganizationMembershipRow(membership),
73 ),
74 },
75
76 workspaces: {
77 list: () =>
78 toListEffect<Workspace>(
79 backend,
80 "rows.workspaces.list",
81 tableNames.workspaces,
82 operations.listWorkspaceRows,
83 ),
84 upsert: (workspace: Workspace) =>
85 toVoidEffect(
86 backend,
87 "rows.workspaces.upsert",
88 tableNames.workspaces,
89 () => operations.upsertWorkspaceRow(workspace),
90 ),
91 },
92
93 storageInstances: {
94 list: () =>
95 toListEffect<StorageInstance>(
96 backend,
97 "rows.storageInstances.list",
98 tableNames.storageInstances,
99 operations.listStorageInstanceRows,
100 ),
101 upsert: (storageInstance: StorageInstance) =>
102 toVoidEffect(
103 backend,
104 "rows.storageInstances.upsert",
105 tableNames.storageInstances,
106 () => operations.upsertStorageInstanceRow(storageInstance),
107 ),
108 removeById: (storageInstanceId: StorageInstance["id"]) =>
109 toBooleanEffect(
110 backend,
111 "rows.storageInstances.remove",
112 tableNames.storageInstances,
113 () => operations.removeStorageInstanceRowById(storageInstanceId),
114 ),
115 },
116
117 policies: {
118 list: () =>
119 toListEffect<Policy>(
120 backend,
121 "rows.policies.list",
122 tableNames.policies,
123 operations.listPolicyRows,
124 ),
125 upsert: (policy: Policy) =>
126 toVoidEffect(
127 backend,
128 "rows.policies.upsert",
129 tableNames.policies,
130 () => operations.upsertPolicyRow(policy),
131 ),
132 removeById: (policyId: Policy["id"]) =>
133 toBooleanEffect(
134 backend,
135 "rows.policies.remove",
136 tableNames.policies,
137 () => operations.removePolicyRowById(policyId),
138 ),
139 },
140
141 approvals: {
142 list: () =>
143 toListEffect<Approval>(
144 backend,
145 "rows.approvals.list",
146 tableNames.approvals,
147 operations.listApprovalRows,
148 ),
149 upsert: (approval: Approval) =>
150 toVoidEffect(
151 backend,
152 "rows.approvals.upsert",
153 tableNames.approvals,
154 () => operations.upsertApprovalRow(approval),
155 ),
156 },
157});
packages/persistence-sql/src/rows-effect-api.ts+5−296
@@ -1,303 +1,12 @@
1import {1import { createAuthRowsEffectApi } from "./rows-effect-api-auth";
2 type Approval,2import { createCoreRowsEffectApi } from "./rows-effect-api-core";
3 type AuthConnection,3import { type RowOperations } from "./rows-effect-helpers";
4 type AuthMaterial,
5 type OAuthState,
6 type Organization,
7 type OrganizationMembership,
8 type Policy,
9 type Profile,
10 type SourceAuthBinding,
11 type StorageInstance,
12 type Workspace,
13} from "@executor-v2/schema";
14import * as Effect from "effect/Effect";
15import * as Option from "effect/Option";
16
17import { toRowStoreError } from "./persistence-errors";
18import { createRowOperations } from "./row-operations";
19import { tableNames } from "./schema";
20import { type SqlBackend } from "./sql-internals";4import { type SqlBackend } from "./sql-internals";
21 5
22type RowOperations = ReturnType<typeof createRowOperations>;
23
24const toListEffect = <A>(
25 backend: SqlBackend,
26 operation: string,
27 location: string,
28 run: () => Promise<ReadonlyArray<A>>,
29) =>
30 Effect.tryPromise({
31 try: run,
32 catch: (cause) => toRowStoreError(backend, operation, location, cause),
33 });
34
35const toVoidEffect = (
36 backend: SqlBackend,
37 operation: string,
38 location: string,
39 run: () => Promise<void>,
40) =>
41 Effect.tryPromise({
42 try: run,
43 catch: (cause) => toRowStoreError(backend, operation, location, cause),
44 });
45
46const toBooleanEffect = (
47 backend: SqlBackend,
48 operation: string,
49 location: string,
50 run: () => Promise<boolean>,
51) =>
52 Effect.tryPromise({
53 try: run,
54 catch: (cause) => toRowStoreError(backend, operation, location, cause),
55 });
56
57const toOptionEffect = <A>(
58 backend: SqlBackend,
59 operation: string,
60 location: string,
61 run: () => Promise<A | null>,
62) =>
63 Effect.tryPromise({
64 try: async () => {
65 const value = await run();
66 return value === null ? Option.none<A>() : Option.some(value);
67 },
68 catch: (cause) => toRowStoreError(backend, operation, location, cause),
69 });
70
71export const createRowsEffectApi = (6export const createRowsEffectApi = (
72 backend: SqlBackend,7 backend: SqlBackend,
73 operations: RowOperations,8 operations: RowOperations,
74) => ({9) => ({
75 profile: {10 ...createCoreRowsEffectApi(backend, operations),
76 get: () =>11 ...createAuthRowsEffectApi(backend, operations),
77 toOptionEffect<Profile>(
78 backend,
79 "rows.profile.get",
80 tableNames.profile,
81 operations.getProfileRow,
82 ),
83 upsert: (profile: Profile) =>
84 toVoidEffect(
85 backend,
86 "rows.profile.upsert",
87 tableNames.profile,
88 () => operations.upsertProfileRow(profile),
89 ),
90 },
91
92 organizations: {
93 list: () =>
94 toListEffect<Organization>(
95 backend,
96 "rows.organizations.list",
97 tableNames.organizations,
98 operations.listOrganizationsRows,
99 ),
100 upsert: (organization: Organization) =>
101 toVoidEffect(
102 backend,
103 "rows.organizations.upsert",
104 tableNames.organizations,
105 () => operations.upsertOrganizationRow(organization),
106 ),
107 },
108
109 organizationMemberships: {
110 list: () =>
111 toListEffect<OrganizationMembership>(
112 backend,
113 "rows.organizationMemberships.list",
114 tableNames.organizationMemberships,
115 operations.listOrganizationMembershipRows,
116 ),
117 upsert: (membership: OrganizationMembership) =>
118 toVoidEffect(
119 backend,
120 "rows.organizationMemberships.upsert",
121 tableNames.organizationMemberships,
122 () => operations.upsertOrganizationMembershipRow(membership),
123 ),
124 },
125
126 workspaces: {
127 list: () =>
128 toListEffect<Workspace>(
129 backend,
130 "rows.workspaces.list",
131 tableNames.workspaces,
132 operations.listWorkspaceRows,
133 ),
134 upsert: (workspace: Workspace) =>
135 toVoidEffect(
136 backend,
137 "rows.workspaces.upsert",
138 tableNames.workspaces,
139 () => operations.upsertWorkspaceRow(workspace),
140 ),
141 },
142
143 authConnections: {
144 list: () =>
145 toListEffect<AuthConnection>(
146 backend,
147 "rows.authConnections.list",
148 tableNames.authConnections,
149 operations.listAuthConnectionRows,
150 ),
151 upsert: (connection: AuthConnection) =>
152 toVoidEffect(
153 backend,
154 "rows.authConnections.upsert",
155 tableNames.authConnections,
156 () => operations.upsertAuthConnectionRow(connection),
157 ),
158 removeById: (connectionId: AuthConnection["id"]) =>
159 toBooleanEffect(
160 backend,
161 "rows.authConnections.remove",
162 tableNames.authConnections,
163 () => operations.removeAuthConnectionRowById(connectionId),
164 ),
165 },
166
167 sourceAuthBindings: {
168 list: () =>
169 toListEffect<SourceAuthBinding>(
170 backend,
171 "rows.sourceAuthBindings.list",
172 tableNames.sourceAuthBindings,
173 operations.listSourceAuthBindingRows,
174 ),
175 upsert: (binding: SourceAuthBinding) =>
176 toVoidEffect(
177 backend,
178 "rows.sourceAuthBindings.upsert",
179 tableNames.sourceAuthBindings,
180 () => operations.upsertSourceAuthBindingRow(binding),
181 ),
182 removeById: (bindingId: SourceAuthBinding["id"]) =>
183 toBooleanEffect(
184 backend,
185 "rows.sourceAuthBindings.remove",
186 tableNames.sourceAuthBindings,
187 () => operations.removeSourceAuthBindingRowById(bindingId),
188 ),
189 },
190
191 authMaterials: {
192 list: () =>
193 toListEffect<AuthMaterial>(
194 backend,
195 "rows.authMaterials.list",
196 tableNames.authMaterials,
197 operations.listAuthMaterialRows,
198 ),
199 upsert: (material: AuthMaterial) =>
200 toVoidEffect(
201 backend,
202 "rows.authMaterials.upsert",
203 tableNames.authMaterials,
204 () => operations.upsertAuthMaterialRow(material),
205 ),
206 removeByConnectionId: (connectionId: AuthMaterial["connectionId"]) =>
207 toVoidEffect(
208 backend,
209 "rows.authMaterials.remove_by_connection",
210 tableNames.authMaterials,
211 () => operations.removeAuthMaterialRowsByConnectionId(connectionId),
212 ),
213 },
214
215 oauthStates: {
216 list: () =>
217 toListEffect<OAuthState>(
218 backend,
219 "rows.oauthStates.list",
220 tableNames.oauthStates,
221 operations.listOAuthStateRows,
222 ),
223 upsert: (state: OAuthState) =>
224 toVoidEffect(
225 backend,
226 "rows.oauthStates.upsert",
227 tableNames.oauthStates,
228 () => operations.upsertOAuthStateRow(state),
229 ),
230 removeByConnectionId: (connectionId: OAuthState["connectionId"]) =>
231 toVoidEffect(
232 backend,
233 "rows.oauthStates.remove_by_connection",
234 tableNames.oauthStates,
235 () => operations.removeOAuthStateRowsByConnectionId(connectionId),
236 ),
237 },
238
239 storageInstances: {
240 list: () =>
241 toListEffect<StorageInstance>(
242 backend,
243 "rows.storageInstances.list",
244 tableNames.storageInstances,
245 operations.listStorageInstanceRows,
246 ),
247 upsert: (storageInstance: StorageInstance) =>
248 toVoidEffect(
249 backend,
250 "rows.storageInstances.upsert",
251 tableNames.storageInstances,
252 () => operations.upsertStorageInstanceRow(storageInstance),
253 ),
254 removeById: (storageInstanceId: StorageInstance["id"]) =>
255 toBooleanEffect(
256 backend,
257 "rows.storageInstances.remove",
258 tableNames.storageInstances,
259 () => operations.removeStorageInstanceRowById(storageInstanceId),
260 ),
261 },
262
263 policies: {
264 list: () =>
265 toListEffect<Policy>(
266 backend,
267 "rows.policies.list",
268 tableNames.policies,
269 operations.listPolicyRows,
270 ),
271 upsert: (policy: Policy) =>
272 toVoidEffect(
273 backend,
274 "rows.policies.upsert",
275 tableNames.policies,
276 () => operations.upsertPolicyRow(policy),
277 ),
278 removeById: (policyId: Policy["id"]) =>
279 toBooleanEffect(
280 backend,
281 "rows.policies.remove",
282 tableNames.policies,
283 () => operations.removePolicyRowById(policyId),
284 ),
285 },
286
287 approvals: {
288 list: () =>
289 toListEffect<Approval>(
290 backend,
291 "rows.approvals.list",
292 tableNames.approvals,
293 operations.listApprovalRows,
294 ),
295 upsert: (approval: Approval) =>
296 toVoidEffect(
297 backend,
298 "rows.approvals.upsert",
299 tableNames.approvals,
300 () => operations.upsertApprovalRow(approval),
301 ),
302 },
303});12});
packages/persistence-sql/src/rows-effect-helpers.ts+55−0
@@ -0,0 +1,55 @@
1import * as Effect from "effect/Effect";
2import * as Option from "effect/Option";
3
4import { toRowStoreError } from "./persistence-errors";
5import { createRowOperations } from "./row-operations";
6import { type SqlBackend } from "./sql-internals";
7
8export type RowOperations = ReturnType<typeof createRowOperations>;
9
10export const toListEffect = <A>(
11 backend: SqlBackend,
12 operation: string,
13 location: string,
14 run: () => Promise<ReadonlyArray<A>>,
15) =>
16 Effect.tryPromise({
17 try: run,
18 catch: (cause) => toRowStoreError(backend, operation, location, cause),
19 });
20
21export const toVoidEffect = (
22 backend: SqlBackend,
23 operation: string,
24 location: string,
25 run: () => Promise<void>,
26) =>
27 Effect.tryPromise({
28 try: run,
29 catch: (cause) => toRowStoreError(backend, operation, location, cause),
30 });
31
32export const toBooleanEffect = (
33 backend: SqlBackend,
34 operation: string,
35 location: string,
36 run: () => Promise<boolean>,
37) =>
38 Effect.tryPromise({
39 try: run,
40 catch: (cause) => toRowStoreError(backend, operation, location, cause),
41 });
42
43export const toOptionEffect = <A>(
44 backend: SqlBackend,
45 operation: string,
46 location: string,
47 run: () => Promise<A | null>,
48) =>
49 Effect.tryPromise({
50 try: async () => {
51 const value = await run();
52 return value === null ? Option.none<A>() : Option.some(value);
53 },
54 catch: (cause) => toRowStoreError(backend, operation, location, cause),
55 });
packages/persistence-sql/src/schema-pg.ts+304−0
@@ -0,0 +1,304 @@
1import {
2 bigint,
3 boolean,
4 index,
5 pgTable,
6 primaryKey,
7 text,
8 uniqueIndex,
9} from "drizzle-orm/pg-core";
10
11import { tableNames } from "./schema";
12
13export const profileTable = pgTable(tableNames.profile, {
14 id: text("id").notNull().primaryKey(),
15 defaultWorkspaceId: text("default_workspace_id"),
16 displayName: text("display_name").notNull(),
17 runtimeMode: text("runtime_mode").notNull(),
18 createdAt: bigint("created_at", { mode: "number" }).notNull(),
19 updatedAt: bigint("updated_at", { mode: "number" }).notNull(),
20});
21
22export const organizationsTable = pgTable(tableNames.organizations, {
23 id: text("id").notNull().primaryKey(),
24 slug: text("slug").notNull(),
25 name: text("name").notNull(),
26 status: text("status").notNull(),
27 createdByAccountId: text("created_by_account_id"),
28 createdAt: bigint("created_at", { mode: "number" }).notNull(),
29 updatedAt: bigint("updated_at", { mode: "number" }).notNull(),
30});
31
32export const organizationMembershipsTable = pgTable(
33 tableNames.organizationMemberships,
34 {
35 id: text("id").notNull().primaryKey(),
36 organizationId: text("organization_id").notNull(),
37 accountId: text("account_id").notNull(),
38 role: text("role").notNull(),
39 status: text("status").notNull(),
40 billable: boolean("billable").notNull(),
41 invitedByAccountId: text("invited_by_account_id"),
42 joinedAt: bigint("joined_at", { mode: "number" }),
43 createdAt: bigint("created_at", { mode: "number" }).notNull(),
44 updatedAt: bigint("updated_at", { mode: "number" }).notNull(),
45 },
46 (table) => [
47 index("organization_memberships_org_idx").on(table.organizationId),
48 index("organization_memberships_account_idx").on(table.accountId),
49 ],
50);
51
52export const workspacesTable = pgTable(
53 tableNames.workspaces,
54 {
55 id: text("id").notNull().primaryKey(),
56 organizationId: text("organization_id").notNull(),
57 name: text("name").notNull(),
58 createdByAccountId: text("created_by_account_id"),
59 createdAt: bigint("created_at", { mode: "number" }).notNull(),
60 updatedAt: bigint("updated_at", { mode: "number" }).notNull(),
61 },
62 (table) => [
63 index("workspaces_org_idx").on(table.organizationId),
64 ],
65);
66
67export const sourcesTable = pgTable(
68 tableNames.sources,
69 {
70 workspaceId: text("workspace_id").notNull(),
71 sourceId: text("source_id").notNull(),
72 name: text("name").notNull(),
73 kind: text("kind").notNull(),
74 endpoint: text("endpoint").notNull(),
75 status: text("status").notNull(),
76 enabled: boolean("enabled").notNull(),
77 configJson: text("config_json").notNull(),
78 sourceHash: text("source_hash"),
79 lastError: text("last_error"),
80 createdAt: bigint("created_at", { mode: "number" }).notNull(),
81 updatedAt: bigint("updated_at", { mode: "number" }).notNull(),
82 },
83 (table) => [
84 primaryKey({
85 columns: [table.workspaceId, table.sourceId],
86 }),
87 index("sources_workspace_name_idx").on(table.workspaceId, table.name),
88 ],
89);
90
91export const toolArtifactsTable = pgTable(
92 tableNames.toolArtifacts,
93 {
94 id: text("id").notNull(),
95 workspaceId: text("workspace_id").notNull(),
96 sourceId: text("source_id").notNull(),
97 sourceHash: text("source_hash").notNull(),
98 toolCount: bigint("tool_count", { mode: "number" }).notNull(),
99 manifestJson: text("manifest_json").notNull(),
100 createdAt: bigint("created_at", { mode: "number" }).notNull(),
101 updatedAt: bigint("updated_at", { mode: "number" }).notNull(),
102 },
103 (table) => [
104 primaryKey({
105 columns: [table.workspaceId, table.sourceId],
106 }),
107 uniqueIndex("tool_artifacts_id_idx").on(table.id),
108 ],
109);
110
111export const authConnectionsTable = pgTable(
112 tableNames.authConnections,
113 {
114 id: text("id").notNull().primaryKey(),
115 organizationId: text("organization_id").notNull(),
116 workspaceId: text("workspace_id"),
117 accountId: text("account_id"),
118 ownerType: text("owner_type").notNull(),
119 strategy: text("strategy").notNull(),
120 displayName: text("display_name").notNull(),
121 status: text("status").notNull(),
122 statusReason: text("status_reason"),
123 lastAuthErrorClass: text("last_auth_error_class"),
124 metadataJson: text("metadata_json"),
125 additionalHeadersJson: text("additional_headers_json"),
126 createdByAccountId: text("created_by_account_id"),
127 createdAt: bigint("created_at", { mode: "number" }).notNull(),
128 updatedAt: bigint("updated_at", { mode: "number" }).notNull(),
129 lastUsedAt: bigint("last_used_at", { mode: "number" }),
130 },
131 (table) => [
132 index("auth_connections_org_idx").on(table.organizationId),
133 index("auth_connections_workspace_idx").on(table.workspaceId),
134 index("auth_connections_account_idx").on(table.accountId),
135 ],
136);
137
138export const sourceAuthBindingsTable = pgTable(
139 tableNames.sourceAuthBindings,
140 {
141 id: text("id").notNull().primaryKey(),
142 sourceId: text("source_id").notNull(),
143 connectionId: text("connection_id").notNull(),
144 organizationId: text("organization_id").notNull(),
145 workspaceId: text("workspace_id"),
146 accountId: text("account_id"),
147 scopeType: text("scope_type").notNull(),
148 selector: text("selector"),
149 enabled: boolean("enabled").notNull(),
150 createdAt: bigint("created_at", { mode: "number" }).notNull(),
151 updatedAt: bigint("updated_at", { mode: "number" }).notNull(),
152 },
153 (table) => [
154 index("source_auth_bindings_source_idx").on(table.sourceId),
155 index("source_auth_bindings_connection_idx").on(table.connectionId),
156 index("source_auth_bindings_org_idx").on(table.organizationId),
157 index("source_auth_bindings_workspace_idx").on(table.workspaceId),
158 index("source_auth_bindings_account_idx").on(table.accountId),
159 ],
160);
161
162export const authMaterialsTable = pgTable(
163 tableNames.authMaterials,
164 {
165 id: text("id").notNull().primaryKey(),
166 connectionId: text("connection_id").notNull(),
167 ciphertext: text("ciphertext").notNull(),
168 keyVersion: text("key_version").notNull(),
169 createdAt: bigint("created_at", { mode: "number" }).notNull(),
170 updatedAt: bigint("updated_at", { mode: "number" }).notNull(),
171 },
172 (table) => [
173 index("auth_materials_connection_idx").on(table.connectionId),
174 ],
175);
176
177export const oauthStatesTable = pgTable(
178 tableNames.oauthStates,
179 {
180 id: text("id").notNull().primaryKey(),
181 connectionId: text("connection_id").notNull(),
182 accessTokenCiphertext: text("access_token_ciphertext").notNull(),
183 refreshTokenCiphertext: text("refresh_token_ciphertext"),
184 keyVersion: text("key_version").notNull(),
185 expiresAt: bigint("expires_at", { mode: "number" }),
186 scope: text("scope"),
187 tokenType: text("token_type"),
188 issuer: text("issuer"),
189 refreshConfigJson: text("refresh_config_json"),
190 tokenVersion: bigint("token_version", { mode: "number" }).notNull(),
191 leaseHolder: text("lease_holder"),
192 leaseExpiresAt: bigint("lease_expires_at", { mode: "number" }),
193 leaseFence: bigint("lease_fence", { mode: "number" }).notNull(),
194 lastRefreshAt: bigint("last_refresh_at", { mode: "number" }),
195 lastRefreshErrorClass: text("last_refresh_error_class"),
196 lastRefreshError: text("last_refresh_error"),
197 reauthRequiredAt: bigint("reauth_required_at", { mode: "number" }),
198 createdAt: bigint("created_at", { mode: "number" }).notNull(),
199 updatedAt: bigint("updated_at", { mode: "number" }).notNull(),
200 },
201 (table) => [
202 index("oauth_states_connection_idx").on(table.connectionId),
203 ],
204);
205
206export const policiesTable = pgTable(
207 tableNames.policies,
208 {
209 id: text("id").notNull().primaryKey(),
210 workspaceId: text("workspace_id").notNull(),
211 toolPathPattern: text("tool_path_pattern").notNull(),
212 decision: text("decision").notNull(),
213 createdAt: bigint("created_at", { mode: "number" }).notNull(),
214 updatedAt: bigint("updated_at", { mode: "number" }).notNull(),
215 },
216 (table) => [
217 index("policies_workspace_idx").on(table.workspaceId),
218 ],
219);
220
221export const approvalsTable = pgTable(
222 tableNames.approvals,
223 {
224 id: text("id").notNull().primaryKey(),
225 workspaceId: text("workspace_id").notNull(),
226 taskRunId: text("task_run_id").notNull(),
227 callId: text("call_id").notNull(),
228 toolPath: text("tool_path").notNull(),
229 status: text("status").notNull(),
230 inputPreviewJson: text("input_preview_json").notNull(),
231 reason: text("reason"),
232 requestedAt: bigint("requested_at", { mode: "number" }).notNull(),
233 resolvedAt: bigint("resolved_at", { mode: "number" }),
234 },
235 (table) => [
236 index("approvals_workspace_idx").on(table.workspaceId),
237 index("approvals_task_run_idx").on(table.taskRunId),
238 ],
239);
240
241export const taskRunsTable = pgTable(
242 tableNames.taskRuns,
243 {
244 id: text("id").notNull().primaryKey(),
245 workspaceId: text("workspace_id").notNull(),
246 accountId: text("account_id").notNull(),
247 sessionId: text("session_id").notNull(),
248 runtimeId: text("runtime_id").notNull(),
249 codeHash: text("code_hash").notNull(),
250 status: text("status").notNull(),
251 startedAt: bigint("started_at", { mode: "number" }),
252 completedAt: bigint("completed_at", { mode: "number" }),
253 exitCode: bigint("exit_code", { mode: "number" }),
254 error: text("error"),
255 },
256 (table) => [
257 index("task_runs_workspace_idx").on(table.workspaceId),
258 ],
259);
260
261export const storageInstancesTable = pgTable(
262 tableNames.storageInstances,
263 {
264 id: text("id").notNull().primaryKey(),
265 scopeType: text("scope_type").notNull(),
266 durability: text("durability").notNull(),
267 status: text("status").notNull(),
268 provider: text("provider").notNull(),
269 backendKey: text("backend_key").notNull(),
270 organizationId: text("organization_id").notNull(),
271 workspaceId: text("workspace_id"),
272 accountId: text("account_id"),
273 createdByAccountId: text("created_by_account_id"),
274 purpose: text("purpose"),
275 sizeBytes: bigint("size_bytes", { mode: "number" }),
276 fileCount: bigint("file_count", { mode: "number" }),
277 createdAt: bigint("created_at", { mode: "number" }).notNull(),
278 updatedAt: bigint("updated_at", { mode: "number" }).notNull(),
279 lastSeenAt: bigint("last_seen_at", { mode: "number" }).notNull(),
280 closedAt: bigint("closed_at", { mode: "number" }),
281 expiresAt: bigint("expires_at", { mode: "number" }),
282 },
283 (table) => [
284 index("storage_instances_org_idx").on(table.organizationId),
285 index("storage_instances_workspace_idx").on(table.workspaceId),
286 ],
287);
288
289export const syncStatesTable = pgTable(
290 tableNames.syncStates,
291 {
292 id: text("id").notNull().primaryKey(),
293 workspaceId: text("workspace_id").notNull(),
294 target: text("target").notNull(),
295 targetUrl: text("target_url").notNull(),
296 linkedSubject: text("linked_subject"),
297 cursor: text("cursor"),
298 lastSyncAt: bigint("last_sync_at", { mode: "number" }),
299 updatedAt: bigint("updated_at", { mode: "number" }).notNull(),
300 },
301 (table) => [
302 index("sync_states_workspace_idx").on(table.workspaceId),
303 ],
304);
packages/persistence-sql/src/schema.ts+212−42
@@ -23,39 +23,61 @@ export const tableNames = { · 22 unmodified lines
23 taskRuns: "task_runs",23 taskRuns: "task_runs",
24 storageInstances: "storage_instances",24 storageInstances: "storage_instances",
25 syncStates: "sync_states",25 syncStates: "sync_states",
26 events: "events",
27} as const;26} as const;
28 27
29const entityColumns = {28export const profileTable = sqliteTable(tableNames.profile, {
30 id: text("id").notNull().primaryKey(),29 id: text("id").notNull().primaryKey(),
31 payloadJson: text("payload_json").notNull(),30 defaultWorkspaceId: text("default_workspace_id"),
31 displayName: text("display_name").notNull(),
32 runtimeMode: text("runtime_mode").notNull(),
33 createdAt: integer("created_at", { mode: "number" }).notNull(),
32 updatedAt: integer("updated_at", { mode: "number" }).notNull(),34 updatedAt: integer("updated_at", { mode: "number" }).notNull(),
33};35});
34
35const workspaceEntityColumns = {
36 ...entityColumns,
37 workspaceId: text("workspace_id"),
38};
39 36
40export const profileTable = sqliteTable(tableNames.profile, {37export const organizationsTable = sqliteTable(tableNames.organizations, {
41 id: integer("id").notNull().primaryKey(),38 id: text("id").notNull().primaryKey(),
42 schemaVersion: integer("schema_version").notNull(),39 slug: text("slug").notNull(),
43 generatedAt: integer("generated_at", { mode: "number" }).notNull(),40 name: text("name").notNull(),
44 profileJson: text("profile_json").notNull(),41 status: text("status").notNull(),
42 createdByAccountId: text("created_by_account_id"),
43 createdAt: integer("created_at", { mode: "number" }).notNull(),
45 updatedAt: integer("updated_at", { mode: "number" }).notNull(),44 updatedAt: integer("updated_at", { mode: "number" }).notNull(),
46});45});
47 46
48export const organizationsTable = sqliteTable(
49 tableNames.organizations,
50 entityColumns,
51);
52
53export const organizationMembershipsTable = sqliteTable(47export const organizationMembershipsTable = sqliteTable(
54 tableNames.organizationMemberships,48 tableNames.organizationMemberships,
55 workspaceEntityColumns,49 {
50 id: text("id").notNull().primaryKey(),
51 organizationId: text("organization_id").notNull(),
52 accountId: text("account_id").notNull(),
53 role: text("role").notNull(),
54 status: text("status").notNull(),
55 billable: integer("billable", { mode: "boolean" }).notNull(),
56 invitedByAccountId: text("invited_by_account_id"),
57 joinedAt: integer("joined_at", { mode: "number" }),
58 createdAt: integer("created_at", { mode: "number" }).notNull(),
59 updatedAt: integer("updated_at", { mode: "number" }).notNull(),
60 },
61 (table) => [
62 index("organization_memberships_org_idx").on(table.organizationId),
63 index("organization_memberships_account_idx").on(table.accountId),
64 ],
56);65);
57 66
58export const workspacesTable = sqliteTable(tableNames.workspaces, workspaceEntityColumns);67export const workspacesTable = sqliteTable(
68 tableNames.workspaces,
69 {
70 id: text("id").notNull().primaryKey(),
71 organizationId: text("organization_id").notNull(),
72 name: text("name").notNull(),
73 createdByAccountId: text("created_by_account_id"),
74 createdAt: integer("created_at", { mode: "number" }).notNull(),
75 updatedAt: integer("updated_at", { mode: "number" }).notNull(),
76 },
77 (table) => [
78 index("workspaces_org_idx").on(table.organizationId),
79 ],
80);
59 81
60export const sourcesTable = sqliteTable(82export const sourcesTable = sqliteTable(
61 tableNames.sources,83 tableNames.sources,
@@ -63,7 +85,14 @@ export const sourcesTable = sqliteTable( · 1 unmodified line
63 workspaceId: text("workspace_id").notNull(),85 workspaceId: text("workspace_id").notNull(),
64 sourceId: text("source_id").notNull(),86 sourceId: text("source_id").notNull(),
65 name: text("name").notNull(),87 name: text("name").notNull(),
66 payloadJson: text("payload_json").notNull(),88 kind: text("kind").notNull(),
89 endpoint: text("endpoint").notNull(),
90 status: text("status").notNull(),
91 enabled: integer("enabled", { mode: "boolean" }).notNull(),
92 configJson: text("config_json").notNull(),
93 sourceHash: text("source_hash"),
94 lastError: text("last_error"),
95 createdAt: integer("created_at", { mode: "number" }).notNull(),
67 updatedAt: integer("updated_at", { mode: "number" }).notNull(),96 updatedAt: integer("updated_at", { mode: "number" }).notNull(),
68 },97 },
69 (table) => [98 (table) => [
@@ -77,73 +106,214 @@ export const sourcesTable = sqliteTable( · 7 unmodified lines
77export const toolArtifactsTable = sqliteTable(106export const toolArtifactsTable = sqliteTable(
78 tableNames.toolArtifacts,107 tableNames.toolArtifacts,
79 {108 {
109 id: text("id").notNull(),
80 workspaceId: text("workspace_id").notNull(),110 workspaceId: text("workspace_id").notNull(),
81 sourceId: text("source_id").notNull(),111 sourceId: text("source_id").notNull(),
82 payloadJson: text("payload_json").notNull(),112 sourceHash: text("source_hash").notNull(),
113 toolCount: integer("tool_count", { mode: "number" }).notNull(),
114 manifestJson: text("manifest_json").notNull(),
115 createdAt: integer("created_at", { mode: "number" }).notNull(),
83 updatedAt: integer("updated_at", { mode: "number" }).notNull(),116 updatedAt: integer("updated_at", { mode: "number" }).notNull(),
84 },117 },
85 (table) => [118 (table) => [
86 primaryKey({119 primaryKey({
87 columns: [table.workspaceId, table.sourceId],120 columns: [table.workspaceId, table.sourceId],
88 }),121 }),
122 uniqueIndex("tool_artifacts_id_idx").on(table.id),
89 ],123 ],
90);124);
91 125
92export const authConnectionsTable = sqliteTable(126export const authConnectionsTable = sqliteTable(
93 tableNames.authConnections,127 tableNames.authConnections,
94 workspaceEntityColumns,128 {
129 id: text("id").notNull().primaryKey(),
130 organizationId: text("organization_id").notNull(),
131 workspaceId: text("workspace_id"),
132 accountId: text("account_id"),
133 ownerType: text("owner_type").notNull(),
134 strategy: text("strategy").notNull(),
135 displayName: text("display_name").notNull(),
136 status: text("status").notNull(),
137 statusReason: text("status_reason"),
138 lastAuthErrorClass: text("last_auth_error_class"),
139 metadataJson: text("metadata_json"),
140 additionalHeadersJson: text("additional_headers_json"),
141 createdByAccountId: text("created_by_account_id"),
142 createdAt: integer("created_at", { mode: "number" }).notNull(),
143 updatedAt: integer("updated_at", { mode: "number" }).notNull(),
144 lastUsedAt: integer("last_used_at", { mode: "number" }),
145 },
146 (table) => [
147 index("auth_connections_org_idx").on(table.organizationId),
148 index("auth_connections_workspace_idx").on(table.workspaceId),
149 index("auth_connections_account_idx").on(table.accountId),
150 ],
95);151);
96 152
97export const sourceAuthBindingsTable = sqliteTable(153export const sourceAuthBindingsTable = sqliteTable(
98 tableNames.sourceAuthBindings,154 tableNames.sourceAuthBindings,
99 workspaceEntityColumns,155 {
156 id: text("id").notNull().primaryKey(),
157 sourceId: text("source_id").notNull(),
158 connectionId: text("connection_id").notNull(),
159 organizationId: text("organization_id").notNull(),
160 workspaceId: text("workspace_id"),
161 accountId: text("account_id"),
162 scopeType: text("scope_type").notNull(),
163 selector: text("selector"),
164 enabled: integer("enabled", { mode: "boolean" }).notNull(),
165 createdAt: integer("created_at", { mode: "number" }).notNull(),
166 updatedAt: integer("updated_at", { mode: "number" }).notNull(),
167 },
168 (table) => [
169 index("source_auth_bindings_source_idx").on(table.sourceId),
170 index("source_auth_bindings_connection_idx").on(table.connectionId),
171 index("source_auth_bindings_org_idx").on(table.organizationId),
172 index("source_auth_bindings_workspace_idx").on(table.workspaceId),
173 index("source_auth_bindings_account_idx").on(table.accountId),
174 ],
100);175);
101 176
102export const authMaterialsTable = sqliteTable(177export const authMaterialsTable = sqliteTable(
103 tableNames.authMaterials,178 tableNames.authMaterials,
104 workspaceEntityColumns,179 {
180 id: text("id").notNull().primaryKey(),
181 connectionId: text("connection_id").notNull(),
182 ciphertext: text("ciphertext").notNull(),
183 keyVersion: text("key_version").notNull(),
184 createdAt: integer("created_at", { mode: "number" }).notNull(),
185 updatedAt: integer("updated_at", { mode: "number" }).notNull(),
186 },
187 (table) => [
188 index("auth_materials_connection_idx").on(table.connectionId),
189 ],
105);190);
106 191
107export const oauthStatesTable = sqliteTable(192export const oauthStatesTable = sqliteTable(
108 tableNames.oauthStates,193 tableNames.oauthStates,
109 workspaceEntityColumns,194 {
195 id: text("id").notNull().primaryKey(),
196 connectionId: text("connection_id").notNull(),
197 accessTokenCiphertext: text("access_token_ciphertext").notNull(),
198 refreshTokenCiphertext: text("refresh_token_ciphertext"),
199 keyVersion: text("key_version").notNull(),
200 expiresAt: integer("expires_at", { mode: "number" }),
201 scope: text("scope"),
202 tokenType: text("token_type"),
203 issuer: text("issuer"),
204 refreshConfigJson: text("refresh_config_json"),
205 tokenVersion: integer("token_version", { mode: "number" }).notNull(),
206 leaseHolder: text("lease_holder"),
207 leaseExpiresAt: integer("lease_expires_at", { mode: "number" }),
208 leaseFence: integer("lease_fence", { mode: "number" }).notNull(),
209 lastRefreshAt: integer("last_refresh_at", { mode: "number" }),
210 lastRefreshErrorClass: text("last_refresh_error_class"),
211 lastRefreshError: text("last_refresh_error"),
212 reauthRequiredAt: integer("reauth_required_at", { mode: "number" }),
213 createdAt: integer("created_at", { mode: "number" }).notNull(),
214 updatedAt: integer("updated_at", { mode: "number" }).notNull(),
215 },
216 (table) => [
217 index("oauth_states_connection_idx").on(table.connectionId),
218 ],
110);219);
111 220
112export const policiesTable = sqliteTable(221export const policiesTable = sqliteTable(
113 tableNames.policies,222 tableNames.policies,
114 workspaceEntityColumns,223 {
224 id: text("id").notNull().primaryKey(),
225 workspaceId: text("workspace_id").notNull(),
226 toolPathPattern: text("tool_path_pattern").notNull(),
227 decision: text("decision").notNull(),
228 createdAt: integer("created_at", { mode: "number" }).notNull(),
229 updatedAt: integer("updated_at", { mode: "number" }).notNull(),
230 },
231 (table) => [
232 index("policies_workspace_idx").on(table.workspaceId),
233 ],
115);234);
116 235
117export const approvalsTable = sqliteTable(236export const approvalsTable = sqliteTable(
118 tableNames.approvals,237 tableNames.approvals,
119 workspaceEntityColumns,238 {
239 id: text("id").notNull().primaryKey(),
240 workspaceId: text("workspace_id").notNull(),
241 taskRunId: text("task_run_id").notNull(),
242 callId: text("call_id").notNull(),
243 toolPath: text("tool_path").notNull(),
244 status: text("status").notNull(),
245 inputPreviewJson: text("input_preview_json").notNull(),
246 reason: text("reason"),
247 requestedAt: integer("requested_at", { mode: "number" }).notNull(),
248 resolvedAt: integer("resolved_at", { mode: "number" }),
249 },
250 (table) => [
251 index("approvals_workspace_idx").on(table.workspaceId),
252 index("approvals_task_run_idx").on(table.taskRunId),
253 ],
120);254);
121 255
122export const taskRunsTable = sqliteTable(256export const taskRunsTable = sqliteTable(
123 tableNames.taskRuns,257 tableNames.taskRuns,
124 workspaceEntityColumns,258 {
259 id: text("id").notNull().primaryKey(),
260 workspaceId: text("workspace_id").notNull(),
261 accountId: text("account_id").notNull(),
262 sessionId: text("session_id").notNull(),
263 runtimeId: text("runtime_id").notNull(),
264 codeHash: text("code_hash").notNull(),
265 status: text("status").notNull(),
266 startedAt: integer("started_at", { mode: "number" }),
267 completedAt: integer("completed_at", { mode: "number" }),
268 exitCode: integer("exit_code", { mode: "number" }),
269 error: text("error"),
270 },
271 (table) => [
272 index("task_runs_workspace_idx").on(table.workspaceId),
273 ],
125);274);
126 275
127export const storageInstancesTable = sqliteTable(276export const storageInstancesTable = sqliteTable(
128 tableNames.storageInstances,277 tableNames.storageInstances,
129 workspaceEntityColumns,278 {
279 id: text("id").notNull().primaryKey(),
280 scopeType: text("scope_type").notNull(),
281 durability: text("durability").notNull(),
282 status: text("status").notNull(),
283 provider: text("provider").notNull(),
284 backendKey: text("backend_key").notNull(),
285 organizationId: text("organization_id").notNull(),
286 workspaceId: text("workspace_id"),
287 accountId: text("account_id"),
288 createdByAccountId: text("created_by_account_id"),
289 purpose: text("purpose"),
290 sizeBytes: integer("size_bytes", { mode: "number" }),
291 fileCount: integer("file_count", { mode: "number" }),
292 createdAt: integer("created_at", { mode: "number" }).notNull(),
293 updatedAt: integer("updated_at", { mode: "number" }).notNull(),
294 lastSeenAt: integer("last_seen_at", { mode: "number" }).notNull(),
295 closedAt: integer("closed_at", { mode: "number" }),
296 expiresAt: integer("expires_at", { mode: "number" }),
297 },
298 (table) => [
299 index("storage_instances_org_idx").on(table.organizationId),
300 index("storage_instances_workspace_idx").on(table.workspaceId),
301 ],
130);302);
131 303
132export const syncStatesTable = sqliteTable(tableNames.syncStates, workspaceEntityColumns);304export const syncStatesTable = sqliteTable(
133 305 tableNames.syncStates,
134export const eventsTable = sqliteTable(
135 tableNames.events,
136 {306 {
137 id: text("id").notNull().primaryKey(),307 id: text("id").notNull().primaryKey(),
138 workspaceId: text("workspace_id").notNull(),308 workspaceId: text("workspace_id").notNull(),
139 sequence: integer("sequence").notNull(),309 target: text("target").notNull(),
140 eventJson: text("event_json").notNull(),310 targetUrl: text("target_url").notNull(),
141 createdAt: integer("created_at", { mode: "number" }).notNull(),311 linkedSubject: text("linked_subject"),
312 cursor: text("cursor"),
313 lastSyncAt: integer("last_sync_at", { mode: "number" }),
314 updatedAt: integer("updated_at", { mode: "number" }).notNull(),
142 },315 },
143 (table) => [316 (table) => [
144 uniqueIndex("events_workspace_sequence_idx").on(317 index("sync_states_workspace_idx").on(table.workspaceId),
145 table.workspaceId,
146 table.sequence,
147 ),
148 ],318 ],
149);319);
packages/persistence-sql/src/source-artifact-stores.ts+69−28
@@ -9,7 +9,6 @@ import * as Effect from "effect/Effect"; · 8 unmodified lines
9import * as Option from "effect/Option";9import * as Option from "effect/Option";
10import { and, asc, eq } from "drizzle-orm";10import { and, asc, eq } from "drizzle-orm";
11 11
12import { SourceJson, ToolArtifactJson } from "./persistence-codecs";
13import {12import {
14 toSourceStoreError,13 toSourceStoreError,
15 toToolArtifactStoreError,14 toToolArtifactStoreError,
@@ -47,6 +46,34 @@ const sortSources = (sources: ReadonlyArray<Source>): Array<Source> => · 31 unmodified lines
47 return leftName.localeCompare(rightName);46 return leftName.localeCompare(rightName);
48 });47 });
49 48
49const toSource = (row: DrizzleTables["sourcesTable"]["$inferSelect"]): Source => ({
50 id: row.sourceId as Source["id"],
51 workspaceId: row.workspaceId as Source["workspaceId"],
52 name: row.name,
53 kind: row.kind as Source["kind"],
54 endpoint: row.endpoint,
55 status: row.status as Source["status"],
56 enabled: row.enabled,
57 configJson: row.configJson,
58 sourceHash: row.sourceHash,
59 lastError: row.lastError,
60 createdAt: row.createdAt,
61 updatedAt: row.updatedAt,
62});
63
64const toToolArtifact = (
65 row: DrizzleTables["toolArtifactsTable"]["$inferSelect"],
66): ToolArtifact => ({
67 id: row.id as ToolArtifact["id"],
68 workspaceId: row.workspaceId as ToolArtifact["workspaceId"],
69 sourceId: row.sourceId as ToolArtifact["sourceId"],
70 sourceHash: row.sourceHash,
71 toolCount: row.toolCount,
72 manifestJson: row.manifestJson,
73 createdAt: row.createdAt,
74 updatedAt: row.updatedAt,
75});
76
50export const createSourceAndArtifactStores = ({77export const createSourceAndArtifactStores = ({
51 backend,78 backend,
52 adapter,79 adapter,
@@ -61,23 +88,19 @@ export const createSourceAndArtifactStores = ({ · 8 unmodified lines
61 getById: (workspaceId: WorkspaceId, sourceId: SourceId) =>88 getById: (workspaceId: WorkspaceId, sourceId: SourceId) =>
62 Effect.tryPromise({89 Effect.tryPromise({
63 try: async () => {90 try: async () => {
64 const rows = await db91 const rows = await db.select().from(tables.sourcesTable).where(
65 .select({ payloadJson: tables.sourcesTable.payloadJson })92 and(
66 .from(tables.sourcesTable)93 eq(tables.sourcesTable.workspaceId, workspaceId),
67 .where(94 eq(tables.sourcesTable.sourceId, sourceId),
68 and(95 ),
69 eq(tables.sourcesTable.workspaceId, workspaceId),96 ).limit(1);
70 eq(tables.sourcesTable.sourceId, sourceId),
71 ),
72 )
73 .limit(1);
74 97
75 const row = rows[0];98 const row = rows[0];
76 if (!row) {99 if (!row) {
77 return Option.none<Source>();100 return Option.none<Source>();
78 }101 }
79 102
80 return Option.some(SourceJson.decode(row.payloadJson));103 return Option.some(toSource(row));
81 },104 },
82 catch: (cause) =>105 catch: (cause) =>
83 toSourceStoreError(backend, "get_by_id", tableNames.sources, cause),106 toSourceStoreError(backend, "get_by_id", tableNames.sources, cause),
@@ -87,12 +110,12 @@ export const createSourceAndArtifactStores = ({ · 3 unmodified lines
87 Effect.tryPromise({110 Effect.tryPromise({
88 try: async () => {111 try: async () => {
89 const rows = await db112 const rows = await db
90 .select({ payloadJson: tables.sourcesTable.payloadJson })113 .select()
91 .from(tables.sourcesTable)114 .from(tables.sourcesTable)
92 .where(eq(tables.sourcesTable.workspaceId, workspaceId))115 .where(eq(tables.sourcesTable.workspaceId, workspaceId))
93 .orderBy(asc(tables.sourcesTable.name), asc(tables.sourcesTable.sourceId));116 .orderBy(asc(tables.sourcesTable.name), asc(tables.sourcesTable.sourceId));
94 117
95 return sortSources(rows.map((row) => SourceJson.decode(row.payloadJson)));118 return sortSources(rows.map(toSource));
96 },119 },
97 catch: (cause) =>120 catch: (cause) =>
98 toSourceStoreError(backend, "list_by_workspace", tableNames.sources, cause),121 toSourceStoreError(backend, "list_by_workspace", tableNames.sources, cause),
@@ -104,8 +127,6 @@ export const createSourceAndArtifactStores = ({ · 5 unmodified lines
104 await writeLocked(async () => {127 await writeLocked(async () => {
105 await adapter.transaction(async (transaction) => {128 await adapter.transaction(async (transaction) => {
106 const transactionContext = createDrizzleContext(transaction);129 const transactionContext = createDrizzleContext(transaction);
107 const payloadJson = SourceJson.encode(source);
108 const updatedAt = Date.now();
109 130
110 await transactionContext.db131 await transactionContext.db
111 .insert(transactionContext.tables.sourcesTable)132 .insert(transactionContext.tables.sourcesTable)
@@ -113,8 +134,15 @@ export const createSourceAndArtifactStores = ({ · 1 unmodified line
113 workspaceId: source.workspaceId,134 workspaceId: source.workspaceId,
114 sourceId: source.id,135 sourceId: source.id,
115 name: source.name,136 name: source.name,
116 payloadJson,137 kind: source.kind,
117 updatedAt,138 endpoint: source.endpoint,
139 status: source.status,
140 enabled: source.enabled,
141 configJson: source.configJson,
142 sourceHash: source.sourceHash,
143 lastError: source.lastError,
144 createdAt: source.createdAt,
145 updatedAt: source.updatedAt,
118 })146 })
119 .onConflictDoUpdate({147 .onConflictDoUpdate({
120 target: [148 target: [
@@ -123,8 +151,15 @@ export const createSourceAndArtifactStores = ({ · 2 unmodified lines
123 ],151 ],
124 set: {152 set: {
125 name: source.name,153 name: source.name,
126 payloadJson,154 kind: source.kind,
127 updatedAt,155 endpoint: source.endpoint,
156 status: source.status,
157 enabled: source.enabled,
158 configJson: source.configJson,
159 sourceHash: source.sourceHash,
160 lastError: source.lastError,
161 createdAt: source.createdAt,
162 updatedAt: source.updatedAt,
128 },163 },
129 });164 });
130 });165 });
@@ -177,7 +212,7 @@ export const createSourceAndArtifactStores = ({ · 46 unmodified lines
177 Effect.tryPromise({212 Effect.tryPromise({
178 try: async () => {213 try: async () => {
179 const rows = await db214 const rows = await db
180 .select({ payloadJson: tables.toolArtifactsTable.payloadJson })215 .select()
181 .from(tables.toolArtifactsTable)216 .from(tables.toolArtifactsTable)
182 .where(217 .where(
183 and(218 and(
@@ -192,7 +227,7 @@ export const createSourceAndArtifactStores = ({ · 8 unmodified lines
192 return Option.none<ToolArtifact>();227 return Option.none<ToolArtifact>();
193 }228 }
194 229
195 return Option.some(ToolArtifactJson.decode(row.payloadJson));230 return Option.some(toToolArtifact(row));
196 },231 },
197 catch: (cause) =>232 catch: (cause) =>
198 toToolArtifactStoreError(233 toToolArtifactStoreError(
@@ -209,16 +244,18 @@ export const createSourceAndArtifactStores = ({ · 10 unmodified lines
209 await writeLocked(async () => {244 await writeLocked(async () => {
210 await adapter.transaction(async (transaction) => {245 await adapter.transaction(async (transaction) => {
211 const transactionContext = createDrizzleContext(transaction);246 const transactionContext = createDrizzleContext(transaction);
212 const payloadJson = ToolArtifactJson.encode(artifact);
213 const updatedAt = Date.now();
214 247
215 await transactionContext.db248 await transactionContext.db
216 .insert(transactionContext.tables.toolArtifactsTable)249 .insert(transactionContext.tables.toolArtifactsTable)
217 .values({250 .values({
251 id: artifact.id,
218 workspaceId: artifact.workspaceId,252 workspaceId: artifact.workspaceId,
219 sourceId: artifact.sourceId,253 sourceId: artifact.sourceId,
220 payloadJson,254 sourceHash: artifact.sourceHash,
221 updatedAt,255 toolCount: artifact.toolCount,
256 manifestJson: artifact.manifestJson,
257 createdAt: artifact.createdAt,
258 updatedAt: artifact.updatedAt,
222 })259 })
223 .onConflictDoUpdate({260 .onConflictDoUpdate({
224 target: [261 target: [
@@ -226,8 +263,12 @@ export const createSourceAndArtifactStores = ({ · 1 unmodified line
226 transactionContext.tables.toolArtifactsTable.sourceId,263 transactionContext.tables.toolArtifactsTable.sourceId,
227 ],264 ],
228 set: {265 set: {
229 payloadJson,266 id: artifact.id,
230 updatedAt,267 sourceHash: artifact.sourceHash,
268 toolCount: artifact.toolCount,
269 manifestJson: artifact.manifestJson,
270 createdAt: artifact.createdAt,
271 updatedAt: artifact.updatedAt,
231 },272 },
232 });273 });
233 });274 });
packages/persistence-sql/src/sql-internals.ts+0−418
@@ -1,418 +0,0 @@
1import { drizzle as drizzlePgProxy } from "drizzle-orm/pg-proxy";
2import { migrate as migratePgProxy } from "drizzle-orm/pg-proxy/migrator";
3import { drizzle as drizzleSqliteProxy } from "drizzle-orm/sqlite-proxy";
4import { migrate as migrateSqliteProxy } from "drizzle-orm/sqlite-proxy/migrator";
5import { mkdir } from "node:fs/promises";
6import { existsSync } from "node:fs";
7import * as path from "node:path";
8import postgres, { type Sql } from "postgres";
9
10import {
11 approvalsTable as approvalsSqliteTable,
12 authConnectionsTable as authConnectionsSqliteTable,
13 authMaterialsTable as authMaterialsSqliteTable,
14 oauthStatesTable as oauthStatesSqliteTable,
15 organizationMembershipsTable as organizationMembershipsSqliteTable,
16 organizationsTable as organizationsSqliteTable,
17 policiesTable as policiesSqliteTable,
18 profileTable as profileSqliteTable,
19 sourceAuthBindingsTable as sourceAuthBindingsSqliteTable,
20 sourcesTable as sourcesSqliteTable,
21 storageInstancesTable as storageInstancesSqliteTable,
22 syncStatesTable as syncStatesSqliteTable,
23 taskRunsTable as taskRunsSqliteTable,
24 toolArtifactsTable as toolArtifactsSqliteTable,
25 workspacesTable as workspacesSqliteTable,
26} from "./schema";
27
28export type SqlBackend = "sqlite" | "postgres";
29type SqlRow = Record<string, unknown>;
30
31export type SqlAdapter = {
32 readonly backend: SqlBackend;
33 query: <TRow extends SqlRow = SqlRow>(
34 statement: string,
35 args?: ReadonlyArray<unknown>,
36 ) => Promise<Array<TRow>>;
37 execute: (statement: string, args?: ReadonlyArray<unknown>) => Promise<void>;
38 transaction: <A>(run: (transaction: SqlAdapter) => Promise<A>) => Promise<A>;
39 close: () => Promise<void>;
40};
41
42type SqliteStatement = {
43 all: (...parameters: Array<unknown>) => Array<SqlRow>;
44 run: (...parameters: Array<unknown>) => unknown;
45};
46
47type GenericSqliteDatabase = {
48 exec: (statement: string) => void;
49 prepare: (statement: string) => SqliteStatement;
50 close: (...parameters: Array<unknown>) => void;
51};
52
53type NodeSqliteModule = {
54 DatabaseSync: new (filename: string) => GenericSqliteDatabase;
55};
56
57type BunSqliteQuery = {
58 all: (...parameters: Array<unknown>) => Array<SqlRow>;
59 run: (...parameters: Array<unknown>) => unknown;
60};
61
62type BunSqliteDatabase = {
63 query: (statement: string) => BunSqliteQuery;
64 exec: (statement: string) => void;
65 close: (...parameters: Array<unknown>) => void;
66};
67
68type BunSqliteModule = {
69 Database: new (
70 filename: string,
71 options?: {
72 create?: boolean;
73 readonly?: boolean;
74 },
75 ) => BunSqliteDatabase;
76};
77
78const withPostgresPlaceholders = (statement: string): string => {
79 let index = 0;
80 return statement.replace(/\?/g, () => {
81 index += 1;
82 return `$${index}`;
83 });
84};
85
86const isBunRuntime = (): boolean =>
87 typeof (globalThis as { Bun?: unknown }).Bun !== "undefined";
88
89const loadNodeSqliteModule = async (): Promise<NodeSqliteModule> => {
90 const moduleSpecifier = "node:sqlite";
91 return (await import(moduleSpecifier)) as NodeSqliteModule;
92};
93
94const loadBunSqliteModule = async (): Promise<BunSqliteModule> => {
95 const moduleSpecifier = "bun:sqlite";
96 return (await import(moduleSpecifier)) as BunSqliteModule;
97};
98
99const makeSqliteTransaction = (
100 execute: (statement: string, args?: ReadonlyArray<unknown>) => Promise<void>,
101 query: <TRow extends SqlRow = SqlRow>(
102 statement: string,
103 args?: ReadonlyArray<unknown>,
104 ) => Promise<Array<TRow>>,
105): SqlAdapter["transaction"] =>
106 async <A>(run: (transactionAdapter: SqlAdapter) => Promise<A>): Promise<A> => {
107 await execute("BEGIN IMMEDIATE");
108
109 try {
110 const adapter: SqlAdapter = {
111 backend: "sqlite",
112 query,
113 execute,
114 transaction: async (nestedRun) => nestedRun(adapter),
115 close: async () => {},
116 };
117
118 const result = await run(adapter);
119 await execute("COMMIT");
120 return result;
121 } catch (error) {
122 try {
123 await execute("ROLLBACK");
124 } catch {
125 // ignore rollback failure after original error
126 }
127
128 throw error;
129 }
130 };
131
132const createNodeSqliteAdapter = async (
133 sqlitePath: string,
134): Promise<SqlAdapter> => {
135 const { DatabaseSync } = await loadNodeSqliteModule();
136 const db = new DatabaseSync(sqlitePath);
137
138 const query = async <TRow extends SqlRow = SqlRow>(
139 statement: string,
140 args: ReadonlyArray<unknown> = [],
141 ): Promise<Array<TRow>> => {
142 const prepared = db.prepare(statement);
143 return prepared.all(...args) as Array<TRow>;
144 };
145
146 const execute = async (
147 statement: string,
148 args: ReadonlyArray<unknown> = [],
149 ): Promise<void> => {
150 if (args.length === 0) {
151 db.exec(statement);
152 return;
153 }
154
155 const prepared = db.prepare(statement);
156 prepared.run(...args);
157 };
158
159 return {
160 backend: "sqlite",
161 query,
162 execute,
163 transaction: makeSqliteTransaction(execute, query),
164 close: async () => {
165 db.close();
166 },
167 };
168};
169
170const createBunSqliteAdapter = async (
171 sqlitePath: string,
172): Promise<SqlAdapter> => {
173 const { Database } = await loadBunSqliteModule();
174 const db = new Database(sqlitePath, { create: true });
175
176 const query = async <TRow extends SqlRow = SqlRow>(
177 statement: string,
178 args: ReadonlyArray<unknown> = [],
179 ): Promise<Array<TRow>> => db.query(statement).all(...args) as Array<TRow>;
180
181 const execute = async (
182 statement: string,
183 args: ReadonlyArray<unknown> = [],
184 ): Promise<void> => {
185 db.query(statement).run(...args);
186 };
187
188 return {
189 backend: "sqlite",
190 query,
191 execute,
192 transaction: makeSqliteTransaction(execute, query),
193 close: async () => {
194 db.close();
195 },
196 };
197};
198
199export const createSqliteAdapter = async (sqlitePath: string): Promise<SqlAdapter> => {
200 const resolvedPath = path.resolve(sqlitePath);
201 await mkdir(path.dirname(resolvedPath), { recursive: true });
202
203 return isBunRuntime()
204 ? createBunSqliteAdapter(resolvedPath)
205 : createNodeSqliteAdapter(resolvedPath);
206};
207
208export const createPostgresAdapter = async (
209 databaseUrl: string,
210 applicationName: string | undefined,
211): Promise<SqlAdapter> => {
212 const client = postgres(databaseUrl, {
213 prepare: false,
214 max: 10,
215 ...(applicationName ? { connection: { application_name: applicationName } } : {}),
216 });
217
218 type UnsafeRunner = {
219 unsafe: Sql["unsafe"];
220 };
221
222 const toPostgresParams = (
223 args: ReadonlyArray<unknown>,
224 ): Array<postgres.ParameterOrJSON<never>> =>
225 args as unknown as Array<postgres.ParameterOrJSON<never>>;
226
227 const queryWith = async <TRow extends SqlRow = SqlRow>(
228 runner: UnsafeRunner,
229 statement: string,
230 args: ReadonlyArray<unknown> = [],
231 ): Promise<Array<TRow>> =>
232 (await runner.unsafe(
233 withPostgresPlaceholders(statement),
234 toPostgresParams(args),
235 )) as unknown as Array<TRow>;
236
237 const executeWith = async (
238 runner: UnsafeRunner,
239 statement: string,
240 args: ReadonlyArray<unknown> = [],
241 ): Promise<void> => {
242 await runner.unsafe(
243 withPostgresPlaceholders(statement),
244 toPostgresParams(args),
245 );
246 };
247
248 const adapter: SqlAdapter = {
249 backend: "postgres",
250 query: (statement, args = []) => queryWith(client, statement, args),
251 execute: (statement, args = []) => executeWith(client, statement, args),
252 transaction: async <A>(run: (transaction: SqlAdapter) => Promise<A>) => {
253 const result = await client.begin(async (transactionClient) => {
254 const runner: UnsafeRunner = transactionClient;
255 const transactionAdapter: SqlAdapter = {
256 backend: "postgres",
257 query: (statement, args = []) => queryWith(runner, statement, args),
258 execute: (statement, args = []) => executeWith(runner, statement, args),
259 transaction: async (nestedRun) => nestedRun(transactionAdapter),
260 close: async () => {},
261 };
262
263 return run(transactionAdapter);
264 });
265
266 return result as unknown as A;
267 },
268 close: async () => {
269 await client.end({ timeout: 5 });
270 },
271 };
272
273 return adapter;
274};
275
276const resolveDrizzleMigrationsFolder = (): string => {
277 const cwd = process.cwd();
278 const candidates = [
279 path.resolve(cwd, "packages/persistence-sql/drizzle"),
280 path.resolve(cwd, "../packages/persistence-sql/drizzle"),
281 path.resolve(cwd, "../../packages/persistence-sql/drizzle"),
282 ];
283
284 for (const candidate of candidates) {
285 if (existsSync(path.join(candidate, "meta", "_journal.json"))) {
286 return candidate;
287 }
288 }
289
290 throw new Error("Unable to resolve drizzle migrations folder");
291};
292
293const runMigrationQueries = async (
294 adapter: SqlAdapter,
295 queries: ReadonlyArray<string>,
296): Promise<void> => {
297 for (const query of queries) {
298 const statement = query.trim();
299 if (statement.length === 0) {
300 continue;
301 }
302
303 await adapter.execute(statement);
304 }
305};
306
307const toProxyRow = (row: unknown): unknown => {
308 if (Array.isArray(row) || row === null || row === undefined) {
309 return row;
310 }
311
312 if (typeof row === "object") {
313 return Object.values(row as Record<string, unknown>);
314 }
315
316 return row;
317};
318
319const normalizeProxyRows = (
320 method: "run" | "all" | "values" | "get",
321 rows: ReadonlyArray<unknown>,
322): Array<unknown> => {
323 if (method === "get") {
324 const first = rows[0];
325 return first === undefined ? [] : [toProxyRow(first)];
326 }
327
328 return rows.map(toProxyRow);
329};
330
331const sqliteDrizzleSchema = {
332 profileTable: profileSqliteTable,
333 organizationsTable: organizationsSqliteTable,
334 organizationMembershipsTable: organizationMembershipsSqliteTable,
335 workspacesTable: workspacesSqliteTable,
336 sourcesTable: sourcesSqliteTable,
337 toolArtifactsTable: toolArtifactsSqliteTable,
338 authConnectionsTable: authConnectionsSqliteTable,
339 sourceAuthBindingsTable: sourceAuthBindingsSqliteTable,
340 authMaterialsTable: authMaterialsSqliteTable,
341 oauthStatesTable: oauthStatesSqliteTable,
342 policiesTable: policiesSqliteTable,
343 approvalsTable: approvalsSqliteTable,
344 taskRunsTable: taskRunsSqliteTable,
345 storageInstancesTable: storageInstancesSqliteTable,
346 syncStatesTable: syncStatesSqliteTable,
347};
348
349type SqliteDrizzleSchema = typeof sqliteDrizzleSchema;
350export type DrizzleDb = ReturnType<typeof drizzleSqliteProxy<SqliteDrizzleSchema>>;
351export type DrizzleTables = SqliteDrizzleSchema;
352
353export type DrizzleContext = {
354 db: DrizzleDb;
355 tables: DrizzleTables;
356};
357
358const createSqliteProxyDb = (adapter: SqlAdapter): DrizzleDb =>
359 drizzleSqliteProxy(
360 async (statement, params, method) => {
361 if (method === "run") {
362 await adapter.execute(statement, params);
363 return { rows: [] };
364 }
365
366 const rows = await adapter.query(statement, params);
367 return {
368 rows: normalizeProxyRows(method, rows),
369 };
370 },
371 {
372 schema: sqliteDrizzleSchema,
373 },
374 );
375
376export const createDrizzleContext = (adapter: SqlAdapter): DrizzleContext => ({
377 db: createSqliteProxyDb(adapter),
378 tables: sqliteDrizzleSchema,
379});
380
381const createPostgresMigrationDb = (adapter: SqlAdapter) =>
382 drizzlePgProxy(async (statement, params, method) => {
383 if (method === "execute") {
384 await adapter.execute(statement, params);
385 return { rows: [] };
386 }
387
388 const rows = await adapter.query(statement, params);
389 return { rows };
390 });
391
392export const runMigrations = async (
393 backend: SqlBackend,
394 adapter: SqlAdapter,
395): Promise<void> => {
396 const migrationsFolder = resolveDrizzleMigrationsFolder();
397
398 if (backend === "postgres") {
399 const migrationDb = createPostgresMigrationDb(adapter);
400 await migratePgProxy(
401 migrationDb,
402 async (queries) => runMigrationQueries(adapter, queries),
403 {
404 migrationsFolder,
405 },
406 );
407 return;
408 }
409
410 const migrationDb = createSqliteProxyDb(adapter);
411 await migrateSqliteProxy(
412 migrationDb,
413 async (queries) => runMigrationQueries(adapter, queries),
414 {
415 migrationsFolder,
416 },
417 );
418};

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t