@opengeni/sdk 3.3.2-canary.1 → 3.4.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.
- package/README.md +1007 -72
- package/dist/adapters/express.d.ts +31 -0
- package/dist/adapters/express.js +87 -0
- package/dist/adapters/express.js.map +1 -0
- package/dist/adapters/hono.d.ts +16 -0
- package/dist/adapters/hono.js +8 -0
- package/dist/adapters/hono.js.map +1 -0
- package/dist/adapters/next.d.ts +29 -0
- package/dist/adapters/next.js +22 -0
- package/dist/adapters/next.js.map +1 -0
- package/dist/allowance-refusal.d.ts +2 -0
- package/dist/allowance-refusal.js +50 -0
- package/dist/allowance-refusal.js.map +1 -0
- package/dist/app-links.d.ts +42 -0
- package/dist/app-links.js +66 -0
- package/dist/app-links.js.map +1 -0
- package/dist/artifact-catalog.d.ts +40 -0
- package/dist/artifact-client.d.ts +20 -8
- package/dist/artifacts.d.ts +1 -1
- package/dist/artifacts.js +8 -6
- package/dist/automations.js +8 -2
- package/dist/automations.js.map +1 -1
- package/dist/azure-live-transport.d.ts +32 -0
- package/dist/browser.d.ts +6 -2
- package/dist/browser.js +25 -5
- package/dist/chat/fold.d.ts +75 -0
- package/dist/chat/handler.d.ts +41 -0
- package/dist/chat/http.d.ts +67 -0
- package/dist/chat/ids.d.ts +34 -0
- package/dist/chat/index.d.ts +9 -0
- package/dist/chat/index.js +1369 -0
- package/dist/chat/index.js.map +1 -0
- package/dist/chat/openai.d.ts +30 -0
- package/dist/chat/opengeni.d.ts +129 -0
- package/dist/chat/types.d.ts +207 -0
- package/dist/chat/vercel.d.ts +49 -0
- package/dist/chats.d.ts +8 -0
- package/dist/chunk-4AHR4KGA.js +301 -0
- package/dist/chunk-4AHR4KGA.js.map +1 -0
- package/dist/chunk-6GYGMLX4.js +332 -0
- package/dist/chunk-6GYGMLX4.js.map +1 -0
- package/dist/chunk-7EWT3PV6.js +368 -0
- package/dist/chunk-7EWT3PV6.js.map +1 -0
- package/dist/chunk-FTWVVPR6.js +1665 -0
- package/dist/chunk-FTWVVPR6.js.map +1 -0
- package/dist/{chunk-VYCTL62C.js → chunk-GZQSWAKD.js} +1 -1
- package/dist/chunk-GZQSWAKD.js.map +1 -0
- package/dist/chunk-KGEABAID.js +71 -0
- package/dist/chunk-KGEABAID.js.map +1 -0
- package/dist/{chunk-YKZME56C.js → chunk-KWADQ227.js} +3 -3
- package/dist/{chunk-YKZME56C.js.map → chunk-KWADQ227.js.map} +1 -1
- package/dist/{chunk-E5BNEG2D.js → chunk-NCU5OAN7.js} +27 -2
- package/dist/chunk-NCU5OAN7.js.map +1 -0
- package/dist/{chunk-BESZFWMU.js → chunk-OI5YLASH.js} +73 -2
- package/dist/chunk-OI5YLASH.js.map +1 -0
- package/dist/chunk-OV3POE62.js +359 -0
- package/dist/chunk-OV3POE62.js.map +1 -0
- package/dist/chunk-P7UWKORG.js +561 -0
- package/dist/chunk-P7UWKORG.js.map +1 -0
- package/dist/chunk-QGEIL4TR.js +195 -0
- package/dist/chunk-QGEIL4TR.js.map +1 -0
- package/dist/{chunk-GY6RQPCG.js → chunk-S2NLS3ES.js} +3598 -1278
- package/dist/chunk-S2NLS3ES.js.map +1 -0
- package/dist/chunk-UM4ZXXJR.js +9 -0
- package/dist/chunk-UM4ZXXJR.js.map +1 -0
- package/dist/{chunk-TFCLHRZK.js → chunk-UME3X7CP.js} +28 -32
- package/dist/chunk-UME3X7CP.js.map +1 -0
- package/dist/chunk-VT4YM4XQ.js +210 -0
- package/dist/chunk-VT4YM4XQ.js.map +1 -0
- package/dist/chunk-WSYYXONG.js +1602 -0
- package/dist/chunk-WSYYXONG.js.map +1 -0
- package/dist/{chunk-6NEPJ7NC.js → chunk-WVCJRSGJ.js} +119 -14
- package/dist/chunk-WVCJRSGJ.js.map +1 -0
- package/dist/chunk-X5ITQVXE.js +15 -0
- package/dist/chunk-X5ITQVXE.js.map +1 -0
- package/dist/chunk-XA7HVIHI.js +126 -0
- package/dist/chunk-XA7HVIHI.js.map +1 -0
- package/dist/{chunk-QTBAMHEF.js → chunk-YJCHB7R3.js} +60 -12
- package/dist/chunk-YJCHB7R3.js.map +1 -0
- package/dist/chunk-YKIHNLWD.js +153 -0
- package/dist/chunk-YKIHNLWD.js.map +1 -0
- package/dist/chunk-ZDUBPV33.js +277 -0
- package/dist/chunk-ZDUBPV33.js.map +1 -0
- package/dist/client.d.ts +1056 -118
- package/dist/codex-realtime-controller.d.ts +13 -0
- package/dist/codex-realtime-controller.js +4 -2
- package/dist/codex-realtime-v3-wire.d.ts +3 -2
- package/dist/codex-realtime.d.ts +5 -1
- package/dist/company-brain.d.ts +1 -11
- package/dist/core.d.ts +6 -2
- package/dist/core.js +23 -6
- package/dist/deprecation.d.ts +47 -0
- package/dist/document-authority-client.d.ts +24 -2
- package/dist/document-authority.js +7 -5
- package/dist/editable-artifacts/index.d.ts +1 -1
- package/dist/editable-artifacts/types.d.ts +12 -2
- package/dist/editable-artifacts.js +19 -3
- package/dist/editable-artifacts.js.map +1 -1
- package/dist/embedding-client.d.ts +129 -0
- package/dist/errors.d.ts +64 -1
- package/dist/external-vault-receiver.d.ts +203 -0
- package/dist/external-vault-receiver.js +564 -0
- package/dist/external-vault-receiver.js.map +1 -0
- package/dist/feedback.d.ts +23 -0
- package/dist/gateway-realtime-transport.js +1 -1
- package/dist/github-repositories.d.ts +10 -0
- package/dist/github-repositories.js +36 -0
- package/dist/github-repositories.js.map +1 -0
- package/dist/index.d.ts +61 -11
- package/dist/index.js +555 -338
- package/dist/index.js.map +1 -1
- package/dist/insights-usage.d.ts +33 -0
- package/dist/insights-usage.js +7 -0
- package/dist/insights-usage.js.map +1 -0
- package/dist/interaction.d.ts +165 -71
- package/dist/interaction.js +2 -2
- package/dist/knowledge.d.ts +7 -0
- package/dist/knowledge.js +20 -0
- package/dist/knowledge.js.map +1 -0
- package/dist/known-tools.d.ts +4 -0
- package/dist/message-links.d.ts +68 -0
- package/dist/model-context.d.ts +68 -0
- package/dist/model-display.d.ts +2 -0
- package/dist/model-display.js +17 -0
- package/dist/model-display.js.map +1 -0
- package/dist/organization-integration-policy.d.ts +26 -0
- package/dist/organization-integration-policy.js +26 -0
- package/dist/organization-integration-policy.js.map +1 -0
- package/dist/pr-review-client.d.ts +1 -1
- package/dist/pr-review.d.ts +1 -1
- package/dist/pr-review.js.map +1 -1
- package/dist/preference-registry.d.ts +1 -1
- package/dist/prepared-mcp-setup.d.ts +5 -0
- package/dist/proxy.d.ts +13 -11
- package/dist/realtime.d.ts +1 -1
- package/dist/realtime.js +253 -7
- package/dist/realtime.js.map +1 -1
- package/dist/session-history-import.d.ts +22 -0
- package/dist/session-history-import.js +36 -0
- package/dist/session-history-import.js.map +1 -0
- package/dist/session-list-entries.d.ts +1 -0
- package/dist/session-list-entries.js +7 -0
- package/dist/session-list-entries.js.map +1 -0
- package/dist/session-message-search.d.ts +53 -0
- package/dist/session-proxy-client.d.ts +28 -0
- package/dist/session-proxy.d.ts +334 -0
- package/dist/session-proxy.js +24 -0
- package/dist/session-proxy.js.map +1 -0
- package/dist/session-titles.d.ts +2 -28
- package/dist/session-usage-limits.d.ts +10 -0
- package/dist/session-usage-limits.js +43 -0
- package/dist/session-usage-limits.js.map +1 -0
- package/dist/shared-catalog-loader.d.ts +34 -0
- package/dist/site-ai.d.ts +35 -0
- package/dist/site-bridge-host.d.ts +112 -0
- package/dist/site-bridge-host.js +286 -0
- package/dist/site-bridge-host.js.map +1 -0
- package/dist/site-browser-entry.d.ts +1 -0
- package/dist/site-browser-runtime.gen.d.ts +1 -0
- package/dist/site-data.d.ts +178 -0
- package/dist/site-document.d.ts +5 -0
- package/dist/site-document.js +20 -0
- package/dist/site-document.js.map +1 -0
- package/dist/site-document.test.d.ts +1 -0
- package/dist/site-http.d.ts +17 -0
- package/dist/site-sql.d.ts +31 -0
- package/dist/site-tool-bridge.d.ts +57 -0
- package/dist/site.d.ts +186 -0
- package/dist/site.js +63 -0
- package/dist/site.js.map +1 -0
- package/dist/skills.d.ts +75 -0
- package/dist/sse.d.ts +1 -1
- package/dist/stream.d.ts +2 -0
- package/dist/tenant-workspaces.d.ts +47 -0
- package/dist/tenant-workspaces.js +8 -0
- package/dist/tenant-workspaces.js.map +1 -0
- package/dist/tool-auth.d.ts +87 -0
- package/dist/tool-auth.js +23 -0
- package/dist/tool-auth.js.map +1 -0
- package/dist/tool-display-metadata.d.ts +3 -0
- package/dist/tools-37DCTCNZ.js +12 -0
- package/dist/tools-37DCTCNZ.js.map +1 -0
- package/dist/tools.d.ts +81 -0
- package/dist/transcription.d.ts +1 -1
- package/dist/types.d.ts +2785 -592
- package/dist/usage-allowances.d.ts +36 -0
- package/dist/usage-allowances.js +80 -0
- package/dist/usage-allowances.js.map +1 -0
- package/dist/vault-types.d.ts +324 -0
- package/dist/vaults-api.d.ts +65 -0
- package/dist/workspace-artifacts.d.ts +47 -5
- package/dist/workspace-instruction-policies.d.ts +2 -2
- package/dist/workspace-integrations.d.ts +74 -0
- package/dist/workspace-integrations.js +67 -0
- package/dist/workspace-integrations.js.map +1 -0
- package/dist/workspace-state.d.ts +8 -71
- package/package.json +99 -5
- package/src/adapters/express.ts +136 -0
- package/src/adapters/hono.ts +18 -0
- package/src/adapters/next.ts +42 -0
- package/src/allowance-refusal.ts +5 -0
- package/src/app-links.ts +117 -0
- package/src/artifact-catalog.ts +51 -0
- package/src/artifact-client.ts +40 -49
- package/src/artifacts.ts +1 -0
- package/src/automations-client.ts +8 -2
- package/src/azure-live-transport.ts +286 -0
- package/src/browser.ts +35 -0
- package/src/chat/fold.ts +431 -0
- package/src/chat/handler.ts +240 -0
- package/src/chat/http.ts +257 -0
- package/src/chat/ids.ts +85 -0
- package/src/chat/index.ts +88 -0
- package/src/chat/openai.ts +439 -0
- package/src/chat/opengeni.ts +737 -0
- package/src/chat/types.ts +219 -0
- package/src/chat/vercel.ts +204 -0
- package/src/chats.ts +16 -0
- package/src/client.ts +5595 -1847
- package/src/codex-realtime-controller.ts +163 -8
- package/src/codex-realtime-v3-wire.ts +4 -3
- package/src/codex-realtime-v3.ts +12 -3
- package/src/codex-realtime.ts +11 -3
- package/src/company-brain.ts +0 -40
- package/src/core.ts +18 -0
- package/src/deprecation.ts +149 -0
- package/src/document-authority-client.ts +104 -1
- package/src/editable-artifacts/controller.ts +36 -2
- package/src/editable-artifacts/index.ts +1 -0
- package/src/editable-artifacts/types.ts +29 -16
- package/src/embedding-client.ts +519 -0
- package/src/errors.ts +281 -5
- package/src/external-vault-receiver.ts +914 -0
- package/src/feedback.ts +20 -0
- package/src/gateway-realtime-transport.ts +3 -3
- package/src/github-repositories.ts +60 -0
- package/src/index.ts +592 -65
- package/src/insights-usage.ts +64 -0
- package/src/interaction.ts +315 -93
- package/src/knowledge.ts +72 -0
- package/src/known-tools.ts +279 -0
- package/src/message-links.ts +178 -0
- package/src/model-context.ts +113 -0
- package/src/model-display.ts +11 -0
- package/src/organization-integration-policy.ts +54 -0
- package/src/pr-review-client.ts +1 -1
- package/src/pr-review.ts +1 -1
- package/src/preference-registry.ts +2 -0
- package/src/prepared-mcp-setup.ts +123 -0
- package/src/proxy.ts +23 -12
- package/src/realtime.ts +15 -6
- package/src/session-history-import.ts +84 -0
- package/src/session-list-entries.ts +1 -0
- package/src/session-message-search.ts +47 -0
- package/src/session-proxy-client.ts +68 -0
- package/src/session-proxy.ts +2098 -0
- package/src/session-titles.ts +8 -82
- package/src/session-usage-limits.ts +71 -0
- package/src/shared-catalog-loader.ts +169 -0
- package/src/site-ai.ts +284 -0
- package/src/site-bridge-host.ts +422 -0
- package/src/site-browser-entry.ts +6 -0
- package/src/site-browser-runtime.gen.ts +2 -0
- package/src/site-data.ts +372 -0
- package/src/site-document.test.ts +64 -0
- package/src/site-document.ts +18 -0
- package/src/site-http.ts +171 -0
- package/src/site-sql.ts +153 -0
- package/src/site-tool-bridge.ts +401 -0
- package/src/site.ts +878 -0
- package/src/skills.ts +69 -0
- package/src/sse.ts +9 -3
- package/src/stream.ts +33 -10
- package/src/tenant-workspaces.ts +148 -0
- package/src/tool-auth.ts +301 -0
- package/src/tool-display-metadata.ts +27 -0
- package/src/tools.ts +452 -0
- package/src/transcription.ts +3 -0
- package/src/types.ts +3142 -594
- package/src/usage-allowances.ts +189 -0
- package/src/vault-types.ts +379 -0
- package/src/vaults-api.ts +339 -0
- package/src/workspace-artifacts.ts +55 -6
- package/src/workspace-instruction-policies.ts +2 -1
- package/src/workspace-integrations.ts +402 -0
- package/src/workspace-state.ts +8 -82
- package/dist/chunk-6NEPJ7NC.js.map +0 -1
- package/dist/chunk-BESZFWMU.js.map +0 -1
- package/dist/chunk-E5BNEG2D.js.map +0 -1
- package/dist/chunk-GY6RQPCG.js.map +0 -1
- package/dist/chunk-OO5LPTO7.js +0 -132
- package/dist/chunk-OO5LPTO7.js.map +0 -1
- package/dist/chunk-QTBAMHEF.js.map +0 -1
- package/dist/chunk-TFCLHRZK.js.map +0 -1
- package/dist/chunk-VYCTL62C.js.map +0 -1
package/src/site-data.ts
ADDED
|
@@ -0,0 +1,372 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Site Data for Site HTML: persistent JSON collections and files that belong
|
|
3
|
+
* to the published Site. Requests travel over the host's Site HTTP channel;
|
|
4
|
+
* the host adds the viewer's credentials and pins the Site, and the API
|
|
5
|
+
* enforces each collection's access mode. Stored records are untrusted input:
|
|
6
|
+
* render them with textContent, never innerHTML.
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
export type OpenGeniSiteDataErrorCode =
|
|
10
|
+
| "validation"
|
|
11
|
+
| "conflict"
|
|
12
|
+
| "not_found"
|
|
13
|
+
| "forbidden"
|
|
14
|
+
/** This viewer may not do this on this Site (a role the Site's rules exclude). */
|
|
15
|
+
| "not_available_for_viewer"
|
|
16
|
+
| "quota_exceeded"
|
|
17
|
+
| "rate_limited"
|
|
18
|
+
| "site_data_unsupported"
|
|
19
|
+
| "request_failed";
|
|
20
|
+
|
|
21
|
+
export class OpenGeniSiteDataError extends Error {
|
|
22
|
+
constructor(
|
|
23
|
+
readonly code: OpenGeniSiteDataErrorCode,
|
|
24
|
+
message: string,
|
|
25
|
+
readonly status: number,
|
|
26
|
+
readonly details: Record<string, unknown> = {},
|
|
27
|
+
) {
|
|
28
|
+
super(message);
|
|
29
|
+
this.name = "OpenGeniSiteDataError";
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
export type OpenGeniSiteDataRecord<T extends Record<string, unknown> = Record<string, unknown>> = {
|
|
34
|
+
id: string;
|
|
35
|
+
key: string | null;
|
|
36
|
+
data: T;
|
|
37
|
+
/** Principal that owns the record, such as `user:<id>`. */
|
|
38
|
+
owner: string;
|
|
39
|
+
createdBy: string;
|
|
40
|
+
updatedBy: string;
|
|
41
|
+
version: number;
|
|
42
|
+
sizeBytes: number;
|
|
43
|
+
createdAt: string;
|
|
44
|
+
updatedAt: string;
|
|
45
|
+
};
|
|
46
|
+
|
|
47
|
+
export type OpenGeniSiteDataScalar = string | number | boolean | null;
|
|
48
|
+
|
|
49
|
+
export type OpenGeniSiteDataFilter = {
|
|
50
|
+
/** Dotted data path (up to 4 levels) or $id, $key, $owner, $createdAt, $updatedAt, $version. */
|
|
51
|
+
field: string;
|
|
52
|
+
op: "eq" | "ne" | "in" | "gt" | "gte" | "lt" | "lte" | "contains" | "exists";
|
|
53
|
+
value?: OpenGeniSiteDataScalar | OpenGeniSiteDataScalar[];
|
|
54
|
+
};
|
|
55
|
+
|
|
56
|
+
export type OpenGeniSiteDataListOptions = {
|
|
57
|
+
where?: OpenGeniSiteDataFilter[];
|
|
58
|
+
sort?: Array<{ field: string; direction?: "asc" | "desc" }>;
|
|
59
|
+
/** 1 to 200; 50 by default. */
|
|
60
|
+
limit?: number;
|
|
61
|
+
cursor?: string | null;
|
|
62
|
+
count?: boolean;
|
|
63
|
+
/** `own` returns only the viewer's records. */
|
|
64
|
+
scope?: "own" | "all";
|
|
65
|
+
};
|
|
66
|
+
|
|
67
|
+
export type OpenGeniSiteDataPage<T extends Record<string, unknown> = Record<string, unknown>> = {
|
|
68
|
+
records: OpenGeniSiteDataRecord<T>[];
|
|
69
|
+
nextCursor: string | null;
|
|
70
|
+
count?: number;
|
|
71
|
+
};
|
|
72
|
+
|
|
73
|
+
/** A record by id, or by your own key. A plain string is treated as a key. */
|
|
74
|
+
export type OpenGeniSiteDataRef = string | { id: string } | { key: string };
|
|
75
|
+
|
|
76
|
+
export type OpenGeniSiteDataOperation =
|
|
77
|
+
| { op: "insert"; collection: string; key?: string; data: Record<string, unknown> }
|
|
78
|
+
| {
|
|
79
|
+
op: "put";
|
|
80
|
+
collection: string;
|
|
81
|
+
key: string;
|
|
82
|
+
data: Record<string, unknown>;
|
|
83
|
+
expectedVersion?: number;
|
|
84
|
+
}
|
|
85
|
+
| ({
|
|
86
|
+
op: "patch";
|
|
87
|
+
collection: string;
|
|
88
|
+
data: Record<string, unknown>;
|
|
89
|
+
expectedVersion?: number;
|
|
90
|
+
} & RefFields)
|
|
91
|
+
| ({ op: "delete"; collection: string; expectedVersion?: number } & RefFields)
|
|
92
|
+
| ({ op: "increment"; collection: string; field: string; by?: number } & RefFields);
|
|
93
|
+
|
|
94
|
+
type RefFields = { id: string; key?: never } | { key: string; id?: never };
|
|
95
|
+
|
|
96
|
+
export type OpenGeniSiteDataWriteResult =
|
|
97
|
+
| { op: "insert" | "put" | "patch" | "increment"; record: OpenGeniSiteDataRecord }
|
|
98
|
+
| { op: "delete"; deleted: { id: string } };
|
|
99
|
+
|
|
100
|
+
export type OpenGeniSiteDataCollection<
|
|
101
|
+
T extends Record<string, unknown> = Record<string, unknown>,
|
|
102
|
+
> = {
|
|
103
|
+
readonly name: string;
|
|
104
|
+
list(options?: OpenGeniSiteDataListOptions): Promise<OpenGeniSiteDataPage<T>>;
|
|
105
|
+
/** Resolves null when the record does not exist or is not visible to the viewer. */
|
|
106
|
+
get(ref: OpenGeniSiteDataRef): Promise<OpenGeniSiteDataRecord<T> | null>;
|
|
107
|
+
insert(data: T, options?: { key?: string }): Promise<OpenGeniSiteDataRecord<T>>;
|
|
108
|
+
/** Create or replace the record with this key. */
|
|
109
|
+
put(
|
|
110
|
+
key: string,
|
|
111
|
+
data: T,
|
|
112
|
+
options?: { expectedVersion?: number },
|
|
113
|
+
): Promise<OpenGeniSiteDataRecord<T>>;
|
|
114
|
+
/** Shallow-merge fields; expectedVersion turns concurrent edits into a conflict error. */
|
|
115
|
+
patch(
|
|
116
|
+
ref: OpenGeniSiteDataRef,
|
|
117
|
+
data: Partial<T>,
|
|
118
|
+
options?: { expectedVersion?: number },
|
|
119
|
+
): Promise<OpenGeniSiteDataRecord<T>>;
|
|
120
|
+
delete(ref: OpenGeniSiteDataRef, options?: { expectedVersion?: number }): Promise<void>;
|
|
121
|
+
/** Atomically add to a numeric field; a missing key is created. */
|
|
122
|
+
increment(
|
|
123
|
+
ref: OpenGeniSiteDataRef,
|
|
124
|
+
field: string,
|
|
125
|
+
by?: number,
|
|
126
|
+
): Promise<OpenGeniSiteDataRecord<T>>;
|
|
127
|
+
count(where?: OpenGeniSiteDataFilter[], options?: { scope?: "own" | "all" }): Promise<number>;
|
|
128
|
+
};
|
|
129
|
+
|
|
130
|
+
export type OpenGeniSiteData = {
|
|
131
|
+
collection<T extends Record<string, unknown> = Record<string, unknown>>(
|
|
132
|
+
name: string,
|
|
133
|
+
): OpenGeniSiteDataCollection<T>;
|
|
134
|
+
/** Up to 100 operations across collections, applied together or not at all. */
|
|
135
|
+
batch(operations: OpenGeniSiteDataOperation[]): Promise<OpenGeniSiteDataWriteResult[]>;
|
|
136
|
+
count(collection: string, where?: OpenGeniSiteDataFilter[]): Promise<number>;
|
|
137
|
+
};
|
|
138
|
+
|
|
139
|
+
export type OpenGeniSiteFile = {
|
|
140
|
+
id: string;
|
|
141
|
+
name: string;
|
|
142
|
+
contentType: string;
|
|
143
|
+
sizeBytes: number;
|
|
144
|
+
sha256: string;
|
|
145
|
+
/** shared: every viewer can open it. private: only the uploader and the Site's managers. */
|
|
146
|
+
scope: "shared" | "private";
|
|
147
|
+
owner: string;
|
|
148
|
+
createdBy: string;
|
|
149
|
+
createdAt: string;
|
|
150
|
+
};
|
|
151
|
+
|
|
152
|
+
export type OpenGeniSiteFiles = {
|
|
153
|
+
upload(
|
|
154
|
+
file: Blob | ArrayBuffer | Uint8Array,
|
|
155
|
+
options?: { name?: string; contentType?: string; scope?: "shared" | "private" },
|
|
156
|
+
): Promise<OpenGeniSiteFile>;
|
|
157
|
+
list(options?: { limit?: number; cursor?: string | null }): Promise<{
|
|
158
|
+
files: OpenGeniSiteFile[];
|
|
159
|
+
nextCursor: string | null;
|
|
160
|
+
}>;
|
|
161
|
+
/** A short-lived download URL for an img/src, link or fetch. */
|
|
162
|
+
url(fileId: string): Promise<{ url: string; expiresAt: string; file: OpenGeniSiteFile }>;
|
|
163
|
+
delete(fileId: string): Promise<void>;
|
|
164
|
+
};
|
|
165
|
+
|
|
166
|
+
/** Path prefix the host rewrites to its pinned Site; Site code never names a Site id. */
|
|
167
|
+
export const SITE_DATA_PATH_PREFIX = "/v1/workspaces/site-host/published-artifacts/current";
|
|
168
|
+
|
|
169
|
+
type SiteDataFetch = (path: string, init: RequestInit) => Promise<Response>;
|
|
170
|
+
|
|
171
|
+
/**
|
|
172
|
+
* Build the typed Site Data facade over a Site HTTP fetch. `ready` resolves
|
|
173
|
+
* once the host has said whether it serves Site Data.
|
|
174
|
+
*/
|
|
175
|
+
export function createOpenGeniSiteData(
|
|
176
|
+
fetchSite: SiteDataFetch,
|
|
177
|
+
ready: () => Promise<boolean>,
|
|
178
|
+
): { data: OpenGeniSiteData; files: OpenGeniSiteFiles } {
|
|
179
|
+
const send = async <T>(path: string, init: RequestInit = {}): Promise<T> => {
|
|
180
|
+
if (!(await ready()))
|
|
181
|
+
throw new OpenGeniSiteDataError(
|
|
182
|
+
"site_data_unsupported",
|
|
183
|
+
"This Site host does not provide Site Data",
|
|
184
|
+
0,
|
|
185
|
+
);
|
|
186
|
+
const response = await fetchSite(`${SITE_DATA_PATH_PREFIX}${path}`, init);
|
|
187
|
+
const text = await response.text();
|
|
188
|
+
let value: unknown = null;
|
|
189
|
+
try {
|
|
190
|
+
value = text ? JSON.parse(text) : null;
|
|
191
|
+
} catch {
|
|
192
|
+
value = null;
|
|
193
|
+
}
|
|
194
|
+
if (response.ok) return value as T;
|
|
195
|
+
throw siteDataErrorFromResponse(response.status, value);
|
|
196
|
+
};
|
|
197
|
+
const json = (body: unknown): RequestInit => ({
|
|
198
|
+
method: "POST",
|
|
199
|
+
headers: { "content-type": "application/json" },
|
|
200
|
+
body: JSON.stringify(body),
|
|
201
|
+
});
|
|
202
|
+
const write = async (operations: OpenGeniSiteDataOperation[]) =>
|
|
203
|
+
(await send<{ results: OpenGeniSiteDataWriteResult[] }>("/data/write", json({ operations })))
|
|
204
|
+
.results;
|
|
205
|
+
const one = async (operation: OpenGeniSiteDataOperation) => {
|
|
206
|
+
const [result] = await write([operation]);
|
|
207
|
+
if (!result || !("record" in result))
|
|
208
|
+
throw new OpenGeniSiteDataError("request_failed", "Unexpected Site Data response", 200);
|
|
209
|
+
return result.record;
|
|
210
|
+
};
|
|
211
|
+
const count = async (
|
|
212
|
+
collection: string,
|
|
213
|
+
where?: OpenGeniSiteDataFilter[],
|
|
214
|
+
scope?: "own" | "all",
|
|
215
|
+
) =>
|
|
216
|
+
(
|
|
217
|
+
await send<OpenGeniSiteDataPage>(
|
|
218
|
+
"/data/query",
|
|
219
|
+
json({
|
|
220
|
+
collection,
|
|
221
|
+
limit: 1,
|
|
222
|
+
count: true,
|
|
223
|
+
...(where ? { where } : {}),
|
|
224
|
+
...(scope ? { scope } : {}),
|
|
225
|
+
}),
|
|
226
|
+
)
|
|
227
|
+
).count ?? 0;
|
|
228
|
+
|
|
229
|
+
const data: OpenGeniSiteData = {
|
|
230
|
+
collection<T extends Record<string, unknown> = Record<string, unknown>>(name: string) {
|
|
231
|
+
const collection: OpenGeniSiteDataCollection<T> = {
|
|
232
|
+
name,
|
|
233
|
+
list: async (options = {}) =>
|
|
234
|
+
await send<OpenGeniSiteDataPage<T>>(
|
|
235
|
+
"/data/query",
|
|
236
|
+
json({ collection: name, ...options }),
|
|
237
|
+
),
|
|
238
|
+
get: async (ref) => {
|
|
239
|
+
try {
|
|
240
|
+
return (
|
|
241
|
+
await send<{ record: OpenGeniSiteDataRecord<T> }>(
|
|
242
|
+
"/data/get",
|
|
243
|
+
json({ collection: name, ...refFields(ref) }),
|
|
244
|
+
)
|
|
245
|
+
).record;
|
|
246
|
+
} catch (error) {
|
|
247
|
+
if (error instanceof OpenGeniSiteDataError && error.code === "not_found") return null;
|
|
248
|
+
throw error;
|
|
249
|
+
}
|
|
250
|
+
},
|
|
251
|
+
insert: async (value, options = {}) =>
|
|
252
|
+
(await one({
|
|
253
|
+
op: "insert",
|
|
254
|
+
collection: name,
|
|
255
|
+
data: value,
|
|
256
|
+
...(options.key === undefined ? {} : { key: options.key }),
|
|
257
|
+
})) as OpenGeniSiteDataRecord<T>,
|
|
258
|
+
put: async (key, value, options = {}) =>
|
|
259
|
+
(await one({
|
|
260
|
+
op: "put",
|
|
261
|
+
collection: name,
|
|
262
|
+
key,
|
|
263
|
+
data: value,
|
|
264
|
+
...options,
|
|
265
|
+
})) as OpenGeniSiteDataRecord<T>,
|
|
266
|
+
patch: async (ref, value, options = {}) =>
|
|
267
|
+
(await one({
|
|
268
|
+
op: "patch",
|
|
269
|
+
collection: name,
|
|
270
|
+
...refFields(ref),
|
|
271
|
+
data: value as Record<string, unknown>,
|
|
272
|
+
...options,
|
|
273
|
+
})) as OpenGeniSiteDataRecord<T>,
|
|
274
|
+
delete: async (ref, options = {}) => {
|
|
275
|
+
await write([{ op: "delete", collection: name, ...refFields(ref), ...options }]);
|
|
276
|
+
},
|
|
277
|
+
increment: async (ref, field, by) =>
|
|
278
|
+
(await one({
|
|
279
|
+
op: "increment",
|
|
280
|
+
collection: name,
|
|
281
|
+
...refFields(ref),
|
|
282
|
+
field,
|
|
283
|
+
...(by === undefined ? {} : { by }),
|
|
284
|
+
})) as OpenGeniSiteDataRecord<T>,
|
|
285
|
+
count: async (where, options = {}) => await count(name, where, options.scope),
|
|
286
|
+
};
|
|
287
|
+
return collection;
|
|
288
|
+
},
|
|
289
|
+
batch: write,
|
|
290
|
+
count: async (collection, where) => await count(collection, where),
|
|
291
|
+
};
|
|
292
|
+
|
|
293
|
+
const files: OpenGeniSiteFiles = {
|
|
294
|
+
upload: async (file, options = {}) => {
|
|
295
|
+
const blob =
|
|
296
|
+
file instanceof Blob
|
|
297
|
+
? file
|
|
298
|
+
: new Blob([file instanceof Uint8Array ? file.slice() : file], {
|
|
299
|
+
type: options.contentType ?? "application/octet-stream",
|
|
300
|
+
});
|
|
301
|
+
const name =
|
|
302
|
+
options.name ?? (typeof File !== "undefined" && file instanceof File ? file.name : "file");
|
|
303
|
+
const query = new URLSearchParams({ name, scope: options.scope ?? "shared" });
|
|
304
|
+
return await send<OpenGeniSiteFile>(`/files?${query}`, {
|
|
305
|
+
method: "POST",
|
|
306
|
+
headers: {
|
|
307
|
+
"content-type": options.contentType ?? (blob.type || "application/octet-stream"),
|
|
308
|
+
},
|
|
309
|
+
body: await blob.arrayBuffer(),
|
|
310
|
+
});
|
|
311
|
+
},
|
|
312
|
+
list: async (options = {}) => {
|
|
313
|
+
const query = new URLSearchParams();
|
|
314
|
+
if (options.limit !== undefined) query.set("limit", String(options.limit));
|
|
315
|
+
if (options.cursor) query.set("cursor", options.cursor);
|
|
316
|
+
const suffix = query.size ? `?${query}` : "";
|
|
317
|
+
return await send(`/files${suffix}`, { method: "GET" });
|
|
318
|
+
},
|
|
319
|
+
url: async (fileId) => await send(`/files/${encodeURIComponent(fileId)}`, { method: "GET" }),
|
|
320
|
+
delete: async (fileId) => {
|
|
321
|
+
await send(`/files/${encodeURIComponent(fileId)}`, { method: "DELETE" });
|
|
322
|
+
},
|
|
323
|
+
};
|
|
324
|
+
return { data, files };
|
|
325
|
+
}
|
|
326
|
+
|
|
327
|
+
function refFields(ref: OpenGeniSiteDataRef): RefFields {
|
|
328
|
+
if (typeof ref === "string") return { key: ref };
|
|
329
|
+
if ("id" in ref) return { id: ref.id };
|
|
330
|
+
return { key: ref.key };
|
|
331
|
+
}
|
|
332
|
+
|
|
333
|
+
const KNOWN_CODES = new Set<OpenGeniSiteDataErrorCode>([
|
|
334
|
+
"validation",
|
|
335
|
+
"conflict",
|
|
336
|
+
"not_found",
|
|
337
|
+
"forbidden",
|
|
338
|
+
"not_available_for_viewer",
|
|
339
|
+
"quota_exceeded",
|
|
340
|
+
"rate_limited",
|
|
341
|
+
]);
|
|
342
|
+
|
|
343
|
+
function siteDataErrorFromResponse(status: number, value: unknown): OpenGeniSiteDataError {
|
|
344
|
+
const error =
|
|
345
|
+
typeof value === "object" && value !== null && "error" in value
|
|
346
|
+
? (value as { error: unknown }).error
|
|
347
|
+
: null;
|
|
348
|
+
const record =
|
|
349
|
+
typeof error === "object" && error !== null ? (error as Record<string, unknown>) : {};
|
|
350
|
+
const details =
|
|
351
|
+
typeof record.details === "object" && record.details !== null
|
|
352
|
+
? (record.details as Record<string, unknown>)
|
|
353
|
+
: {};
|
|
354
|
+
const detailCode = details.code as OpenGeniSiteDataErrorCode | undefined;
|
|
355
|
+
const code: OpenGeniSiteDataErrorCode =
|
|
356
|
+
detailCode && KNOWN_CODES.has(detailCode)
|
|
357
|
+
? detailCode
|
|
358
|
+
: status === 404
|
|
359
|
+
? "not_found"
|
|
360
|
+
: status === 403
|
|
361
|
+
? "forbidden"
|
|
362
|
+
: status === 413
|
|
363
|
+
? "quota_exceeded"
|
|
364
|
+
: status === 429
|
|
365
|
+
? "rate_limited"
|
|
366
|
+
: "request_failed";
|
|
367
|
+
const message =
|
|
368
|
+
typeof record.message === "string" && record.message
|
|
369
|
+
? record.message
|
|
370
|
+
: `Site Data request failed with HTTP ${status}`;
|
|
371
|
+
return new OpenGeniSiteDataError(code, message, status, details);
|
|
372
|
+
}
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
import { expect, test } from "bun:test";
|
|
2
|
+
import { runInNewContext } from "node:vm";
|
|
3
|
+
import { resolveSiteClientScript, SITE_CLIENT_SCRIPT_PATH } from "./site-document";
|
|
4
|
+
|
|
5
|
+
const tag = `<script src="${SITE_CLIENT_SCRIPT_PATH}"></script>`;
|
|
6
|
+
|
|
7
|
+
test("ordinary bundled Sites remain byte-identical", () => {
|
|
8
|
+
const html =
|
|
9
|
+
'<!doctype html><script type="module">const client = "bundled SDK";</script><main>React</main>';
|
|
10
|
+
expect(resolveSiteClientScript(html)).toBe(html);
|
|
11
|
+
const comment = `<!-- ${tag} -->`;
|
|
12
|
+
expect(resolveSiteClientScript(comment)).toBe(comment);
|
|
13
|
+
const sample = `<script>const example = '<script src="${SITE_CLIENT_SCRIPT_PATH}"><\\/script>';</script>`;
|
|
14
|
+
expect(resolveSiteClientScript(sample)).toBe(sample);
|
|
15
|
+
});
|
|
16
|
+
|
|
17
|
+
test("optional script preserves document order and exposes the existing client", () => {
|
|
18
|
+
const html = `<!doctype html><title>Preview</title>${tag}<script>globalThis.authorRan = true</script>`;
|
|
19
|
+
const result = resolveSiteClientScript(html);
|
|
20
|
+
expect(result.startsWith("<!doctype html><title>Preview</title><script>")).toBe(true);
|
|
21
|
+
expect(result.endsWith("<script>globalThis.authorRan = true</script>")).toBe(true);
|
|
22
|
+
const script = result.match(/<script>([\s\S]*?)<\/script>/)![1]!;
|
|
23
|
+
const context: Record<string, unknown> = {
|
|
24
|
+
URL,
|
|
25
|
+
Request,
|
|
26
|
+
Response,
|
|
27
|
+
Headers,
|
|
28
|
+
AbortController,
|
|
29
|
+
TextEncoder,
|
|
30
|
+
TextDecoder,
|
|
31
|
+
setTimeout,
|
|
32
|
+
clearTimeout,
|
|
33
|
+
};
|
|
34
|
+
runInNewContext(script, context);
|
|
35
|
+
expect(typeof context.createOpenGeniSiteClient).toBe("function");
|
|
36
|
+
});
|
|
37
|
+
|
|
38
|
+
test("optional client uses the existing local catalog transport", async () => {
|
|
39
|
+
const html = resolveSiteClientScript(tag);
|
|
40
|
+
const calls: string[] = [];
|
|
41
|
+
const window: Record<string, unknown> = {};
|
|
42
|
+
window.parent = window;
|
|
43
|
+
const context: Record<string, any> = {
|
|
44
|
+
window,
|
|
45
|
+
URL,
|
|
46
|
+
Request,
|
|
47
|
+
Response,
|
|
48
|
+
Headers,
|
|
49
|
+
AbortController,
|
|
50
|
+
TextEncoder,
|
|
51
|
+
TextDecoder,
|
|
52
|
+
setTimeout,
|
|
53
|
+
clearTimeout,
|
|
54
|
+
fetch: async (url: string) => {
|
|
55
|
+
calls.push(url);
|
|
56
|
+
return Response.json({ version: 1, generation: 1, digest: "test", entries: [] });
|
|
57
|
+
},
|
|
58
|
+
};
|
|
59
|
+
runInNewContext(html.match(/<script>([\s\S]*?)<\/script>/)![1]!, context);
|
|
60
|
+
const client = context.createOpenGeniSiteClient();
|
|
61
|
+
await client.tools.$catalog();
|
|
62
|
+
expect(calls).toEqual(["/__opengeni/site-tools/catalog"]);
|
|
63
|
+
client.close();
|
|
64
|
+
});
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { SITE_BROWSER_RUNTIME } from "./site-browser-runtime.gen";
|
|
2
|
+
|
|
3
|
+
export const SITE_CLIENT_SCRIPT_PATH = "/__opengeni/site-tools/client.js";
|
|
4
|
+
export { SITE_BROWSER_RUNTIME };
|
|
5
|
+
|
|
6
|
+
/** Resolve only the optional client tag; ordinary bundled Sites remain unchanged. */
|
|
7
|
+
export function resolveSiteClientScript(html: string): string {
|
|
8
|
+
// Consume whole scripts/comments so examples inside JS or comments stay literal.
|
|
9
|
+
return html.replace(/<!--[\s\S]*?-->|<script\b[^>]*>[\s\S]*?<\/script\s*>/gi, (tag) => {
|
|
10
|
+
if (
|
|
11
|
+
!/^<script\s+src\s*=\s*(["'])\/__opengeni\/site-tools\/client\.js\1\s*>\s*<\/script\s*>$/i.test(
|
|
12
|
+
tag,
|
|
13
|
+
)
|
|
14
|
+
)
|
|
15
|
+
return tag;
|
|
16
|
+
return "<script>" + SITE_BROWSER_RUNTIME.replace(/<\/script/gi, "<\\/script") + "</script>";
|
|
17
|
+
});
|
|
18
|
+
}
|
package/src/site-http.ts
ADDED
|
@@ -0,0 +1,171 @@
|
|
|
1
|
+
/** HTTP transport for the ordinary SDK. One response port per request keeps
|
|
2
|
+
* event streams incremental and cancellation independent of other requests. */
|
|
3
|
+
export const SITE_HTTP = "opengeni.site.http";
|
|
4
|
+
export const SITE_WORKSPACE = "site-host";
|
|
5
|
+
export type SiteHttpRequest = {
|
|
6
|
+
type: typeof SITE_HTTP;
|
|
7
|
+
requestId: string;
|
|
8
|
+
path: string;
|
|
9
|
+
method: string;
|
|
10
|
+
headers: [string, string][];
|
|
11
|
+
/** Text for JSON requests; bytes for Site Data file uploads. */
|
|
12
|
+
body?: string | ArrayBuffer;
|
|
13
|
+
};
|
|
14
|
+
|
|
15
|
+
import { siteSessionPath } from "@opengeni/contracts/site-session-http";
|
|
16
|
+
export { siteSessionPath } from "@opengeni/contracts/site-session-http";
|
|
17
|
+
|
|
18
|
+
export function isSiteHttpRequest(value: unknown): value is SiteHttpRequest {
|
|
19
|
+
if (!value || typeof value !== "object") return false;
|
|
20
|
+
const v = value as SiteHttpRequest;
|
|
21
|
+
return (
|
|
22
|
+
v.type === SITE_HTTP &&
|
|
23
|
+
typeof v.requestId === "string" &&
|
|
24
|
+
typeof v.path === "string" &&
|
|
25
|
+
typeof v.method === "string" &&
|
|
26
|
+
/^[!#$%&'*+.^_`|~0-9A-Za-z-]+$/u.test(v.method) &&
|
|
27
|
+
(v.body === undefined || typeof v.body === "string" || v.body instanceof ArrayBuffer) &&
|
|
28
|
+
Array.isArray(v.headers) &&
|
|
29
|
+
v.headers.every(
|
|
30
|
+
(h) => Array.isArray(h) && h.length === 2 && h.every((x) => typeof x === "string"),
|
|
31
|
+
)
|
|
32
|
+
);
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
export async function serveSiteHttp(
|
|
36
|
+
message: SiteHttpRequest,
|
|
37
|
+
port: MessagePort,
|
|
38
|
+
fetchResponse: (request: SiteHttpRequest, signal: AbortSignal) => Promise<Response>,
|
|
39
|
+
signal: AbortSignal,
|
|
40
|
+
): Promise<void> {
|
|
41
|
+
let reader: ReadableStreamDefaultReader<Uint8Array> | undefined;
|
|
42
|
+
let wake: (() => void) | undefined;
|
|
43
|
+
let pulling = false;
|
|
44
|
+
const onMessage = (event: MessageEvent) => {
|
|
45
|
+
if (event.data === "pull") {
|
|
46
|
+
pulling = true;
|
|
47
|
+
wake?.();
|
|
48
|
+
}
|
|
49
|
+
};
|
|
50
|
+
const abort = () => {
|
|
51
|
+
void reader?.cancel(signal.reason).catch(() => {});
|
|
52
|
+
wake?.();
|
|
53
|
+
};
|
|
54
|
+
port.addEventListener("message", onMessage);
|
|
55
|
+
signal.addEventListener("abort", abort, { once: true });
|
|
56
|
+
port.start();
|
|
57
|
+
try {
|
|
58
|
+
if (signal.aborted) throw signal.reason;
|
|
59
|
+
const response = await fetchResponse(message, signal);
|
|
60
|
+
reader = response.body?.getReader();
|
|
61
|
+
port.postMessage({ status: response.status, headers: [...response.headers], body: !!reader });
|
|
62
|
+
if (reader)
|
|
63
|
+
while (!signal.aborted) {
|
|
64
|
+
if (!pulling)
|
|
65
|
+
await new Promise<void>((resolve) => {
|
|
66
|
+
wake = resolve;
|
|
67
|
+
});
|
|
68
|
+
wake = undefined;
|
|
69
|
+
if (signal.aborted) break;
|
|
70
|
+
pulling = false;
|
|
71
|
+
const part = await reader.read();
|
|
72
|
+
if (part.done) {
|
|
73
|
+
port.postMessage({ done: true });
|
|
74
|
+
break;
|
|
75
|
+
}
|
|
76
|
+
port.postMessage({ chunk: part.value });
|
|
77
|
+
}
|
|
78
|
+
if (signal.aborted) throw signal.reason;
|
|
79
|
+
} catch (error) {
|
|
80
|
+
port.postMessage({ error: error instanceof Error ? error.message : "Site request failed" });
|
|
81
|
+
} finally {
|
|
82
|
+
signal.removeEventListener("abort", abort);
|
|
83
|
+
port.removeEventListener("message", onMessage);
|
|
84
|
+
await reader?.cancel().catch(() => {});
|
|
85
|
+
port.close();
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
export async function sitePortFetch(
|
|
90
|
+
port: MessagePort,
|
|
91
|
+
input: RequestInfo | URL,
|
|
92
|
+
init?: RequestInit,
|
|
93
|
+
): Promise<Response> {
|
|
94
|
+
const request = new Request(input, init);
|
|
95
|
+
const url = new URL(request.url);
|
|
96
|
+
const path = `${url.pathname}${url.search}`;
|
|
97
|
+
siteSessionPath(path, SITE_WORKSPACE, request.method);
|
|
98
|
+
const channel = new MessageChannel();
|
|
99
|
+
const requestId = crypto.randomUUID();
|
|
100
|
+
const binary =
|
|
101
|
+
init?.body instanceof ArrayBuffer ||
|
|
102
|
+
ArrayBuffer.isView(init?.body) ||
|
|
103
|
+
(typeof Blob !== "undefined" && init?.body instanceof Blob);
|
|
104
|
+
const body = request.body
|
|
105
|
+
? binary
|
|
106
|
+
? await request.arrayBuffer()
|
|
107
|
+
: await request.text()
|
|
108
|
+
: undefined;
|
|
109
|
+
return await new Promise<Response>((resolve, reject) => {
|
|
110
|
+
let controller: ReadableStreamDefaultController<Uint8Array> | undefined;
|
|
111
|
+
let finished = false;
|
|
112
|
+
const cleanup = () => {
|
|
113
|
+
finished = true;
|
|
114
|
+
request.signal.removeEventListener("abort", abort);
|
|
115
|
+
channel.port1.close();
|
|
116
|
+
};
|
|
117
|
+
const abort = () => {
|
|
118
|
+
if (finished) return;
|
|
119
|
+
port.postMessage({ type: "opengeni.site.cancel", version: 2, requestId });
|
|
120
|
+
const error = request.signal.reason ?? new DOMException("Cancelled", "AbortError");
|
|
121
|
+
controller?.error(error);
|
|
122
|
+
reject(error);
|
|
123
|
+
cleanup();
|
|
124
|
+
};
|
|
125
|
+
channel.port1.onmessage = (event) => {
|
|
126
|
+
const data = event.data;
|
|
127
|
+
if (data.error) {
|
|
128
|
+
const error = new Error(data.error);
|
|
129
|
+
controller?.error(error);
|
|
130
|
+
reject(error);
|
|
131
|
+
cleanup();
|
|
132
|
+
} else if (data.status) {
|
|
133
|
+
const stream = data.body
|
|
134
|
+
? new ReadableStream<Uint8Array>({
|
|
135
|
+
start(c) {
|
|
136
|
+
controller = c;
|
|
137
|
+
},
|
|
138
|
+
pull() {
|
|
139
|
+
channel.port1.postMessage("pull");
|
|
140
|
+
},
|
|
141
|
+
cancel() {
|
|
142
|
+
controller = undefined;
|
|
143
|
+
abort();
|
|
144
|
+
},
|
|
145
|
+
})
|
|
146
|
+
: null;
|
|
147
|
+
resolve(new Response(stream, { status: data.status, headers: data.headers }));
|
|
148
|
+
if (!data.body) cleanup();
|
|
149
|
+
} else if (data.done) {
|
|
150
|
+
controller?.close();
|
|
151
|
+
cleanup();
|
|
152
|
+
} else if (data.chunk) controller?.enqueue(data.chunk);
|
|
153
|
+
};
|
|
154
|
+
if (request.signal.aborted) {
|
|
155
|
+
abort();
|
|
156
|
+
return;
|
|
157
|
+
}
|
|
158
|
+
request.signal.addEventListener("abort", abort, { once: true });
|
|
159
|
+
port.postMessage(
|
|
160
|
+
{
|
|
161
|
+
type: SITE_HTTP,
|
|
162
|
+
requestId,
|
|
163
|
+
path,
|
|
164
|
+
method: request.method,
|
|
165
|
+
headers: [...request.headers],
|
|
166
|
+
...(body === undefined ? {} : { body }),
|
|
167
|
+
} satisfies SiteHttpRequest,
|
|
168
|
+
[channel.port2],
|
|
169
|
+
);
|
|
170
|
+
});
|
|
171
|
+
}
|