apps 0.0.1-beta.3 → 0.0.1-beta.31
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +68 -44
- package/framework-reference.json +1 -1
- package/js/{chunk-RN2MXB4R.js → chunk-3FJYVAE4.js} +128 -24
- package/js/chunk-4OKYLVU4.js +118 -0
- package/js/{chunk-LGIYBDWA.js → chunk-5DLG2FVN.js} +65 -1
- package/js/{chunk-PLCMJREA.js → chunk-5JVNM3CQ.js} +60 -20
- package/js/chunk-5XJR4XGW.js +254 -0
- package/js/{chunk-FZJOYIZO.js → chunk-6KG4DZD7.js} +1 -1
- package/js/{chunk-EVJUVWN2.js → chunk-6ZJ2H6P4.js} +2 -2
- package/js/{chunk-NQ3OMCA5.js → chunk-AUFVX4KM.js} +2 -2
- package/js/{chunk-D47C7KG5.js → chunk-AYM2FUI5.js} +2 -2
- package/js/{chunk-5MQZEB6Y.js → chunk-BGALSHLT.js} +37 -12
- package/js/{chunk-QKHR7BMF.js → chunk-CJY5X26R.js} +3 -3
- package/js/{chunk-M6ZRRIBI.js → chunk-DASNNAP4.js} +1 -1
- package/js/{chunk-ZCAMUXSG.js → chunk-ETLILMHY.js} +3 -4
- package/js/{chunk-FW5HBOIK.js → chunk-EXGKN554.js} +2005 -1710
- package/js/{chunk-SATWJKN6.js → chunk-FBBXFFFJ.js} +1 -1
- package/js/{chunk-JN55AYQH.js → chunk-FULRJSWU.js} +61 -32
- package/js/{chunk-HDTGZWP2.js → chunk-GG566OOE.js} +139 -32
- package/js/chunk-GZ4UHXRT.js +92 -0
- package/js/{chunk-YEJOQEII.js → chunk-HW3DPBZR.js} +45 -7
- package/js/{chunk-HDJH3RPR.js → chunk-MFHUR5SB.js} +2 -2
- package/js/{chunk-MYYEW3RA.js → chunk-N72RKJ5E.js} +984 -61
- package/js/{chunk-WFSQXYUT.js → chunk-NPGRURDG.js} +390 -18
- package/js/chunk-OD3KFKZD.js +1617 -0
- package/js/{chunk-FDNTX5QJ.js → chunk-OX233L7N.js} +2 -2
- package/js/{chunk-G7ZIRKMK.js → chunk-QYM4STZW.js} +118 -197
- package/js/chunk-RULZPNGP.js +801 -0
- package/js/{chunk-BMOIAIVR.js → chunk-UMCMZFXW.js} +49 -1
- package/js/{chunk-J7O55ZV7.js → chunk-W7F23NQ2.js} +419 -191
- package/js/chunk-WG5DFZFT.js +42 -0
- package/js/{chunk-T2LAZCAD.js → chunk-ZOY7PDMI.js} +1 -1
- package/js/client.js +120 -84
- package/js/contracts.js +110 -16
- package/js/effect.js +20 -20
- package/js/{es-APDZKREY.js → es-DIULA3ZF.js} +62 -1659
- package/js/graphql.js +58 -54
- package/js/host.js +20 -20
- package/js/index.js +247 -204
- package/js/mcp/effect.js +24 -22
- package/js/mcp/stdio.js +35 -30
- package/js/mcp.js +105 -68
- package/js/openapi.js +4087 -1503
- package/js/react.js +3 -3
- package/js/skills/effect.js +5 -3
- package/js/skills.js +15 -15
- package/js/storage/facet.js +4 -4
- package/js/ui/auth/contracts.js +2 -2
- package/js/ui/auth.js +5 -5
- package/js/ui/contracts.js +5 -4
- package/js/ui/serving.js +8516 -214
- package/package.json +1 -1
- package/runtime.json +1 -1
- package/types/app-data/src/contracts/database.d.ts +33 -6
- package/types/app-data/src/implementation/schema.d.ts +2 -17
- package/types/apps/src/contracts/api-response-error.d.ts +4 -0
- package/types/apps/src/contracts/app.d.ts +7 -6
- package/types/apps/src/contracts/failure.d.ts +54 -0
- package/types/apps/src/contracts/graphql.d.ts +2 -1
- package/types/apps/src/contracts/host.d.ts +34 -11
- package/types/apps/src/contracts/mcp.d.ts +91 -10
- package/types/apps/src/contracts/network.d.ts +84 -0
- package/types/apps/src/contracts/openapi-compile.d.ts +31 -3
- package/types/apps/src/contracts/openapi.d.ts +45 -9
- package/types/apps/src/contracts/operations.d.ts +5 -6
- package/types/apps/src/contracts/protocol-version.d.ts +2 -2
- package/types/apps/src/contracts/protocols/1.d.ts +251 -69
- package/types/apps/src/contracts/protocols/2.d.ts +710 -0
- package/types/apps/src/contracts/protocols/3.d.ts +716 -0
- package/types/apps/src/contracts/protocols/4.d.ts +1298 -0
- package/types/apps/src/contracts/protocols/5.d.ts +1174 -0
- package/types/apps/src/contracts/protocols/6.d.ts +1620 -0
- package/types/apps/src/contracts/protocols/7.d.ts +1784 -0
- package/types/apps/src/contracts/protocols/8.d.ts +1119 -0
- package/types/apps/src/contracts/protocols/oauth.d.ts +89 -0
- package/types/apps/src/contracts/provider-error.d.ts +9 -0
- package/types/apps/src/contracts/provider.d.ts +115 -10
- package/types/apps/src/contracts/router.d.ts +59 -0
- package/types/apps/src/contracts/skills.d.ts +18 -5
- package/types/apps/src/contracts/storage.d.ts +3 -3
- package/types/apps/src/contracts/ui.d.ts +18 -0
- package/types/apps/src/contracts/workflows.d.ts +34 -3
- package/types/apps/src/graphql.d.ts +1 -3
- package/types/apps/src/implementation/account-router.d.ts +12 -0
- package/types/apps/src/implementation/app.d.ts +5 -4
- package/types/apps/src/implementation/browser-scripts.gen.d.ts +6 -0
- package/types/apps/src/implementation/catalog-cache.d.ts +34 -4
- package/types/apps/src/implementation/elicitation.d.ts +9 -9
- package/types/apps/src/implementation/failure-detail.d.ts +46 -0
- package/types/apps/src/implementation/graphql-catalog.d.ts +4 -7
- package/types/apps/src/implementation/graphql.d.ts +4 -3
- package/types/apps/src/implementation/input-problems.d.ts +4 -1
- package/types/apps/src/implementation/mcp-call.d.ts +6 -5
- package/types/apps/src/implementation/mcp-catalog.d.ts +7 -8
- package/types/apps/src/implementation/mcp-client.d.ts +49 -25
- package/types/apps/src/implementation/mcp-stdio.d.ts +1 -1
- package/types/apps/src/implementation/mcp-tools.d.ts +2 -1
- package/types/apps/src/implementation/mcp.d.ts +52 -25
- package/types/apps/src/implementation/network.d.ts +16 -0
- package/types/apps/src/implementation/openapi-compile.d.ts +27 -6
- package/types/apps/src/implementation/openapi-document.d.ts +46 -19
- package/types/apps/src/implementation/openapi-names.d.ts +9 -4
- package/types/apps/src/implementation/openapi-request.d.ts +10 -2
- package/types/apps/src/implementation/openapi-source.d.ts +8 -6
- package/types/apps/src/implementation/openapi-upgrade.d.ts +4 -0
- package/types/apps/src/implementation/operations.d.ts +36 -3
- package/types/apps/src/implementation/protocol-operations.d.ts +6 -4
- package/types/apps/src/implementation/provider-error.d.ts +28 -1
- package/types/apps/src/implementation/provider.d.ts +19 -5
- package/types/apps/src/implementation/router-catalog.d.ts +224 -0
- package/types/apps/src/implementation/router.d.ts +68 -0
- package/types/apps/src/implementation/runtime-yield.d.ts +7 -0
- package/types/apps/src/implementation/schema.d.ts +80 -1
- package/types/apps/src/implementation/skills.d.ts +2 -2
- package/types/apps/src/implementation/storage.d.ts +5 -3
- package/types/apps/src/implementation/ui-account-notice.d.ts +9 -0
- package/types/apps/src/implementation/ui-client.d.ts +2 -2
- package/types/apps/src/implementation/ui-document.d.ts +5 -0
- package/types/apps/src/implementation/ui-errors.d.ts +1 -1
- package/types/apps/src/implementation/ui-serving.d.ts +10 -4
- package/types/apps/src/implementation/ui-watch.d.ts +1 -1
- package/types/apps/src/implementation/upstream-error.d.ts +7 -0
- package/types/apps/src/implementation/webhooks.d.ts +1 -1
- package/types/apps/src/implementation/workflow-context.d.ts +11 -3
- package/types/apps/src/index.d.ts +29 -11
- package/types/apps/src/mcp-stdio.d.ts +2 -5
- package/types/apps/src/mcp.d.ts +25 -5
- package/types/apps/src/openapi.d.ts +6 -6
- package/types/apps/src/skills.d.ts +4 -4
- package/types/telemetry/src/browser-operations.d.ts +5 -2
- package/types/telemetry/src/config.d.ts +2 -2
- package/types/utils/src/api-error.d.ts +48 -0
- package/js/chunk-PYUYJRSK.js +0 -93
- package/js/chunk-SWPD52J7.js +0 -35
- package/js/chunk-W7D7WVSY.js +0 -18
- package/js/chunk-Z5NMEGJN.js +0 -29
- package/js/chunk-ZJWDMTE3.js +0 -63
- package/types/apps/src/contracts/dynamic-tools.d.ts +0 -13
- package/types/apps/src/implementation/account-operations.d.ts +0 -151
- package/types/apps/src/implementation/dynamic-tools.d.ts +0 -8
|
@@ -1,26 +1,32 @@
|
|
|
1
1
|
import {
|
|
2
2
|
prepareElicitation
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-W7F23NQ2.js";
|
|
4
4
|
import {
|
|
5
5
|
fromPromise
|
|
6
|
-
} from "./chunk-
|
|
6
|
+
} from "./chunk-5XJR4XGW.js";
|
|
7
|
+
import {
|
|
8
|
+
bodyUpstreamError
|
|
9
|
+
} from "./chunk-4OKYLVU4.js";
|
|
7
10
|
import {
|
|
8
11
|
ElicitationFailed,
|
|
9
12
|
McpError,
|
|
13
|
+
McpServerHeader,
|
|
10
14
|
McpToolMetadata,
|
|
11
15
|
McpToolResult,
|
|
16
|
+
RouterIcon,
|
|
12
17
|
ToolResultObservation,
|
|
13
18
|
defaultElicitationLimits,
|
|
14
19
|
defaultMcpClientLimits,
|
|
15
20
|
mcpSdkTimerCeilingMs
|
|
16
|
-
} from "./chunk-
|
|
21
|
+
} from "./chunk-N72RKJ5E.js";
|
|
17
22
|
import {
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
23
|
+
jsonSchemaDecoder,
|
|
24
|
+
nestJsonSchema,
|
|
25
|
+
preparedJsonSchemaDecoder
|
|
26
|
+
} from "./chunk-NPGRURDG.js";
|
|
21
27
|
import {
|
|
22
28
|
JsonObject
|
|
23
|
-
} from "./chunk-
|
|
29
|
+
} from "./chunk-FBBXFFFJ.js";
|
|
24
30
|
import {
|
|
25
31
|
Clock_exports,
|
|
26
32
|
Deferred_exports,
|
|
@@ -29,29 +35,79 @@ import {
|
|
|
29
35
|
Option_exports,
|
|
30
36
|
Queue_exports,
|
|
31
37
|
Schema_exports
|
|
32
|
-
} from "./chunk-
|
|
38
|
+
} from "./chunk-EXGKN554.js";
|
|
33
39
|
|
|
34
40
|
// src/implementation/mcp-tools.ts
|
|
41
|
+
var resultFields = {
|
|
42
|
+
content: { type: "array", items: { type: "object" } },
|
|
43
|
+
structuredContent: { type: "object" },
|
|
44
|
+
isError: { type: "boolean" },
|
|
45
|
+
_meta: { type: "object" }
|
|
46
|
+
};
|
|
47
|
+
var definitionReference = /^#\/(?:\$defs|definitions)\/[^/]+$/;
|
|
48
|
+
var locating = /* @__PURE__ */ new Set(["$id", "$anchor", "$dynamicAnchor", "$recursiveAnchor"]);
|
|
49
|
+
var onlyDefinitionReferences = (value) => Array.isArray(value) ? value.every(onlyDefinitionReferences) : value === null || typeof value !== "object" ? true : Object.entries(value).every(
|
|
50
|
+
([key, item]) => locating.has(key) || key === "$dynamicRef" || key === "$recursiveRef" ? false : key === "$ref" ? typeof item === "string" && definitionReference.test(item) : onlyDefinitionReferences(item)
|
|
51
|
+
);
|
|
52
|
+
var placed = (structuredContent, pointer) => {
|
|
53
|
+
if (onlyDefinitionReferences(structuredContent)) {
|
|
54
|
+
const { $defs, definitions, $schema: _draft, ...schema } = structuredContent;
|
|
55
|
+
return {
|
|
56
|
+
schema,
|
|
57
|
+
root: {
|
|
58
|
+
...$defs === void 0 ? {} : { $defs },
|
|
59
|
+
...definitions === void 0 ? {} : { definitions }
|
|
60
|
+
}
|
|
61
|
+
};
|
|
62
|
+
}
|
|
63
|
+
try {
|
|
64
|
+
return { schema: nestJsonSchema(structuredContent, pointer), root: {} };
|
|
65
|
+
} catch {
|
|
66
|
+
return { schema: structuredContent, root: {} };
|
|
67
|
+
}
|
|
68
|
+
};
|
|
69
|
+
var resultSchema = (structuredContent) => {
|
|
70
|
+
if (structuredContent === void 0)
|
|
71
|
+
return { type: "object", properties: resultFields, required: ["content"] };
|
|
72
|
+
const { schema, root } = placed(structuredContent, "#/anyOf/0/properties/structuredContent");
|
|
73
|
+
return {
|
|
74
|
+
// The envelope's keywords mean the same in every draft, so the server's draft applies.
|
|
75
|
+
...structuredContent.$schema === void 0 ? {} : { $schema: structuredContent.$schema },
|
|
76
|
+
...root,
|
|
77
|
+
anyOf: [
|
|
78
|
+
{
|
|
79
|
+
type: "object",
|
|
80
|
+
properties: { ...resultFields, structuredContent: schema, isError: { const: false } },
|
|
81
|
+
required: ["content", "structuredContent"]
|
|
82
|
+
},
|
|
83
|
+
{
|
|
84
|
+
type: "object",
|
|
85
|
+
properties: { ...resultFields, isError: { const: true } },
|
|
86
|
+
required: ["content", "isError"]
|
|
87
|
+
}
|
|
88
|
+
]
|
|
89
|
+
};
|
|
90
|
+
};
|
|
35
91
|
var adaptMcpTool = (client, tool) => Effect_exports.gen(function* () {
|
|
36
92
|
const decoder = yield* jsonSchemaDecoder(tool.inputSchema).pipe(
|
|
37
93
|
Effect_exports.mapError(() => new McpError({ phase: "schema", reason: "invalid_response" }))
|
|
38
94
|
);
|
|
39
|
-
const output = tool.outputSchema
|
|
40
|
-
|
|
41
|
-
Effect_exports.mapError(() => new McpError({ phase: "schema", reason: "invalid_response" }))
|
|
42
|
-
)
|
|
43
|
-
);
|
|
95
|
+
const output = preparedJsonSchemaDecoder(resultSchema(tool.outputSchema));
|
|
96
|
+
const { outputSchema: _upstream, ...metadata } = tool;
|
|
44
97
|
const adapted = {
|
|
45
|
-
...
|
|
98
|
+
...metadata,
|
|
46
99
|
description: tool.description ?? tool.title ?? tool.name,
|
|
47
100
|
input: decoder,
|
|
101
|
+
output: output.decoder,
|
|
48
102
|
...tool.annotations?.readOnlyHint === void 0 ? {} : { readOnly: tool.annotations.readOnlyHint },
|
|
49
103
|
run: (context, input) => Effect_exports.gen(function* () {
|
|
50
104
|
const arguments_ = yield* Schema_exports.decodeUnknownEffect(decoder)(input).pipe(
|
|
51
105
|
Effect_exports.flatMap(Schema_exports.decodeUnknownEffect(JsonObject)),
|
|
52
106
|
Effect_exports.mapError(() => new McpError({ phase: "call", reason: "invalid_input" }))
|
|
53
107
|
);
|
|
54
|
-
|
|
108
|
+
yield* output.compile.pipe(
|
|
109
|
+
Effect_exports.mapError(() => new McpError({ phase: "schema", reason: "invalid_response" }))
|
|
110
|
+
);
|
|
55
111
|
const result = yield* client.call(tool.name, arguments_, context);
|
|
56
112
|
if (result.isError === true) {
|
|
57
113
|
(yield* ToolResultObservation).failed();
|
|
@@ -60,17 +116,13 @@ var adaptMcpTool = (client, tool) => Effect_exports.gen(function* () {
|
|
|
60
116
|
"error.type": "McpToolError"
|
|
61
117
|
});
|
|
62
118
|
}
|
|
63
|
-
if (outputDecoder !== void 0 && !result.isError)
|
|
64
|
-
yield* Schema_exports.decodeUnknownEffect(outputDecoder)(result.structuredContent).pipe(
|
|
65
|
-
Effect_exports.mapError(() => new McpError({ phase: "call", reason: "invalid_response" }))
|
|
66
|
-
);
|
|
67
119
|
return result;
|
|
68
120
|
})
|
|
69
121
|
};
|
|
70
122
|
return adapted;
|
|
71
123
|
});
|
|
72
124
|
var adaptMcpTools = (client) => Effect_exports.gen(function* () {
|
|
73
|
-
const metadata = yield* client.list;
|
|
125
|
+
const { tools: metadata } = yield* client.list;
|
|
74
126
|
const entries = yield* Effect_exports.forEach(
|
|
75
127
|
metadata,
|
|
76
128
|
(tool) => adaptMcpTool(client, tool).pipe(Effect_exports.map((adapted) => [tool.name, adapted]))
|
|
@@ -79,7 +131,11 @@ var adaptMcpTools = (client) => Effect_exports.gen(function* () {
|
|
|
79
131
|
});
|
|
80
132
|
|
|
81
133
|
// src/implementation/mcp-client.ts
|
|
82
|
-
import {
|
|
134
|
+
import {
|
|
135
|
+
ErrorCode as ErrorCode2,
|
|
136
|
+
ListToolsResultSchema,
|
|
137
|
+
McpError as ProtocolError2
|
|
138
|
+
} from "@modelcontextprotocol/sdk/types.js";
|
|
83
139
|
|
|
84
140
|
// src/implementation/mcp-call.ts
|
|
85
141
|
import {
|
|
@@ -208,6 +264,20 @@ var mcpCall = (client, name, input, context, timeoutMs, failure) => Effect_expor
|
|
|
208
264
|
);
|
|
209
265
|
|
|
210
266
|
// src/implementation/mcp-client.ts
|
|
267
|
+
var clientCodes = /* @__PURE__ */ new Set([
|
|
268
|
+
ErrorCode2.RequestTimeout,
|
|
269
|
+
ErrorCode2.ConnectionClosed
|
|
270
|
+
]);
|
|
271
|
+
var answeredError = (error) => {
|
|
272
|
+
if (!(error instanceof ProtocolError2) || clientCodes.has(error.code)) return void 0;
|
|
273
|
+
const prefix = `MCP error ${error.code}: `;
|
|
274
|
+
return bodyUpstreamError({
|
|
275
|
+
error: {
|
|
276
|
+
code: error.code,
|
|
277
|
+
message: error.message.startsWith(prefix) ? error.message.slice(prefix.length) : error.message
|
|
278
|
+
}
|
|
279
|
+
});
|
|
280
|
+
};
|
|
211
281
|
var mcpJsonSchemaValidator = {
|
|
212
282
|
getValidator(document) {
|
|
213
283
|
const decoder = Effect_exports.runSync(jsonSchemaDecoder(document));
|
|
@@ -233,7 +303,7 @@ function mcpClient(withClient, timeoutMs, failure) {
|
|
|
233
303
|
do {
|
|
234
304
|
const page = yield* Effect_exports.tryPromise({
|
|
235
305
|
// This session only reads metadata. listTools() also eagerly compiles
|
|
236
|
-
// every output validator;
|
|
306
|
+
// every output validator; mcpRouter validates the selected tool on call.
|
|
237
307
|
try: (signal) => client.request(
|
|
238
308
|
{ method: "tools/list", params: cursor === void 0 ? {} : { cursor } },
|
|
239
309
|
ListToolsResultSchema,
|
|
@@ -263,18 +333,52 @@ function mcpClient(withClient, timeoutMs, failure) {
|
|
|
263
333
|
cursors.add(cursor);
|
|
264
334
|
}
|
|
265
335
|
} while (cursor !== void 0);
|
|
266
|
-
|
|
336
|
+
const info = client.getServerVersion();
|
|
337
|
+
const instructions = client.getInstructions();
|
|
338
|
+
const icons = info?.icons?.flatMap(
|
|
339
|
+
(icon) => Option_exports.toArray(Schema_exports.decodeUnknownOption(RouterIcon)(icon))
|
|
340
|
+
);
|
|
341
|
+
const server = Schema_exports.decodeUnknownOption(McpServerHeader)({
|
|
342
|
+
...info?.name === void 0 ? {} : { name: info.name },
|
|
343
|
+
...info?.title === void 0 ? {} : { title: info.title },
|
|
344
|
+
...info?.version === void 0 ? {} : { version: info.version },
|
|
345
|
+
...info?.description === void 0 ? {} : { description: info.description },
|
|
346
|
+
...info?.websiteUrl === void 0 ? {} : { websiteUrl: info.websiteUrl },
|
|
347
|
+
...icons === void 0 ? {} : { icons },
|
|
348
|
+
...instructions === void 0 ? {} : { instructions }
|
|
349
|
+
});
|
|
350
|
+
return {
|
|
351
|
+
tools: [...tools.values()],
|
|
352
|
+
server: Option_exports.getOrElse(server, () => ({}))
|
|
353
|
+
};
|
|
267
354
|
})
|
|
268
355
|
).pipe(Effect_exports.withSpan("provider.mcp.discover"));
|
|
356
|
+
const check = withClient(
|
|
357
|
+
"discover",
|
|
358
|
+
(client) => Effect_exports.tryPromise({
|
|
359
|
+
try: (signal) => client.request({ method: "tools/list", params: {} }, ListToolsResultSchema, {
|
|
360
|
+
signal,
|
|
361
|
+
timeout: timeoutMs
|
|
362
|
+
}),
|
|
363
|
+
catch: (error) => failure("discover", error)
|
|
364
|
+
}).pipe(
|
|
365
|
+
Effect_exports.asVoid,
|
|
366
|
+
Effect_exports.withSpan("provider.mcp.request", {
|
|
367
|
+
kind: "client",
|
|
368
|
+
attributes: { "rpc.system.name": "jsonrpc", "rpc.method": "tools/list" }
|
|
369
|
+
})
|
|
370
|
+
)
|
|
371
|
+
).pipe(Effect_exports.withSpan("provider.mcp.check"));
|
|
269
372
|
const call = (name, input, context) => withClient("call", (client) => mcpCall(client, name, input, context, timeoutMs, failure)).pipe(
|
|
270
373
|
Effect_exports.withSpan("provider.mcp.call", { attributes: { "mcp.tool.name": name } })
|
|
271
374
|
);
|
|
272
|
-
return { list, call };
|
|
375
|
+
return { list, check, call };
|
|
273
376
|
}
|
|
274
377
|
|
|
275
378
|
export {
|
|
276
379
|
adaptMcpTool,
|
|
277
380
|
adaptMcpTools,
|
|
381
|
+
answeredError,
|
|
278
382
|
mcpJsonSchemaValidator,
|
|
279
383
|
mcpClient
|
|
280
384
|
};
|
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
import {
|
|
2
|
+
ProviderError,
|
|
3
|
+
maxUpstreamMessageLength
|
|
4
|
+
} from "./chunk-5DLG2FVN.js";
|
|
5
|
+
import {
|
|
6
|
+
AccountId
|
|
7
|
+
} from "./chunk-FBBXFFFJ.js";
|
|
8
|
+
import {
|
|
9
|
+
Option_exports,
|
|
10
|
+
Schema_exports
|
|
11
|
+
} from "./chunk-EXGKN554.js";
|
|
12
|
+
|
|
13
|
+
// src/implementation/upstream-error.ts
|
|
14
|
+
var ErrorToken = Schema_exports.String.check(Schema_exports.isPattern(/^[A-Za-z0-9._-]{1,128}$/));
|
|
15
|
+
var JsonRpcError = Schema_exports.Struct({
|
|
16
|
+
error: Schema_exports.Struct({ code: Schema_exports.Int, message: Schema_exports.String })
|
|
17
|
+
});
|
|
18
|
+
var OAuthError = Schema_exports.Struct({
|
|
19
|
+
error: ErrorToken,
|
|
20
|
+
error_description: Schema_exports.optional(Schema_exports.String)
|
|
21
|
+
});
|
|
22
|
+
var bounded = (message) => message.length <= maxUpstreamMessageLength ? message : `${message.slice(0, maxUpstreamMessageLength - 1)}\u2026`;
|
|
23
|
+
var isShortenedUpstream = (message) => message.length === maxUpstreamMessageLength && message.endsWith("\u2026");
|
|
24
|
+
var stated = (code, message) => ({
|
|
25
|
+
code,
|
|
26
|
+
...message === void 0 || message === "" ? {} : { message: bounded(message) }
|
|
27
|
+
});
|
|
28
|
+
var bodyUpstreamError = (json) => {
|
|
29
|
+
const rpc = Schema_exports.decodeUnknownOption(JsonRpcError)(json);
|
|
30
|
+
if (Option_exports.isSome(rpc)) return stated(rpc.value.error.code, rpc.value.error.message);
|
|
31
|
+
const oauth = Schema_exports.decodeUnknownOption(OAuthError)(json);
|
|
32
|
+
if (Option_exports.isSome(oauth)) return stated(oauth.value.error, oauth.value.error_description);
|
|
33
|
+
return void 0;
|
|
34
|
+
};
|
|
35
|
+
var authParam = /([A-Za-z][A-Za-z0-9_-]*)\s*=\s*(?:"((?:[^"\\]|\\.)*)"|([^\s,"]+))/g;
|
|
36
|
+
var challengeUpstreamError = (header) => {
|
|
37
|
+
const bearer = header === void 0 ? -1 : header.search(/\bBearer\b/i);
|
|
38
|
+
if (header === void 0 || bearer === -1) return void 0;
|
|
39
|
+
const params = /* @__PURE__ */ new Map();
|
|
40
|
+
for (const [, name, quoted, token] of header.slice(bearer + "Bearer".length).matchAll(authParam))
|
|
41
|
+
if (name !== void 0 && !params.has(name.toLowerCase()))
|
|
42
|
+
params.set(name.toLowerCase(), quoted?.replace(/\\(.)/g, "$1") ?? token ?? "");
|
|
43
|
+
const code = Schema_exports.decodeUnknownOption(ErrorToken)(params.get("error"));
|
|
44
|
+
return Option_exports.isNone(code) ? void 0 : stated(code.value, params.get("error_description"));
|
|
45
|
+
};
|
|
46
|
+
|
|
47
|
+
// src/implementation/provider-error.ts
|
|
48
|
+
var providerError = ({
|
|
49
|
+
reason,
|
|
50
|
+
status,
|
|
51
|
+
accountId,
|
|
52
|
+
phase,
|
|
53
|
+
upstream
|
|
54
|
+
}) => new ProviderError({
|
|
55
|
+
reason,
|
|
56
|
+
...status === void 0 ? {} : { status },
|
|
57
|
+
...accountId === void 0 ? {} : { accountId },
|
|
58
|
+
...phase === void 0 ? {} : { phase },
|
|
59
|
+
...upstream === void 0 ? {} : { upstream }
|
|
60
|
+
});
|
|
61
|
+
function parseProviderError(error) {
|
|
62
|
+
return Schema_exports.decodeUnknownOption(ProviderError)(error).pipe(Option_exports.map(providerError));
|
|
63
|
+
}
|
|
64
|
+
function providerErrorDetail(error, detail) {
|
|
65
|
+
return providerError({
|
|
66
|
+
...error,
|
|
67
|
+
phase: error.phase ?? detail.phase,
|
|
68
|
+
upstream: error.upstream ?? detail.upstream
|
|
69
|
+
});
|
|
70
|
+
}
|
|
71
|
+
function httpProviderError(status, headers = {}) {
|
|
72
|
+
const upstream = challengeUpstreamError(headers["www-authenticate"]);
|
|
73
|
+
if (status >= 500 && status <= 599)
|
|
74
|
+
return providerError({ reason: "unavailable", status, upstream });
|
|
75
|
+
if (status === 401) return providerError({ reason: "unauthorized", status, upstream });
|
|
76
|
+
if (status === 429) return providerError({ reason: "rate_limited", status, upstream });
|
|
77
|
+
if (status !== 403) return void 0;
|
|
78
|
+
const retry = headers["retry-after"];
|
|
79
|
+
if (headers["x-ratelimit-remaining"] === "0" || retry !== void 0 && (/^\d+$/.test(retry) || Number.isFinite(Date.parse(retry))))
|
|
80
|
+
return providerError({ reason: "rate_limited", status, upstream });
|
|
81
|
+
if (typeof upstream?.code === "string" && upstream.code.toLowerCase() === "insufficient_scope")
|
|
82
|
+
return providerError({ reason: "forbidden", status, upstream });
|
|
83
|
+
return providerError({ reason: "rejected", status, upstream });
|
|
84
|
+
}
|
|
85
|
+
function accountProviderError(error, accountId) {
|
|
86
|
+
const parsed = parseProviderError(error);
|
|
87
|
+
const account = Schema_exports.decodeUnknownOption(AccountId)(accountId);
|
|
88
|
+
if (Option_exports.isNone(parsed) || Option_exports.isNone(account)) return error;
|
|
89
|
+
return providerError({ ...parsed.value, accountId: account.value });
|
|
90
|
+
}
|
|
91
|
+
function graphqlProviderError(errors, status) {
|
|
92
|
+
const codes = errors.flatMap((error) => {
|
|
93
|
+
const parsed = Schema_exports.decodeUnknownOption(
|
|
94
|
+
Schema_exports.Struct({
|
|
95
|
+
type: Schema_exports.optional(Schema_exports.String),
|
|
96
|
+
extensions: Schema_exports.optional(Schema_exports.Struct({ code: Schema_exports.optional(Schema_exports.String) }))
|
|
97
|
+
})
|
|
98
|
+
)(error);
|
|
99
|
+
return Option_exports.isSome(parsed) ? [parsed.value.type, parsed.value.extensions?.code] : [];
|
|
100
|
+
});
|
|
101
|
+
if (codes.includes("RATE_LIMITED") || codes.includes("TOO_MANY_REQUESTS"))
|
|
102
|
+
return new ProviderError({ reason: "rate_limited", status });
|
|
103
|
+
if (codes.includes("UNAUTHENTICATED"))
|
|
104
|
+
return new ProviderError({ reason: "unauthorized", status });
|
|
105
|
+
if (codes.includes("FORBIDDEN")) return new ProviderError({ reason: "forbidden", status });
|
|
106
|
+
return void 0;
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
export {
|
|
110
|
+
isShortenedUpstream,
|
|
111
|
+
bodyUpstreamError,
|
|
112
|
+
providerError,
|
|
113
|
+
parseProviderError,
|
|
114
|
+
providerErrorDetail,
|
|
115
|
+
httpProviderError,
|
|
116
|
+
accountProviderError,
|
|
117
|
+
graphqlProviderError
|
|
118
|
+
};
|
|
@@ -1,6 +1,55 @@
|
|
|
1
|
+
import {
|
|
2
|
+
AccountId
|
|
3
|
+
} from "./chunk-FBBXFFFJ.js";
|
|
1
4
|
import {
|
|
2
5
|
Schema_exports
|
|
3
|
-
} from "./chunk-
|
|
6
|
+
} from "./chunk-EXGKN554.js";
|
|
7
|
+
|
|
8
|
+
// src/contracts/failure.ts
|
|
9
|
+
var maxFailureMessageLength = 2048;
|
|
10
|
+
var FailureSource = Schema_exports.Literals(["app", "storage", "service"]);
|
|
11
|
+
var FailureName = Schema_exports.String.check(Schema_exports.isMaxLength(128));
|
|
12
|
+
var FailureCode = Schema_exports.String.check(Schema_exports.isMaxLength(128));
|
|
13
|
+
var FailureMessage = Schema_exports.String.check(Schema_exports.isMaxLength(maxFailureMessageLength));
|
|
14
|
+
var maxFailureFields = 8;
|
|
15
|
+
var maxFailureFieldLength = 256;
|
|
16
|
+
var FailureFieldName = Schema_exports.String.check(
|
|
17
|
+
Schema_exports.isPattern(/^[A-Za-z_$][A-Za-z0-9_$]{0,63}$/)
|
|
18
|
+
);
|
|
19
|
+
var FailureFieldValue = Schema_exports.Union([
|
|
20
|
+
Schema_exports.String.check(Schema_exports.isMaxLength(maxFailureFieldLength)),
|
|
21
|
+
Schema_exports.Finite,
|
|
22
|
+
Schema_exports.Boolean
|
|
23
|
+
]);
|
|
24
|
+
var FailureFields = Schema_exports.Record(FailureFieldName, FailureFieldValue).check(
|
|
25
|
+
Schema_exports.isMaxProperties(maxFailureFields)
|
|
26
|
+
);
|
|
27
|
+
var FailureDetail = {
|
|
28
|
+
source: Schema_exports.optionalKey(FailureSource),
|
|
29
|
+
errorName: Schema_exports.optionalKey(FailureName),
|
|
30
|
+
code: Schema_exports.optionalKey(FailureCode),
|
|
31
|
+
message: Schema_exports.optionalKey(FailureMessage),
|
|
32
|
+
fields: Schema_exports.optionalKey(FailureFields)
|
|
33
|
+
};
|
|
34
|
+
var maxUpstreamMessageLength = 1024;
|
|
35
|
+
var UpstreamError = Schema_exports.Struct({
|
|
36
|
+
code: Schema_exports.Union([
|
|
37
|
+
Schema_exports.Int,
|
|
38
|
+
Schema_exports.String.check(Schema_exports.isMinLength(1), Schema_exports.isMaxLength(128))
|
|
39
|
+
]),
|
|
40
|
+
message: Schema_exports.optionalKey(Schema_exports.String.check(Schema_exports.isMaxLength(maxUpstreamMessageLength)))
|
|
41
|
+
});
|
|
42
|
+
var FailurePhase = Schema_exports.Literals(["connect", "discover", "call"]);
|
|
43
|
+
|
|
44
|
+
// src/contracts/provider-error.ts
|
|
45
|
+
var ProviderError = class extends Schema_exports.TaggedError()("ProviderError", {
|
|
46
|
+
reason: Schema_exports.Literals(["unauthorized", "forbidden", "rate_limited", "unavailable", "rejected"]),
|
|
47
|
+
status: Schema_exports.optional(Schema_exports.Int.check(Schema_exports.isBetween({ minimum: 100, maximum: 599 }))),
|
|
48
|
+
accountId: Schema_exports.optional(AccountId),
|
|
49
|
+
phase: Schema_exports.optional(FailurePhase),
|
|
50
|
+
upstream: Schema_exports.optional(UpstreamError)
|
|
51
|
+
}) {
|
|
52
|
+
};
|
|
4
53
|
|
|
5
54
|
// ../app-cache/src/contracts/cache.ts
|
|
6
55
|
var CacheError = class extends Schema_exports.TaggedError()("CacheError", {
|
|
@@ -76,6 +125,21 @@ var CacheReply = Schema_exports.Union([
|
|
|
76
125
|
]);
|
|
77
126
|
|
|
78
127
|
export {
|
|
128
|
+
maxFailureMessageLength,
|
|
129
|
+
FailureSource,
|
|
130
|
+
FailureName,
|
|
131
|
+
FailureCode,
|
|
132
|
+
FailureMessage,
|
|
133
|
+
maxFailureFields,
|
|
134
|
+
maxFailureFieldLength,
|
|
135
|
+
FailureFieldName,
|
|
136
|
+
FailureFieldValue,
|
|
137
|
+
FailureFields,
|
|
138
|
+
FailureDetail,
|
|
139
|
+
maxUpstreamMessageLength,
|
|
140
|
+
UpstreamError,
|
|
141
|
+
FailurePhase,
|
|
142
|
+
ProviderError,
|
|
79
143
|
CacheError,
|
|
80
144
|
cacheLimits,
|
|
81
145
|
CacheEntry,
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
import {
|
|
2
2
|
AppDatabaseError,
|
|
3
|
+
DatabaseFieldReserved,
|
|
4
|
+
DatabaseLimitExceeded,
|
|
3
5
|
DatabaseLimits,
|
|
4
6
|
DatabaseOperation,
|
|
5
7
|
DatabaseSchema,
|
|
@@ -8,18 +10,21 @@ import {
|
|
|
8
10
|
Row,
|
|
9
11
|
RowMetadata,
|
|
10
12
|
defaultDatabaseLimits,
|
|
11
|
-
defaultDatabaseRuntimeLimits
|
|
12
|
-
|
|
13
|
+
defaultDatabaseRuntimeLimits,
|
|
14
|
+
reservedFieldNames
|
|
15
|
+
} from "./chunk-UMCMZFXW.js";
|
|
13
16
|
import {
|
|
17
|
+
Cause_exports,
|
|
14
18
|
Clock_exports,
|
|
15
19
|
Effect_exports,
|
|
16
20
|
Encoding_exports,
|
|
17
21
|
Schema_exports,
|
|
18
22
|
Semaphore_exports
|
|
19
|
-
} from "./chunk-
|
|
23
|
+
} from "./chunk-EXGKN554.js";
|
|
20
24
|
|
|
21
25
|
// ../app-data/src/implementation/schema.ts
|
|
22
|
-
var metadata =
|
|
26
|
+
var metadata = new Set(reservedFieldNames);
|
|
27
|
+
var reserved = (name) => metadata.has(name);
|
|
23
28
|
var indexesFor = (table) => [{ name: "by_creation", fields: [] }, ...table.indexes].map((index) => ({
|
|
24
29
|
name: index.name,
|
|
25
30
|
fields: [
|
|
@@ -33,23 +38,25 @@ var validScalar = (field, value) => field.kind === "number" ? typeof value === "
|
|
|
33
38
|
return point !== void 0 && point >= 55296 && point <= 57343;
|
|
34
39
|
});
|
|
35
40
|
var parseDatabaseSchema = (input) => Schema_exports.decodeUnknownEffect(DatabaseSchema)(input).pipe(
|
|
41
|
+
Effect_exports.mapError(() => new AppDatabaseError({ reason: "schema" })),
|
|
36
42
|
Effect_exports.flatMap(
|
|
37
43
|
(schema) => Effect_exports.gen(function* () {
|
|
38
|
-
for (const table of Object.
|
|
39
|
-
|
|
44
|
+
for (const [name, table] of Object.entries(schema)) {
|
|
45
|
+
const field = Object.keys(table.fields).find(reserved);
|
|
46
|
+
if (field !== void 0) return yield* new DatabaseFieldReserved({ table: name, field });
|
|
47
|
+
if (new Set(table.indexes.map((index) => index.name)).size !== table.indexes.length)
|
|
40
48
|
return yield* new AppDatabaseError({ reason: "schema" });
|
|
41
|
-
for (const
|
|
42
|
-
if ((
|
|
49
|
+
for (const field2 of Object.values(table.fields)) {
|
|
50
|
+
if ((field2.kind === "id" ? field2.references === void 0 : field2.references !== void 0) || field2.default !== void 0 && !validScalar(field2, field2.default) || field2.references !== void 0 && !Object.hasOwn(schema, field2.references))
|
|
43
51
|
return yield* new AppDatabaseError({ reason: "schema" });
|
|
44
52
|
}
|
|
45
53
|
for (const index of table.indexes)
|
|
46
|
-
if (index.name === "by_creation" || new Set(index.fields).size !== index.fields.length || index.fields.some((
|
|
54
|
+
if (index.name === "by_creation" || new Set(index.fields).size !== index.fields.length || index.fields.some((name2) => fieldFor(table, name2) === void 0))
|
|
47
55
|
return yield* new AppDatabaseError({ reason: "schema" });
|
|
48
56
|
}
|
|
49
57
|
return schema;
|
|
50
58
|
})
|
|
51
|
-
)
|
|
52
|
-
Effect_exports.mapError(() => new AppDatabaseError({ reason: "schema" }))
|
|
59
|
+
)
|
|
53
60
|
);
|
|
54
61
|
var canonicalSchema = (schema) => JSON.stringify(
|
|
55
62
|
Object.fromEntries(
|
|
@@ -248,7 +255,12 @@ var decodeBody = Schema_exports.decodeUnknownEffect(Schema_exports.fromJsonStrin
|
|
|
248
255
|
var storageError = () => new AppDatabaseError({ reason: "storage" });
|
|
249
256
|
var makeSqliteDatabase = (options) => Effect_exports.gen(function* () {
|
|
250
257
|
const { sql, crypto } = options;
|
|
251
|
-
const schema = yield* parseDatabaseSchema(options.schema)
|
|
258
|
+
const schema = yield* parseDatabaseSchema(options.schema).pipe(
|
|
259
|
+
Effect_exports.catchTag(
|
|
260
|
+
"DatabaseFieldReserved",
|
|
261
|
+
() => Effect_exports.fail(new AppDatabaseError({ reason: "schema" }))
|
|
262
|
+
)
|
|
263
|
+
);
|
|
252
264
|
const limits = yield* Schema_exports.decodeUnknownEffect(DatabaseLimits)(
|
|
253
265
|
options.limits ?? defaultDatabaseLimits
|
|
254
266
|
).pipe(Effect_exports.mapError(() => new AppDatabaseError({ reason: "limit" })));
|
|
@@ -295,7 +307,13 @@ var makeSqliteDatabase = (options) => Effect_exports.gen(function* () {
|
|
|
295
307
|
};
|
|
296
308
|
const charge = (name, amount) => Effect_exports.suspend(() => {
|
|
297
309
|
used[name] += amount;
|
|
298
|
-
return used[name] > limits[name] ? Effect_exports.fail(
|
|
310
|
+
return used[name] > limits[name] ? Effect_exports.fail(
|
|
311
|
+
new DatabaseLimitExceeded({
|
|
312
|
+
limit: name,
|
|
313
|
+
maximum: limits[name],
|
|
314
|
+
requested: used[name]
|
|
315
|
+
})
|
|
316
|
+
) : Effect_exports.void;
|
|
299
317
|
});
|
|
300
318
|
const get = (table, id) => Effect_exports.gen(function* () {
|
|
301
319
|
yield* charge("directGets", 1);
|
|
@@ -312,8 +330,13 @@ var makeSqliteDatabase = (options) => Effect_exports.gen(function* () {
|
|
|
312
330
|
const store = (tableName, table, row) => Effect_exports.gen(function* () {
|
|
313
331
|
const meta = yield* Schema_exports.decodeUnknownEffect(RowMetadata)(row);
|
|
314
332
|
const body = JSON.stringify(row);
|
|
315
|
-
|
|
316
|
-
|
|
333
|
+
const bytes = new TextEncoder().encode(body).length;
|
|
334
|
+
if (bytes > limits.valueBytes)
|
|
335
|
+
return yield* new DatabaseLimitExceeded({
|
|
336
|
+
limit: "valueBytes",
|
|
337
|
+
maximum: limits.valueBytes,
|
|
338
|
+
requested: bytes
|
|
339
|
+
});
|
|
317
340
|
const keys = yield* Effect_exports.forEach(
|
|
318
341
|
indexesFor(table),
|
|
319
342
|
(index) => encodeIndexKey(
|
|
@@ -384,9 +407,14 @@ var makeSqliteDatabase = (options) => Effect_exports.gen(function* () {
|
|
|
384
407
|
const bounds = yield* queryBounds(table, plan, limits.indexBytes);
|
|
385
408
|
reads.add(tableName);
|
|
386
409
|
yield* charge("scanCalls", 1);
|
|
387
|
-
const
|
|
388
|
-
const count = terminal.kind === "first" ? 1 : terminal.kind === "take" ? terminal.count : terminal.kind === "paginate" ? terminal.numItems :
|
|
389
|
-
if (
|
|
410
|
+
const remaining = terminal.kind === "count" ? limits.rowsRead - used.rowsRead : limits.rowsReturned - used.rowsReturned;
|
|
411
|
+
const count = terminal.kind === "first" ? 1 : terminal.kind === "take" ? terminal.count : terminal.kind === "paginate" ? terminal.numItems : remaining;
|
|
412
|
+
if ((terminal.kind === "take" || terminal.kind === "paginate") && count > limits.rowsReturned)
|
|
413
|
+
return yield* new DatabaseLimitExceeded({
|
|
414
|
+
limit: "pageSize",
|
|
415
|
+
maximum: limits.rowsReturned,
|
|
416
|
+
requested: count
|
|
417
|
+
});
|
|
390
418
|
if (count === 0 && terminal.kind === "take") return [];
|
|
391
419
|
const query = yield* fingerprint(
|
|
392
420
|
crypto,
|
|
@@ -412,7 +440,10 @@ var makeSqliteDatabase = (options) => Effect_exports.gen(function* () {
|
|
|
412
440
|
plan.order === "asc" ? sql`i.sort_key > ${position}` : sql`i.sort_key < ${position}`
|
|
413
441
|
);
|
|
414
442
|
const direction = plan.order === "asc" ? sql.literal("ASC") : sql.literal("DESC");
|
|
415
|
-
const limit =
|
|
443
|
+
const limit = Math.min(
|
|
444
|
+
terminal.kind === "first" || terminal.kind === "take" ? count : count + 1,
|
|
445
|
+
remaining + 1
|
|
446
|
+
);
|
|
416
447
|
if (terminal.kind === "count") {
|
|
417
448
|
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
449
|
Effect_exports.flatMap(Schema_exports.decodeUnknownEffect(Schema_exports.Array(CountRow)))
|
|
@@ -436,7 +467,11 @@ var makeSqliteDatabase = (options) => Effect_exports.gen(function* () {
|
|
|
436
467
|
)
|
|
437
468
|
);
|
|
438
469
|
if (terminal.kind === "collect" && rows.length > count)
|
|
439
|
-
return yield* new
|
|
470
|
+
return yield* new DatabaseLimitExceeded({
|
|
471
|
+
limit: "rowsReturned",
|
|
472
|
+
maximum: limits.rowsReturned,
|
|
473
|
+
requested: used.rowsReturned + rows.length
|
|
474
|
+
});
|
|
440
475
|
const page = rows.slice(0, count);
|
|
441
476
|
yield* charge("rowsReturned", page.length);
|
|
442
477
|
const values = yield* Effect_exports.forEach(page, (row) => decodeBody(row.body));
|
|
@@ -502,6 +537,11 @@ var makeSqliteDatabase = (options) => Effect_exports.gen(function* () {
|
|
|
502
537
|
})
|
|
503
538
|
};
|
|
504
539
|
return yield* Effect_exports.suspend(() => work(session)).pipe(
|
|
540
|
+
// A failed database call poisons the session. Report that failure even when
|
|
541
|
+
// authored code caught it or threw something else in its place.
|
|
542
|
+
Effect_exports.catchCause(
|
|
543
|
+
(cause) => failed === void 0 || Cause_exports.hasInterrupts(cause) ? Effect_exports.failCause(cause) : Effect_exports.fail(failed)
|
|
544
|
+
),
|
|
505
545
|
Effect_exports.tap(
|
|
506
546
|
() => gate.withPermits(1)(
|
|
507
547
|
Effect_exports.suspend(() => failed === void 0 ? Effect_exports.void : Effect_exports.fail(failed))
|