apps 0.0.1-beta.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (135) hide show
  1. package/README.md +191 -0
  2. package/check-publish.mjs +10 -0
  3. package/framework-reference.json +1 -0
  4. package/js/chunk-22WRQZT7.js +389 -0
  5. package/js/chunk-2OTCEKL2.js +29480 -0
  6. package/js/chunk-36DNRFZQ.js +34 -0
  7. package/js/chunk-3ANFZFCV.js +1799 -0
  8. package/js/chunk-7JXHF5IF.js +138 -0
  9. package/js/chunk-BCSNKUAC.js +0 -0
  10. package/js/chunk-BKVL7XAJ.js +47 -0
  11. package/js/chunk-BPEFS4YF.js +1323 -0
  12. package/js/chunk-C24KEZXR.js +59 -0
  13. package/js/chunk-D6BKYP2L.js +877 -0
  14. package/js/chunk-EP6AEUZO.js +19 -0
  15. package/js/chunk-HP7E42X6.js +1719 -0
  16. package/js/chunk-KWTCHVLT.js +284 -0
  17. package/js/chunk-LOKGDT6B.js +28 -0
  18. package/js/chunk-MLKGABMK.js +9 -0
  19. package/js/chunk-OWD2YICM.js +2486 -0
  20. package/js/chunk-Q2FD5IBM.js +899 -0
  21. package/js/chunk-R6JMJSVT.js +590 -0
  22. package/js/chunk-SBKHUC5L.js +56 -0
  23. package/js/chunk-VFUZI3NY.js +75 -0
  24. package/js/chunk-W7Q5EOTS.js +4375 -0
  25. package/js/chunk-WIDTG42X.js +171 -0
  26. package/js/chunk-X3YBZCJW.js +246 -0
  27. package/js/chunk-YDR4CPJA.js +2357 -0
  28. package/js/client.js +1023 -0
  29. package/js/contracts.js +163 -0
  30. package/js/effect.js +44 -0
  31. package/js/graphql.js +392 -0
  32. package/js/host.js +193 -0
  33. package/js/index.js +284 -0
  34. package/js/mcp/effect.js +23 -0
  35. package/js/mcp/stdio.js +123 -0
  36. package/js/mcp.js +37 -0
  37. package/js/openapi.js +246 -0
  38. package/js/operations/approval.js +9 -0
  39. package/js/react.js +37 -0
  40. package/js/storage/facet.js +546 -0
  41. package/js/ui/auth/contracts.js +19 -0
  42. package/js/ui/auth.js +28 -0
  43. package/js/ui/contracts.js +24 -0
  44. package/js/ui/serving.js +286 -0
  45. package/package.json +116 -0
  46. package/runtime.json +1 -0
  47. package/types/app-data/src/contracts/database.d.ts +193 -0
  48. package/types/app-data/src/implementation/cursor.d.ts +10 -0
  49. package/types/app-data/src/implementation/index-key.d.ts +7 -0
  50. package/types/app-data/src/implementation/promise.d.ts +68 -0
  51. package/types/app-data/src/implementation/range.d.ts +8 -0
  52. package/types/app-data/src/implementation/schema.d.ts +33 -0
  53. package/types/app-data/src/implementation/sqlite.d.ts +11 -0
  54. package/types/app-data/src/index.d.ts +4 -0
  55. package/types/apps/src/approval.d.ts +10 -0
  56. package/types/apps/src/client.d.ts +5 -0
  57. package/types/apps/src/contracts/app.d.ts +58 -0
  58. package/types/apps/src/contracts/approval.d.ts +14 -0
  59. package/types/apps/src/contracts/context.d.ts +25 -0
  60. package/types/apps/src/contracts/elicitation.d.ts +86 -0
  61. package/types/apps/src/contracts/graphql.d.ts +102 -0
  62. package/types/apps/src/contracts/host.d.ts +568 -0
  63. package/types/apps/src/contracts/http.d.ts +20 -0
  64. package/types/apps/src/contracts/live.d.ts +26 -0
  65. package/types/apps/src/contracts/mcp.d.ts +93 -0
  66. package/types/apps/src/contracts/openapi.d.ts +105 -0
  67. package/types/apps/src/contracts/operations.d.ts +30 -0
  68. package/types/apps/src/contracts/optimistic.d.ts +22 -0
  69. package/types/apps/src/contracts/provider.d.ts +96 -0
  70. package/types/apps/src/contracts/schedules.d.ts +51 -0
  71. package/types/apps/src/contracts/schema.d.ts +20 -0
  72. package/types/apps/src/contracts/storage.d.ts +68 -0
  73. package/types/apps/src/contracts/tools.d.ts +11 -0
  74. package/types/apps/src/contracts/ui-auth.d.ts +28 -0
  75. package/types/apps/src/contracts/ui.d.ts +90 -0
  76. package/types/apps/src/contracts/webhook-protocol.d.ts +102 -0
  77. package/types/apps/src/contracts/webhooks.d.ts +53 -0
  78. package/types/apps/src/contracts/workflows.d.ts +277 -0
  79. package/types/apps/src/effect.d.ts +10 -0
  80. package/types/apps/src/facet.d.ts +5 -0
  81. package/types/apps/src/graphql.d.ts +10 -0
  82. package/types/apps/src/host.d.ts +16 -0
  83. package/types/apps/src/implementation/account-operations.d.ts +32 -0
  84. package/types/apps/src/implementation/app.d.ts +40 -0
  85. package/types/apps/src/implementation/authoring.d.ts +12 -0
  86. package/types/apps/src/implementation/elicitation.d.ts +103 -0
  87. package/types/apps/src/implementation/graphql.d.ts +5 -0
  88. package/types/apps/src/implementation/host.d.ts +3 -0
  89. package/types/apps/src/implementation/http.d.ts +5 -0
  90. package/types/apps/src/implementation/live.d.ts +18 -0
  91. package/types/apps/src/implementation/mcp-call.d.ts +19 -0
  92. package/types/apps/src/implementation/mcp-client.d.ts +50 -0
  93. package/types/apps/src/implementation/mcp-stdio.d.ts +4 -0
  94. package/types/apps/src/implementation/mcp-tools.d.ts +6 -0
  95. package/types/apps/src/implementation/mcp.d.ts +4 -0
  96. package/types/apps/src/implementation/openapi-request.d.ts +11 -0
  97. package/types/apps/src/implementation/openapi.d.ts +5 -0
  98. package/types/apps/src/implementation/operations.d.ts +65 -0
  99. package/types/apps/src/implementation/optimistic.d.ts +30 -0
  100. package/types/apps/src/implementation/protocol-operations.d.ts +24 -0
  101. package/types/apps/src/implementation/provider.d.ts +16 -0
  102. package/types/apps/src/implementation/query-commit.d.ts +10 -0
  103. package/types/apps/src/implementation/schedules.d.ts +16 -0
  104. package/types/apps/src/implementation/schema.d.ts +93 -0
  105. package/types/apps/src/implementation/storage.d.ts +13 -0
  106. package/types/apps/src/implementation/ui-auth.d.ts +13 -0
  107. package/types/apps/src/implementation/ui-client.d.ts +16 -0
  108. package/types/apps/src/implementation/ui-errors.d.ts +2 -0
  109. package/types/apps/src/implementation/ui-serving.d.ts +16 -0
  110. package/types/apps/src/implementation/ui-watch.d.ts +2 -0
  111. package/types/apps/src/implementation/webhooks.d.ts +29 -0
  112. package/types/apps/src/implementation/workflow-context.d.ts +8 -0
  113. package/types/apps/src/implementation/workflow-rpc.d.ts +5 -0
  114. package/types/apps/src/implementation/workflows.d.ts +27 -0
  115. package/types/apps/src/index.d.ts +58 -0
  116. package/types/apps/src/mcp-stdio.d.ts +8 -0
  117. package/types/apps/src/mcp.d.ts +10 -0
  118. package/types/apps/src/openapi.d.ts +10 -0
  119. package/types/apps/src/react.d.ts +7 -0
  120. package/types/apps/src/ui-auth.d.ts +3 -0
  121. package/types/apps/src/ui-serving.d.ts +3 -0
  122. package/types/telemetry/src/browser-operations.d.ts +16 -0
  123. package/types/telemetry/src/browser-performance.d.ts +11 -0
  124. package/types/telemetry/src/browser-request-timing.d.ts +2 -0
  125. package/types/telemetry/src/browser.d.ts +27 -0
  126. package/types/telemetry/src/config.d.ts +83 -0
  127. package/types/telemetry/src/context.d.ts +14 -0
  128. package/types/telemetry/src/index.d.ts +9 -0
  129. package/types/telemetry/src/layer.d.ts +7 -0
  130. package/types/telemetry/src/measurements.d.ts +8 -0
  131. package/types/telemetry/src/pending-span.d.ts +7 -0
  132. package/types/telemetry/src/relay.d.ts +28 -0
  133. package/types/telemetry/src/span-attributes.d.ts +29 -0
  134. package/types/telemetry/src/trace-context.d.ts +20 -0
  135. package/types/telemetry/src/transport.d.ts +6 -0
@@ -0,0 +1,590 @@
1
+ import {
2
+ AppDatabaseError,
3
+ DatabaseLimits,
4
+ DatabaseOperation,
5
+ DatabaseSchema,
6
+ PaginationResult,
7
+ RangeClause,
8
+ Row,
9
+ RowMetadata,
10
+ defaultDatabaseLimits,
11
+ defaultDatabaseRuntimeLimits
12
+ } from "./chunk-7JXHF5IF.js";
13
+ import {
14
+ Clock_exports,
15
+ Effect_exports,
16
+ Encoding_exports,
17
+ Schema_exports,
18
+ Semaphore_exports
19
+ } from "./chunk-2OTCEKL2.js";
20
+
21
+ // ../app-data/src/implementation/schema.ts
22
+ var metadata = /* @__PURE__ */ new Set(["id", "createdAt", "updatedAt"]);
23
+ var indexesFor = (table) => [{ name: "by_creation", fields: [] }, ...table.indexes].map((index) => ({
24
+ name: index.name,
25
+ fields: [
26
+ ...index.fields,
27
+ ...["createdAt", "id"].filter((field) => !index.fields.includes(field))
28
+ ]
29
+ }));
30
+ var fieldFor = (table, name) => metadata.has(name) ? { kind: "string" } : Object.hasOwn(table.fields, name) ? table.fields[name] : void 0;
31
+ var validScalar = (field, value) => field.kind === "number" ? typeof value === "number" && Number.isFinite(value) : field.kind === "boolean" ? typeof value === "boolean" : typeof value === "string" && ![...value].some((character) => {
32
+ const point = character.codePointAt(0);
33
+ return point !== void 0 && point >= 55296 && point <= 57343;
34
+ });
35
+ var parseDatabaseSchema = (input) => Schema_exports.decodeUnknownEffect(DatabaseSchema)(input).pipe(
36
+ Effect_exports.flatMap(
37
+ (schema) => Effect_exports.gen(function* () {
38
+ for (const table of Object.values(schema)) {
39
+ if (Object.keys(table.fields).some((name) => metadata.has(name)) || new Set(table.indexes.map((index) => index.name)).size !== table.indexes.length)
40
+ return yield* new AppDatabaseError({ reason: "schema" });
41
+ for (const field of Object.values(table.fields)) {
42
+ if ((field.kind === "id" ? field.references === void 0 : field.references !== void 0) || field.default !== void 0 && !validScalar(field, field.default) || field.references !== void 0 && !Object.hasOwn(schema, field.references))
43
+ return yield* new AppDatabaseError({ reason: "schema" });
44
+ }
45
+ for (const index of table.indexes)
46
+ if (index.name === "by_creation" || new Set(index.fields).size !== index.fields.length || index.fields.some((name) => fieldFor(table, name) === void 0))
47
+ return yield* new AppDatabaseError({ reason: "schema" });
48
+ }
49
+ return schema;
50
+ })
51
+ ),
52
+ Effect_exports.mapError(() => new AppDatabaseError({ reason: "schema" }))
53
+ );
54
+ var canonicalSchema = (schema) => JSON.stringify(
55
+ Object.fromEntries(
56
+ Object.entries(schema).sort(([a], [b]) => a < b ? -1 : a > b ? 1 : 0).map(([name, table]) => [
57
+ name,
58
+ {
59
+ fields: Object.fromEntries(
60
+ Object.entries(table.fields).sort(([a], [b]) => a < b ? -1 : a > b ? 1 : 0).map(([field, definition]) => [
61
+ field,
62
+ {
63
+ kind: definition.kind,
64
+ optional: definition.optional === true,
65
+ ...definition.default === void 0 ? {} : { default: definition.default },
66
+ ...definition.references === void 0 ? {} : { references: definition.references }
67
+ }
68
+ ])
69
+ ),
70
+ indexes: [...table.indexes].sort(
71
+ (a, b) => a.name < b.name ? -1 : a.name > b.name ? 1 : 0
72
+ )
73
+ }
74
+ ])
75
+ )
76
+ );
77
+ var writeValue = (table, values, previous, meta) => Effect_exports.gen(function* () {
78
+ if (Object.keys(values).some((name) => metadata.has(name) || !Object.hasOwn(table.fields, name)))
79
+ return yield* new AppDatabaseError({ reason: "value" });
80
+ const row = { ...meta };
81
+ for (const [name, field] of Object.entries(table.fields)) {
82
+ const supplied = Object.hasOwn(values, name) ? values[name] : previous?.[name];
83
+ if (supplied === null && !field.optional)
84
+ return yield* new AppDatabaseError({ reason: "value" });
85
+ const value = supplied === null || supplied === void 0 ? field.default : supplied;
86
+ if (value === void 0) {
87
+ if (!field.optional) return yield* new AppDatabaseError({ reason: "value" });
88
+ } else {
89
+ if (!validScalar(field, value)) return yield* new AppDatabaseError({ reason: "value" });
90
+ row[name] = value;
91
+ }
92
+ }
93
+ return row;
94
+ });
95
+
96
+ // ../app-data/src/implementation/cursor.ts
97
+ var Payload = Schema_exports.Struct({
98
+ version: Schema_exports.Literal(1),
99
+ query: Schema_exports.String,
100
+ key: Schema_exports.String
101
+ });
102
+ var fingerprint = (crypto, value) => Effect_exports.tryPromise({
103
+ try: async () => Encoding_exports.encodeBase64Url(
104
+ new Uint8Array(await crypto.subtle.digest("SHA-256", new TextEncoder().encode(value)))
105
+ ),
106
+ catch: () => new AppDatabaseError({ reason: "storage" })
107
+ });
108
+ var cursorCodec = (crypto, bytes) => Effect_exports.gen(function* () {
109
+ const key = yield* Effect_exports.tryPromise({
110
+ try: () => crypto.subtle.importKey("raw", new Uint8Array(bytes), "AES-GCM", false, [
111
+ "encrypt",
112
+ "decrypt"
113
+ ]),
114
+ catch: () => new AppDatabaseError({ reason: "storage" })
115
+ });
116
+ return {
117
+ encode: (query, position) => Effect_exports.tryPromise({
118
+ try: async () => {
119
+ const nonce = crypto.getRandomValues(new Uint8Array(12));
120
+ const plaintext = new TextEncoder().encode(
121
+ JSON.stringify({ version: 1, query, key: Encoding_exports.encodeBase64Url(position) })
122
+ );
123
+ const ciphertext = new Uint8Array(
124
+ await crypto.subtle.encrypt({ name: "AES-GCM", iv: nonce }, key, plaintext)
125
+ );
126
+ const token = new Uint8Array(nonce.length + ciphertext.length);
127
+ token.set(nonce);
128
+ token.set(ciphertext, nonce.length);
129
+ return Encoding_exports.encodeBase64Url(token);
130
+ },
131
+ catch: () => new AppDatabaseError({ reason: "cursor" })
132
+ }),
133
+ decode: (query, token) => Effect_exports.gen(function* () {
134
+ if (token.length > defaultDatabaseRuntimeLimits.maxCursorChars)
135
+ return yield* new AppDatabaseError({ reason: "cursor" });
136
+ const encoded = yield* Effect_exports.fromResult(Encoding_exports.decodeBase64Url(token));
137
+ if (encoded.length < 28) return yield* new AppDatabaseError({ reason: "cursor" });
138
+ const plain = yield* Effect_exports.tryPromise(
139
+ () => crypto.subtle.decrypt(
140
+ { name: "AES-GCM", iv: new Uint8Array(encoded.slice(0, 12)) },
141
+ key,
142
+ new Uint8Array(encoded.slice(12))
143
+ )
144
+ );
145
+ const payload = yield* Schema_exports.decodeUnknownEffect(Schema_exports.fromJsonString(Payload))(
146
+ new TextDecoder().decode(plain)
147
+ );
148
+ if (payload.query !== query) return yield* new AppDatabaseError({ reason: "cursor" });
149
+ return yield* Effect_exports.fromResult(Encoding_exports.decodeBase64Url(payload.key));
150
+ }).pipe(Effect_exports.mapError(() => new AppDatabaseError({ reason: "cursor" })))
151
+ };
152
+ });
153
+
154
+ // ../app-data/src/implementation/index-key.ts
155
+ var encodeIndexKey = (values, maximum = defaultDatabaseLimits.indexBytes) => Effect_exports.try({
156
+ try: () => {
157
+ const bytes = [1];
158
+ for (const value of values) {
159
+ if (value === null) bytes.push(1);
160
+ else if (typeof value === "boolean") bytes.push(value ? 17 : 16);
161
+ else if (typeof value === "string") {
162
+ if ([...value].some((character) => {
163
+ const code = character.codePointAt(0);
164
+ return code !== void 0 && code >= 55296 && code <= 57343;
165
+ }))
166
+ throw new Error("Invalid string");
167
+ bytes.push(32);
168
+ for (const byte of new TextEncoder().encode(value)) {
169
+ bytes.push(byte);
170
+ if (byte === 0) bytes.push(255);
171
+ }
172
+ bytes.push(0, 0);
173
+ } else {
174
+ if (!Number.isFinite(value)) throw new Error("Invalid number");
175
+ const view = new DataView(new ArrayBuffer(8));
176
+ view.setFloat64(0, value === 0 ? 0 : value, false);
177
+ const encoded = new Uint8Array(view.buffer);
178
+ if (value < 0) for (const [i, byte] of encoded.entries()) encoded[i] = 255 ^ byte;
179
+ else view.setUint8(0, view.getUint8(0) ^ 128);
180
+ bytes.push(48, ...encoded);
181
+ }
182
+ if (bytes.length > maximum) throw new Error("Index key too long");
183
+ }
184
+ return Uint8Array.from(bytes);
185
+ },
186
+ catch: () => new AppDatabaseError({ reason: "value" })
187
+ });
188
+ var prefixEnd = (prefix) => {
189
+ const result = prefix.slice();
190
+ for (let i = result.length - 1; i >= 0; i--) {
191
+ const byte = result[i];
192
+ if (byte !== void 0 && byte < 255) {
193
+ result[i] = byte + 1;
194
+ return result.slice(0, i + 1);
195
+ }
196
+ }
197
+ return void 0;
198
+ };
199
+
200
+ // ../app-data/src/implementation/range.ts
201
+ var queryBounds = (table, plan, maximum) => Effect_exports.gen(function* () {
202
+ const index = indexesFor(table).find((index2) => index2.name === plan.index);
203
+ if (index === void 0) return yield* new AppDatabaseError({ reason: "index" });
204
+ const equal = [];
205
+ let rangeField;
206
+ let lower;
207
+ let upper;
208
+ let lowerSet = false;
209
+ let upperSet = false;
210
+ for (const clause of plan.clauses) {
211
+ const expected = rangeField === void 0 ? index.fields[equal.length] : rangeField;
212
+ const field = fieldFor(table, clause.field);
213
+ if (expected !== clause.field || field === void 0)
214
+ return yield* new AppDatabaseError({ reason: "range" });
215
+ if (clause.op === "eq") {
216
+ if (rangeField !== void 0 || (clause.value === null ? !field.optional : !validScalar(field, clause.value)))
217
+ return yield* new AppDatabaseError({ reason: "range" });
218
+ equal.push(clause.value);
219
+ } else {
220
+ if (!validScalar(field, clause.value))
221
+ return yield* new AppDatabaseError({ reason: "range" });
222
+ rangeField = clause.field;
223
+ const encoded = yield* encodeIndexKey([...equal, clause.value], maximum);
224
+ if (clause.op === "gt" || clause.op === "gte") {
225
+ if (lowerSet) return yield* new AppDatabaseError({ reason: "range" });
226
+ lowerSet = true;
227
+ lower = clause.op === "gt" ? prefixEnd(encoded) : encoded;
228
+ } else {
229
+ if (upperSet) return yield* new AppDatabaseError({ reason: "range" });
230
+ upperSet = true;
231
+ upper = clause.op === "lte" ? prefixEnd(encoded) : encoded;
232
+ }
233
+ }
234
+ }
235
+ const prefix = yield* encodeIndexKey(equal, maximum);
236
+ if (rangeField !== void 0 && !lowerSet)
237
+ lower = prefixEnd(yield* encodeIndexKey([...equal, null], maximum));
238
+ return { lower: lower ?? prefix, upper: upper ?? prefixEnd(prefix) };
239
+ });
240
+
241
+ // ../app-data/src/implementation/sqlite.ts
242
+ var Saved = Schema_exports.Struct({ schema_hash: Schema_exports.String, cursor_key: Schema_exports.String });
243
+ var StoredRow = Schema_exports.Struct({ body: Schema_exports.String });
244
+ var ScanRow = Schema_exports.Struct({ sort_key: Schema_exports.Uint8Array, body: Schema_exports.String });
245
+ var CountRow = Schema_exports.Struct({ sort_key: Schema_exports.Uint8Array });
246
+ var decodeRows = Schema_exports.decodeUnknownEffect(Schema_exports.Array(StoredRow));
247
+ var decodeBody = Schema_exports.decodeUnknownEffect(Schema_exports.fromJsonString(Row));
248
+ var storageError = () => new AppDatabaseError({ reason: "storage" });
249
+ var makeSqliteDatabase = (options) => Effect_exports.gen(function* () {
250
+ const { sql, crypto } = options;
251
+ const schema = yield* parseDatabaseSchema(options.schema);
252
+ const limits = yield* Schema_exports.decodeUnknownEffect(DatabaseLimits)(
253
+ options.limits ?? defaultDatabaseLimits
254
+ ).pipe(Effect_exports.mapError(() => new AppDatabaseError({ reason: "limit" })));
255
+ const schemaHash = yield* fingerprint(crypto, canonicalSchema(schema));
256
+ const key = yield* sql.withTransaction(
257
+ Effect_exports.gen(function* () {
258
+ yield* sql`CREATE TABLE IF NOT EXISTS app_database (singleton INTEGER PRIMARY KEY CHECK (singleton = 1), schema_hash TEXT NOT NULL, cursor_key TEXT NOT NULL)`;
259
+ yield* sql`CREATE TABLE IF NOT EXISTS app_rows (table_name TEXT NOT NULL, id TEXT NOT NULL, body TEXT NOT NULL, PRIMARY KEY (table_name, id)) WITHOUT ROWID`;
260
+ yield* sql`CREATE TABLE IF NOT EXISTS app_indexes (table_name TEXT NOT NULL, index_name TEXT NOT NULL, sort_key BLOB NOT NULL, row_id TEXT NOT NULL, PRIMARY KEY (table_name, index_name, sort_key)) WITHOUT ROWID`;
261
+ yield* sql`CREATE TABLE IF NOT EXISTS app_mutation_receipts (id TEXT PRIMARY KEY, fingerprint TEXT NOT NULL, result TEXT NOT NULL) WITHOUT ROWID`;
262
+ yield* sql`CREATE INDEX IF NOT EXISTS app_indexes_by_row ON app_indexes (table_name, row_id)`;
263
+ const generated = Encoding_exports.encodeBase64Url(crypto.getRandomValues(new Uint8Array(32)));
264
+ yield* sql`INSERT OR IGNORE INTO app_database (singleton, schema_hash, cursor_key) VALUES (1, ${schemaHash}, ${generated})`;
265
+ const saved = yield* sql`SELECT schema_hash, cursor_key FROM app_database WHERE singleton = 1`.pipe(
266
+ Effect_exports.flatMap((rows) => Schema_exports.decodeUnknownEffect(Saved)(rows[0]))
267
+ );
268
+ if (saved.schema_hash !== schemaHash)
269
+ return yield* new AppDatabaseError({ reason: "schema_changed" });
270
+ return yield* Effect_exports.fromResult(Encoding_exports.decodeBase64Url(saved.cursor_key));
271
+ })
272
+ ).pipe(
273
+ Effect_exports.catchTags({
274
+ SqlError: () => Effect_exports.fail(storageError()),
275
+ SchemaError: () => Effect_exports.fail(storageError()),
276
+ EncodingError: () => Effect_exports.fail(storageError())
277
+ })
278
+ );
279
+ const cursors = yield* cursorCodec(crypto, key);
280
+ const run = (writable, work) => sql.withTransaction(
281
+ Effect_exports.gen(function* () {
282
+ const context = yield* Effect_exports.context();
283
+ const gate = yield* Semaphore_exports.make(1);
284
+ const reads = /* @__PURE__ */ new Set();
285
+ const changes = /* @__PURE__ */ new Set();
286
+ let active = true;
287
+ let failed;
288
+ const used = {
289
+ rowsRead: 0,
290
+ rowsReturned: 0,
291
+ bytesRead: 0,
292
+ writes: 0,
293
+ scanCalls: 0,
294
+ directGets: 0
295
+ };
296
+ const charge = (name, amount) => Effect_exports.suspend(() => {
297
+ used[name] += amount;
298
+ return used[name] > limits[name] ? Effect_exports.fail(new AppDatabaseError({ reason: "limit" })) : Effect_exports.void;
299
+ });
300
+ const get = (table, id) => Effect_exports.gen(function* () {
301
+ yield* charge("directGets", 1);
302
+ reads.add(table);
303
+ const records = yield* sql`SELECT body FROM app_rows WHERE table_name = ${table} AND id = ${id}`.pipe(
304
+ Effect_exports.flatMap(decodeRows)
305
+ );
306
+ const record = records[0];
307
+ if (record === void 0) return null;
308
+ yield* charge("rowsRead", 1);
309
+ yield* charge("bytesRead", new TextEncoder().encode(record.body).length);
310
+ return yield* decodeBody(record.body);
311
+ });
312
+ const store = (tableName, table, row) => Effect_exports.gen(function* () {
313
+ const meta = yield* Schema_exports.decodeUnknownEffect(RowMetadata)(row);
314
+ const body = JSON.stringify(row);
315
+ if (new TextEncoder().encode(body).length > limits.valueBytes)
316
+ return yield* new AppDatabaseError({ reason: "limit" });
317
+ const keys = yield* Effect_exports.forEach(
318
+ indexesFor(table),
319
+ (index) => encodeIndexKey(
320
+ index.fields.map(
321
+ (field) => Object.hasOwn(row, field) ? row[field] ?? null : null
322
+ ),
323
+ limits.indexBytes
324
+ ).pipe(Effect_exports.map((key2) => ({ name: index.name, key: key2 })))
325
+ );
326
+ yield* sql`INSERT INTO app_rows (table_name, id, body) VALUES (${tableName}, ${meta.id}, ${body}) ON CONFLICT(table_name, id) DO UPDATE SET body = excluded.body`;
327
+ yield* sql`DELETE FROM app_indexes WHERE table_name = ${tableName} AND row_id = ${meta.id}`;
328
+ for (const index of keys)
329
+ yield* sql`INSERT INTO app_indexes (table_name, index_name, sort_key, row_id) VALUES (${tableName}, ${index.name}, ${index.key}, ${meta.id})`;
330
+ changes.add(tableName);
331
+ return row;
332
+ });
333
+ const execute = (input) => gate.withPermits(1)(
334
+ Effect_exports.gen(function* () {
335
+ if (!active) return yield* new AppDatabaseError({ reason: "closed" });
336
+ if (failed !== void 0) return yield* failed;
337
+ const operation = yield* Schema_exports.decodeUnknownEffect(DatabaseOperation)(
338
+ input
339
+ ).pipe(Effect_exports.mapError(() => new AppDatabaseError({ reason: "value" })));
340
+ const tableName = operation.kind === "query" ? operation.plan.table : operation.table;
341
+ const table = Object.hasOwn(schema, tableName) ? schema[tableName] : void 0;
342
+ if (table === void 0) return yield* new AppDatabaseError({ reason: "table" });
343
+ switch (operation.kind) {
344
+ case "get": {
345
+ const row = yield* get(tableName, operation.id);
346
+ if (row !== null) yield* charge("rowsReturned", 1);
347
+ return row;
348
+ }
349
+ case "insert": {
350
+ if (!writable) return yield* new AppDatabaseError({ reason: "readonly" });
351
+ yield* charge("writes", 1);
352
+ const timestamp = new Date(yield* Clock_exports.currentTimeMillis).toISOString();
353
+ const row = yield* writeValue(table, operation.value, void 0, {
354
+ id: crypto.randomUUID(),
355
+ createdAt: timestamp,
356
+ updatedAt: timestamp
357
+ });
358
+ return yield* store(tableName, table, row);
359
+ }
360
+ case "update": {
361
+ if (!writable) return yield* new AppDatabaseError({ reason: "readonly" });
362
+ yield* charge("writes", 1);
363
+ const before = yield* get(tableName, operation.id);
364
+ if (before === null) return null;
365
+ const meta = yield* Schema_exports.decodeUnknownEffect(RowMetadata)(before);
366
+ const row = yield* writeValue(table, operation.patch, before, {
367
+ ...meta,
368
+ updatedAt: new Date(yield* Clock_exports.currentTimeMillis).toISOString()
369
+ });
370
+ return yield* store(tableName, table, row);
371
+ }
372
+ case "delete": {
373
+ if (!writable) return yield* new AppDatabaseError({ reason: "readonly" });
374
+ yield* charge("writes", 1);
375
+ const before = yield* get(tableName, operation.id);
376
+ if (before === null) return false;
377
+ yield* sql`DELETE FROM app_rows WHERE table_name = ${tableName} AND id = ${operation.id}`;
378
+ yield* sql`DELETE FROM app_indexes WHERE table_name = ${tableName} AND row_id = ${operation.id}`;
379
+ changes.add(tableName);
380
+ return true;
381
+ }
382
+ case "query": {
383
+ const { plan, terminal } = operation;
384
+ const bounds = yield* queryBounds(table, plan, limits.indexBytes);
385
+ reads.add(tableName);
386
+ yield* charge("scanCalls", 1);
387
+ const maximum = terminal.kind === "count" ? limits.rowsRead - used.rowsRead : limits.rowsReturned - used.rowsReturned;
388
+ const count = terminal.kind === "first" ? 1 : terminal.kind === "take" ? terminal.count : terminal.kind === "paginate" ? terminal.numItems : maximum;
389
+ if (count > maximum) return yield* new AppDatabaseError({ reason: "limit" });
390
+ if (count === 0 && terminal.kind === "take") return [];
391
+ const query = yield* fingerprint(
392
+ crypto,
393
+ JSON.stringify({
394
+ schemaHash,
395
+ table: tableName,
396
+ index: plan.index,
397
+ order: plan.order,
398
+ lower: Encoding_exports.encodeBase64Url(bounds.lower),
399
+ upper: bounds.upper === void 0 ? null : Encoding_exports.encodeBase64Url(bounds.upper)
400
+ })
401
+ );
402
+ const position = terminal.kind === "paginate" && terminal.cursor !== null ? yield* cursors.decode(query, terminal.cursor) : void 0;
403
+ const predicates = [
404
+ sql`i.table_name = ${tableName}`,
405
+ sql`i.index_name = ${plan.index}`,
406
+ sql`i.sort_key >= ${bounds.lower}`
407
+ ];
408
+ if (bounds.upper !== void 0)
409
+ predicates.push(sql`i.sort_key < ${bounds.upper}`);
410
+ if (position !== void 0)
411
+ predicates.push(
412
+ plan.order === "asc" ? sql`i.sort_key > ${position}` : sql`i.sort_key < ${position}`
413
+ );
414
+ const direction = plan.order === "asc" ? sql.literal("ASC") : sql.literal("DESC");
415
+ const limit = terminal.kind === "first" || terminal.kind === "take" ? count : count + 1;
416
+ if (terminal.kind === "count") {
417
+ const rows2 = yield* sql`SELECT i.sort_key FROM app_indexes i WHERE ${sql.and(predicates)} ORDER BY i.sort_key ${direction} LIMIT ${limit}`.pipe(
418
+ Effect_exports.flatMap(Schema_exports.decodeUnknownEffect(Schema_exports.Array(CountRow)))
419
+ );
420
+ yield* charge("rowsRead", rows2.length);
421
+ yield* charge(
422
+ "bytesRead",
423
+ rows2.reduce((sum, row) => sum + row.sort_key.byteLength, 0)
424
+ );
425
+ return rows2.length;
426
+ }
427
+ const rows = yield* sql`SELECT i.sort_key, r.body FROM app_indexes i JOIN app_rows r ON r.table_name = i.table_name AND r.id = i.row_id WHERE ${sql.and(predicates)} ORDER BY i.sort_key ${direction} LIMIT ${limit}`.pipe(
428
+ Effect_exports.flatMap(Schema_exports.decodeUnknownEffect(Schema_exports.Array(ScanRow)))
429
+ );
430
+ yield* charge("rowsRead", rows.length);
431
+ yield* charge(
432
+ "bytesRead",
433
+ rows.reduce(
434
+ (sum, row) => sum + new TextEncoder().encode(row.body).length + row.sort_key.byteLength,
435
+ 0
436
+ )
437
+ );
438
+ if (terminal.kind === "collect" && rows.length > count)
439
+ return yield* new AppDatabaseError({ reason: "limit" });
440
+ const page = rows.slice(0, count);
441
+ yield* charge("rowsReturned", page.length);
442
+ const values = yield* Effect_exports.forEach(page, (row) => decodeBody(row.body));
443
+ if (terminal.kind === "first") return values[0] ?? null;
444
+ if (terminal.kind !== "paginate") return values;
445
+ const last = page.at(-1);
446
+ const isDone = rows.length <= count;
447
+ return {
448
+ page: values,
449
+ isDone,
450
+ continueCursor: isDone || last === void 0 ? null : yield* cursors.encode(query, last.sort_key)
451
+ };
452
+ }
453
+ }
454
+ }).pipe(
455
+ Effect_exports.catchTags({
456
+ SqlError: () => Effect_exports.fail(storageError()),
457
+ SchemaError: () => Effect_exports.fail(storageError())
458
+ }),
459
+ Effect_exports.tapError(
460
+ (error) => Effect_exports.sync(() => {
461
+ failed = error;
462
+ })
463
+ ),
464
+ Effect_exports.provideContext(context)
465
+ )
466
+ );
467
+ const session = {
468
+ readTables: reads,
469
+ changedTables: changes,
470
+ execute,
471
+ once: (key2, expected, work2) => Effect_exports.gen(function* () {
472
+ if (!active) return yield* new AppDatabaseError({ reason: "closed" });
473
+ if (!writable) return yield* new AppDatabaseError({ reason: "readonly" });
474
+ const rows = yield* sql`SELECT fingerprint, result FROM app_mutation_receipts WHERE id = ${key2}`.pipe(
475
+ Effect_exports.flatMap(
476
+ Schema_exports.decodeUnknownEffect(
477
+ Schema_exports.Array(
478
+ Schema_exports.Struct({ fingerprint: Schema_exports.String, result: Schema_exports.String })
479
+ )
480
+ )
481
+ ),
482
+ Effect_exports.mapError(storageError)
483
+ );
484
+ const saved = rows[0];
485
+ if (saved !== void 0) {
486
+ if (saved.fingerprint !== expected)
487
+ return yield* new AppDatabaseError({ reason: "replay" });
488
+ return yield* Schema_exports.decodeUnknownEffect(Schema_exports.fromJsonString(Schema_exports.Json))(
489
+ saved.result
490
+ ).pipe(Effect_exports.mapError(storageError));
491
+ }
492
+ const result = yield* work2();
493
+ const encoded = yield* Schema_exports.encodeEffect(Schema_exports.fromJsonString(Schema_exports.Json))(
494
+ result
495
+ ).pipe(Effect_exports.mapError(storageError));
496
+ if (new TextEncoder().encode(encoded).byteLength > 1024 * 1024)
497
+ return yield* new AppDatabaseError({ reason: "limit" });
498
+ yield* sql`INSERT INTO app_mutation_receipts (id, fingerprint, result) VALUES (${key2}, ${expected}, ${encoded})`.pipe(
499
+ Effect_exports.mapError(storageError)
500
+ );
501
+ return result;
502
+ })
503
+ };
504
+ return yield* Effect_exports.suspend(() => work(session)).pipe(
505
+ Effect_exports.tap(
506
+ () => gate.withPermits(1)(
507
+ Effect_exports.suspend(() => failed === void 0 ? Effect_exports.void : Effect_exports.fail(failed))
508
+ )
509
+ ),
510
+ Effect_exports.ensuring(
511
+ Effect_exports.sync(() => {
512
+ active = false;
513
+ })
514
+ )
515
+ );
516
+ })
517
+ ).pipe(Effect_exports.catchTag("SqlError", () => Effect_exports.fail(storageError())));
518
+ return {
519
+ schema,
520
+ schemaHash,
521
+ read: (work) => run(false, work),
522
+ mutate: (work) => run(true, work)
523
+ };
524
+ });
525
+
526
+ // ../app-data/src/implementation/promise.ts
527
+ var promiseTable = (session, table, signal) => {
528
+ const execute = (input) => Effect_exports.runPromise(
529
+ Schema_exports.decodeUnknownEffect(DatabaseOperation)(input).pipe(Effect_exports.flatMap(session.execute)),
530
+ { signal }
531
+ );
532
+ const query = (plan) => ({
533
+ order: (direction) => query({ ...plan, order: direction }),
534
+ collect: async () => Schema_exports.decodeUnknownSync(Schema_exports.Array(Row))(
535
+ await execute({ kind: "query", plan, terminal: { kind: "collect" } })
536
+ ),
537
+ count: async () => Schema_exports.decodeUnknownSync(Schema_exports.Int)(
538
+ await execute({ kind: "query", plan, terminal: { kind: "count" } })
539
+ ),
540
+ first: async () => Schema_exports.decodeUnknownSync(Schema_exports.NullOr(Row))(
541
+ await execute({ kind: "query", plan, terminal: { kind: "first" } })
542
+ ),
543
+ take: async (count) => Schema_exports.decodeUnknownSync(Schema_exports.Array(Row))(
544
+ await execute({ kind: "query", plan, terminal: { kind: "take", count } })
545
+ ),
546
+ paginate: async (options) => Schema_exports.decodeUnknownSync(PaginationResult)(
547
+ await execute({ kind: "query", plan, terminal: { kind: "paginate", ...options } })
548
+ )
549
+ });
550
+ return {
551
+ get: async (id) => Schema_exports.decodeUnknownSync(Schema_exports.NullOr(Row))(await execute({ kind: "get", table, id })),
552
+ insert: async (value) => Schema_exports.decodeUnknownSync(Row)(await execute({ kind: "insert", table, value })),
553
+ update: async (id, patch) => Schema_exports.decodeUnknownSync(Schema_exports.NullOr(Row))(
554
+ await execute({ kind: "update", table, id, patch })
555
+ ),
556
+ delete: async (id) => Schema_exports.decodeUnknownSync(Schema_exports.Boolean)(await execute({ kind: "delete", table, id })),
557
+ withIndex: (index, range) => {
558
+ const ranges = /* @__PURE__ */ new WeakMap();
559
+ const makeRange = (clauses2) => {
560
+ const predicate = (op) => (field, value) => makeRange([
561
+ ...clauses2,
562
+ Schema_exports.decodeUnknownSync(RangeClause)({
563
+ field,
564
+ op,
565
+ value: op === "eq" && value === void 0 ? null : value
566
+ })
567
+ ]);
568
+ const result = {
569
+ eq: predicate("eq"),
570
+ gt: predicate("gt"),
571
+ gte: predicate("gte"),
572
+ lt: predicate("lt"),
573
+ lte: predicate("lte")
574
+ };
575
+ ranges.set(result, clauses2);
576
+ return result;
577
+ };
578
+ const selected = range === void 0 ? makeRange([]) : range(makeRange([]));
579
+ const clauses = ranges.get(selected);
580
+ if (clauses === void 0) throw new Error("Return the supplied index range");
581
+ return query({ table, index, order: "asc", clauses });
582
+ }
583
+ };
584
+ };
585
+
586
+ export {
587
+ parseDatabaseSchema,
588
+ makeSqliteDatabase,
589
+ promiseTable
590
+ };
@@ -0,0 +1,56 @@
1
+ import {
2
+ HttpApiEndpoint_exports,
3
+ HttpApiGroup_exports,
4
+ HttpApi_exports,
5
+ UiFailed,
6
+ UiForbidden,
7
+ UiUnauthorized
8
+ } from "./chunk-3ANFZFCV.js";
9
+ import {
10
+ Schema_exports
11
+ } from "./chunk-2OTCEKL2.js";
12
+
13
+ // src/contracts/ui-auth.ts
14
+ var AppSignInId = Schema_exports.String.check(Schema_exports.isPattern(/^[a-f0-9]{64}$/)).pipe(
15
+ Schema_exports.brand("AppSignInId")
16
+ );
17
+ var AppSignInCode = Schema_exports.RedactedFromValue(
18
+ Schema_exports.String.check(Schema_exports.isPattern(/^[a-f0-9]{64}$/))
19
+ );
20
+ var AppReturnPath = Schema_exports.String.check(
21
+ Schema_exports.isMaxLength(8192),
22
+ Schema_exports.makeFilter((value) => {
23
+ if (!value.startsWith("/") || value.startsWith("//") || /[\\\u0000-\u0020\u007f]/.test(value))
24
+ return false;
25
+ try {
26
+ const url = new URL(value, "https://app.invalid");
27
+ return url.origin === "https://app.invalid" && !/^\/(?:_executor|dashboard|auth|v1|mcp)(?:\/|$)/.test(decodeURIComponent(url.pathname));
28
+ } catch {
29
+ return false;
30
+ }
31
+ })
32
+ ).pipe(Schema_exports.brand("AppReturnPath"));
33
+ var AppSignInCallback = Schema_exports.Struct({ request: AppSignInId, code: AppSignInCode });
34
+ var AppSignInApi = HttpApi_exports.make("app-sign-in").add(
35
+ HttpApiGroup_exports.make("appSignIn").add(
36
+ HttpApiEndpoint_exports.post("start", "/_executor/auth/start", {
37
+ payload: Schema_exports.Struct({ returnTo: AppReturnPath }),
38
+ success: Schema_exports.Struct({ url: Schema_exports.String }),
39
+ error: [UiForbidden, UiFailed]
40
+ })
41
+ ).add(
42
+ HttpApiEndpoint_exports.post("complete", "/_executor/auth/complete", {
43
+ payload: AppSignInCallback,
44
+ success: Schema_exports.Struct({ returnTo: AppReturnPath }),
45
+ error: [UiUnauthorized, UiForbidden, UiFailed]
46
+ })
47
+ )
48
+ );
49
+
50
+ export {
51
+ AppSignInId,
52
+ AppSignInCode,
53
+ AppReturnPath,
54
+ AppSignInCallback,
55
+ AppSignInApi
56
+ };