@monoflake/sdk 0.0.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 (44) hide show
  1. package/LICENSE +22 -0
  2. package/dist/artifacts/src/anchors.d.ts +34 -0
  3. package/dist/artifacts/src/anchors.js +64 -0
  4. package/dist/artifacts/src/api.d.ts +14 -0
  5. package/dist/artifacts/src/api.js +20 -0
  6. package/dist/artifacts/src/batch.d.ts +105 -0
  7. package/dist/artifacts/src/batch.js +81 -0
  8. package/dist/artifacts/src/engagement.d.ts +61 -0
  9. package/dist/artifacts/src/engagement.js +67 -0
  10. package/dist/artifacts/src/feed.d.ts +42 -0
  11. package/dist/artifacts/src/feed.js +89 -0
  12. package/dist/artifacts/src/index.d.ts +4224 -0
  13. package/dist/artifacts/src/index.js +219 -0
  14. package/dist/artifacts/src/picture.d.ts +116 -0
  15. package/dist/artifacts/src/picture.js +161 -0
  16. package/dist/artifacts/src/resource.d.ts +1391 -0
  17. package/dist/artifacts/src/resource.js +477 -0
  18. package/dist/artifacts/src/schema.d.ts +5 -0
  19. package/dist/artifacts/src/schema.js +18 -0
  20. package/dist/artifacts/src/types.d.ts +396 -0
  21. package/dist/artifacts/src/types.js +0 -0
  22. package/dist/cache/src/index.d.ts +67 -0
  23. package/dist/cache/src/index.js +58 -0
  24. package/dist/imgsrc/src/index.d.ts +16 -0
  25. package/dist/imgsrc/src/index.js +89 -0
  26. package/dist/limits/src/bucket.d.ts +28 -0
  27. package/dist/limits/src/bucket.js +23 -0
  28. package/dist/limits/src/index.d.ts +29 -0
  29. package/dist/limits/src/index.js +62 -0
  30. package/dist/limits/src/key.d.ts +37 -0
  31. package/dist/limits/src/key.js +64 -0
  32. package/dist/robots/src/index.d.ts +98 -0
  33. package/dist/robots/src/index.js +196 -0
  34. package/dist/security/src/agents.d.ts +10 -0
  35. package/dist/security/src/agents.js +95 -0
  36. package/dist/security/src/index.d.ts +12 -0
  37. package/dist/security/src/index.js +37 -0
  38. package/dist/src/index.d.ts +218 -0
  39. package/dist/src/index.js +219 -0
  40. package/dist/store/src/index.d.ts +92 -0
  41. package/dist/store/src/index.js +264 -0
  42. package/dist/symlink/src/index.d.ts +24 -0
  43. package/dist/symlink/src/index.js +89 -0
  44. package/package.json +85 -0
@@ -0,0 +1,218 @@
1
+ import { GITHUB_OWNER, LOOPBACK_HOST, Normalized, PORT_OFFSET, isDevHost, loopbackUrl, normalizePath, normalizedLocation } from "@canmi/me/urls";
2
+ //#region src/index.d.ts
3
+ /**
4
+ * The repositories whose deploy runs the hook passes to the nodes, as GitHub names them: the two
5
+ * whose apps a node runs. Each node holds its own list too, in `DEPLOY_SOURCES`, and that one
6
+ * decides. See infra's spec/architecture/host.md, "The machine pulls; nothing pushes into it".
7
+ */
8
+ export declare const DEPLOY_SOURCES: readonly string[];
9
+ /**
10
+ * The ports each app answers on in development.
11
+ *
12
+ * Pinned, and bound by exactly one checkout at a time. The gaps are the inspector ports, which
13
+ * wrangler takes as port + 1, and they keep clear of LOCAL_PORT (mise.toml). A second copy of an
14
+ * app collides here rather than drifting to a free port, which is the cheapest mutex there is.
15
+ * See spec/toolchain.md.
16
+ */
17
+ export declare const PINNED_PORTS: {
18
+ readonly site: 26511;
19
+ readonly api: 26512;
20
+ readonly alias: 26514;
21
+ readonly cdn: 26516;
22
+ readonly panel: 26519;
23
+ };
24
+ /** Workers reached by binding alone: a port that is the mutex, and no address. */
25
+ export declare const BOUND_PORTS: {
26
+ readonly quota: 26523;
27
+ };
28
+ /** The ports this checkout's servers bind: the pinned ones, shifted in the sandbox. */
29
+ export declare const DEVELOPMENT_PORTS: { readonly [App in keyof typeof PINNED_PORTS | keyof typeof BOUND_PORTS]: number; };
30
+ export type AppName = keyof typeof PINNED_PORTS;
31
+ export type DevelopmentUrls = Readonly<Record<AppName | 'symlink', string>>;
32
+ /**
33
+ * Where the alias layer and the CDN are reached *from a page* in development: through the site.
34
+ *
35
+ * A page carries no host of its own for either prefix -- see spec/toolchain.md, "They bind
36
+ * every interface, and the other two are reached through the site", for why that is what
37
+ * makes the site work from a phone on the same network. The site's API needs no proxy: the
38
+ * site's Worker answers it under `/api/` itself.
39
+ */
40
+ export declare const DEVELOPMENT_PROXY_PATHS: {
41
+ readonly alias: '/alias';
42
+ readonly symlink: '/symlink';
43
+ readonly cdn: '/cdn';
44
+ };
45
+ export declare function developmentUrl(app: AppName): string;
46
+ /**
47
+ * Every app's address in development. The service layer is reached through the development gateway,
48
+ * as it is in production, so its CORS and its lifetimes hold here too; the gateway has no short
49
+ * hosts here, so each is a service of the API host, at the version its short host pins. See
50
+ * spec/architecture/gateway.md and spec/architecture/services.md, "Development goes through the
51
+ * gateway too".
52
+ */
53
+ export declare function developmentUrls(): DevelopmentUrls;
54
+ export declare const URLS: {
55
+ readonly apps: {
56
+ readonly development: Readonly<Record<"alias" | "api" | "cdn" | "panel" | "site" | "symlink", string>>;
57
+ readonly production: {
58
+ readonly site: "https://canmi.net";
59
+ readonly api: "https://api.monoflake.com/v1/site";
60
+ readonly alias: "https://ill.li";
61
+ readonly symlink: 'https://symlink.si';
62
+ readonly cdn: 'https://cdn.monoflake.com';
63
+ readonly panel: "https://infra.internal.ixc.one";
64
+ };
65
+ };
66
+ readonly source: "https://github.com/canmi21/web";
67
+ readonly internal: {
68
+ readonly panel: 'https://infra.internal.ixc.one';
69
+ readonly keeper: 'https://keeper.internal.ixc.one';
70
+ readonly host: 'http://host:11011';
71
+ readonly app: 'https://canmi.app';
72
+ readonly infra: 'https://ffoni.com';
73
+ readonly alias: 'https://ill.li';
74
+ readonly ledger: "https://api.internal.ixc.one/ledger";
75
+ readonly cron: "https://api.internal.ixc.one/cron";
76
+ readonly shot: "https://api.monoflake.com/v1/shot";
77
+ readonly api: {
78
+ readonly private: 'https://api.internal.ixc.one';
79
+ readonly public: 'https://api.monoflake.com';
80
+ };
81
+ readonly status: {
82
+ readonly canonical: 'https://status.canmi.app';
83
+ readonly mirror: 'https://canmi.vercel.app';
84
+ };
85
+ };
86
+ readonly contact: {
87
+ readonly security: 'mailto:security@canmi.net';
88
+ };
89
+ readonly external: {
90
+ readonly github: {
91
+ readonly web: 'https://github.com';
92
+ readonly api: 'https://api.github.com';
93
+ readonly raw: 'https://raw.githubusercontent.com';
94
+ readonly avatars: 'https://avatars.githubusercontent.com';
95
+ readonly cdn: 'https://cdn.jsdelivr.net/gh';
96
+ };
97
+ readonly google: {
98
+ readonly sourcePreferences: 'https://www.google.com/preferences/source';
99
+ };
100
+ readonly registries: {
101
+ readonly npm: 'https://www.npmjs.com';
102
+ readonly cargo: 'https://crates.io';
103
+ readonly cargoIndex: 'https://index.crates.io';
104
+ };
105
+ readonly spdx: 'https://spdx.org/licenses';
106
+ readonly robotstxt: 'https://www.robotstxt.org/robotstxt.html';
107
+ readonly contentSignals: 'https://contentsignals.org';
108
+ readonly contentUsage: 'https://datatracker.ietf.org/doc/draft-ietf-aipref-attach/';
109
+ readonly agentIncident: 'https://openai.com/index/hugging-face-incident-and-the-road-ahead/';
110
+ readonly sentry: {
111
+ readonly site: 'https://a7f2f790ed2fa4f8e0c4310d26d9c39f@o4511131162116096.ingest.us.sentry.io/4511380121976832';
112
+ readonly status: string | undefined;
113
+ };
114
+ readonly feedsmith: 'https://feedsmith.dev';
115
+ readonly indexnow: 'https://api.indexnow.org/IndexNow';
116
+ readonly social: {
117
+ readonly telegram: 'https://t.me';
118
+ readonly twitter: 'https://twitter.com';
119
+ readonly twitterIntent: 'https://twitter.com/intent/follow';
120
+ readonly fediverse: 'https://nya.one';
121
+ readonly bluesky: 'https://bsky.app/profile';
122
+ };
123
+ readonly rust: {
124
+ readonly docs: 'https://docs.rs';
125
+ readonly lib: 'https://lib.rs';
126
+ };
127
+ readonly webring: {
128
+ readonly travellings: 'https://www.travellings.cn/go.html';
129
+ readonly moe: 'https://travel.moe/go?travel=on';
130
+ };
131
+ readonly icpmoe: 'https://icp.gov.moe';
132
+ readonly umami: 'https://cloud.umami.is/script.js';
133
+ readonly umamiGateway: 'https://gateway.umami.is';
134
+ readonly openpanel: 'https://api.openpanel.dev';
135
+ readonly googleFonts: {
136
+ readonly css: 'https://fonts.googleapis.com';
137
+ readonly static: 'https://fonts.gstatic.com';
138
+ };
139
+ readonly doh: {
140
+ readonly cloudflare: 'https://1.1.1.1/dns-query';
141
+ readonly google: 'https://8.8.8.8/resolve';
142
+ };
143
+ readonly geolite: {
144
+ readonly city: 'https://github.com/P3TERX/GeoLite.mmdb/releases/latest/download/GeoLite2-City.mmdb';
145
+ readonly asn: 'https://github.com/P3TERX/GeoLite.mmdb/releases/latest/download/GeoLite2-ASN.mmdb';
146
+ readonly maxmind: 'https://www.maxmind.com';
147
+ };
148
+ };
149
+ };
150
+ /**
151
+ * The service layer's hostnames, every one bound to the gateway, and the codes a deployment's own
152
+ * hostname is spelled from: `{service}-{region}-{provider}` under `deployments`. A provider or a
153
+ * region is added here before anything is placed on it. See spec/architecture/gateway.md.
154
+ */
155
+ export declare const GATEWAY: {
156
+ readonly domains: readonly ['monoflake.com', 'monoflake.net'];
157
+ readonly api: 'api.monoflake.com';
158
+ readonly cdn: 'cdn.monoflake.com';
159
+ readonly deployments: 'ixc.one';
160
+ readonly alias: 'ill.li';
161
+ readonly symlink: 'symlink.si';
162
+ readonly retired: {
163
+ readonly api: 'api.ffoni.com';
164
+ readonly cdn: 'cdn.ffoni.com';
165
+ };
166
+ readonly providers: {
167
+ readonly int: 'our own machines';
168
+ readonly cf: 'Cloudflare';
169
+ readonly vcl: 'Vercel';
170
+ };
171
+ readonly regions: {
172
+ readonly rdu: 'the machine at home, by Raleigh-Durham';
173
+ readonly glo: 'everywhere, as a Worker runs';
174
+ };
175
+ };
176
+ /**
177
+ * Every hostname the gateway answers at home, as a certificate and a router name them: a wildcard
178
+ * over each zone it owns below the apex, and the two apexes it is. The retired hosts are left out:
179
+ * the house never asks them. See infra's spec/architecture/host.md, "The inside side answers the
180
+ * internal gateway alone".
181
+ */
182
+ export declare const GATEWAY_HOSTS: readonly string[];
183
+ /**
184
+ * The names the gateway answers at home, exactly, as the house's resolver answers them: the API and
185
+ * CDN hosts of each domain and the two apexes, and a deployment's own name, read as the profiles
186
+ * read it, from the registered regions and providers. Nothing else in those zones is the gateway's,
187
+ * so nothing else is answered with the node. See infra's spec/architecture/host.md, "The resolver
188
+ * answers the gateway's names, and passes the rest on".
189
+ */
190
+ export declare const GATEWAY_NAMES: {
191
+ readonly exact: readonly [...string[], "ill.li", "symlink.si"];
192
+ readonly deployments: {
193
+ readonly zone: "ixc.one";
194
+ readonly regions: string[];
195
+ readonly providers: string[];
196
+ };
197
+ };
198
+ /**
199
+ * Where each consumer's pages are served, by its service code: what a declaration's `cors.origins`
200
+ * names, so no `service.toml` spells an origin. The status page has three doors, the platform's
201
+ * own among them. See spec/architecture/gateway.md, "A route names who may call it by service
202
+ * code".
203
+ */
204
+ export declare const PAGE_ORIGINS: Readonly<Record<string, readonly string[]>>;
205
+ export type UrlEnvironment = keyof typeof URLS.apps;
206
+ export type UrlMap = (typeof URLS.apps)[UrlEnvironment];
207
+ export declare function pickUrls(isDev: boolean): UrlMap;
208
+ /**
209
+ * The same map as `pickUrls`, as a page served by the site should ask for it.
210
+ *
211
+ * Two functions because two consumers want opposite things from the development entry: a
212
+ * worker wants origins it can put in a CORS list or a redirect, while a page wants paths, since
213
+ * the host it should ask is whichever one it was opened from and need not be `localhost`.
214
+ * Identical to `pickUrls` in production, where nothing is proxied.
215
+ */
216
+ export declare function pageUrls(isDev: boolean): UrlMap;
217
+ //#endregion
218
+ export { GITHUB_OWNER, LOOPBACK_HOST, type Normalized, PORT_OFFSET, isDevHost, loopbackUrl, normalizePath, normalizedLocation };
@@ -0,0 +1,219 @@
1
+ import { CONTACT, EXTERNAL, GITHUB_OWNER, LOOPBACK_HOST, PORT_OFFSET, SITE, SITE_PORT, SOURCE, isDevHost, loopbackUrl, normalizePath, normalizedLocation } from "@canmi/me/urls";
2
+ import { INFRA, PANEL_PORT } from "@monoflake/urls";
3
+ //#region src/index.ts
4
+ /**
5
+ * The platform's addresses, and the whole map as everything above infra reads it: the platform's
6
+ * own declared here, the author's from `canmi` and infra's from `@monoflake/urls`, composed into
7
+ * one shape so a caller asks one place and the Rust mirror has one source. See
8
+ * spec/architecture/layers.md, "Addresses are split by who owns the name".
9
+ */
10
+ /**
11
+ * The repositories whose deploy runs the hook passes to the nodes, as GitHub names them: the two
12
+ * whose apps a node runs. Each node holds its own list too, in `DEPLOY_SOURCES`, and that one
13
+ * decides. See infra's spec/architecture/host.md, "The machine pulls; nothing pushes into it".
14
+ */
15
+ const DEPLOY_SOURCES = ["monoflake/infra", "monoflake/platform"];
16
+ /**
17
+ * The ports each app answers on in development.
18
+ *
19
+ * Pinned, and bound by exactly one checkout at a time. The gaps are the inspector ports, which
20
+ * wrangler takes as port + 1, and they keep clear of LOCAL_PORT (mise.toml). A second copy of an
21
+ * app collides here rather than drifting to a free port, which is the cheapest mutex there is.
22
+ * See spec/toolchain.md.
23
+ */
24
+ const PINNED_PORTS = {
25
+ site: SITE_PORT,
26
+ api: 26512,
27
+ alias: 26514,
28
+ cdn: 26516,
29
+ panel: PANEL_PORT
30
+ };
31
+ /** Workers reached by binding alone: a port that is the mutex, and no address. */
32
+ const BOUND_PORTS = { quota: 26523 };
33
+ /** The ports this checkout's servers bind: the pinned ones, shifted in the sandbox. */
34
+ const DEVELOPMENT_PORTS = Object.fromEntries(Object.entries({
35
+ ...PINNED_PORTS,
36
+ ...BOUND_PORTS
37
+ }).map(([app, port]) => [app, port + PORT_OFFSET]));
38
+ /** The site's scope of the API host, which is the service's name, `site`. */
39
+ const SITE_SCOPE = "site";
40
+ /**
41
+ * Where the alias layer and the CDN are reached *from a page* in development: through the site.
42
+ *
43
+ * A page carries no host of its own for either prefix -- see spec/toolchain.md, "They bind
44
+ * every interface, and the other two are reached through the site", for why that is what
45
+ * makes the site work from a phone on the same network. The site's API needs no proxy: the
46
+ * site's Worker answers it under `/api/` itself.
47
+ */
48
+ const DEVELOPMENT_PROXY_PATHS = {
49
+ alias: "/alias",
50
+ symlink: "/symlink",
51
+ cdn: "/cdn"
52
+ };
53
+ function developmentUrl(app) {
54
+ return `http://localhost:${DEVELOPMENT_PORTS[app]}`;
55
+ }
56
+ /**
57
+ * Every app's address in development. The service layer is reached through the development gateway,
58
+ * as it is in production, so its CORS and its lifetimes hold here too; the gateway has no short
59
+ * hosts here, so each is a service of the API host, at the version its short host pins. See
60
+ * spec/architecture/gateway.md and spec/architecture/services.md, "Development goes through the
61
+ * gateway too".
62
+ */
63
+ function developmentUrls() {
64
+ const gateway = developmentUrl("api");
65
+ return {
66
+ site: developmentUrl("site"),
67
+ api: `${gateway}/v1/${SITE_SCOPE}`,
68
+ alias: `${gateway}/v1/aka`,
69
+ symlink: `${gateway}/v1/aka/symlink`,
70
+ cdn: `${gateway}/v3/cdn`,
71
+ panel: developmentUrl("panel")
72
+ };
73
+ }
74
+ const development = developmentUrls();
75
+ /** The API host's two sides: private, where every container asks, and public, past the gateway. */
76
+ const API = {
77
+ private: "https://api.internal.ixc.one",
78
+ public: "https://api.monoflake.com"
79
+ };
80
+ /**
81
+ * The domains owned here, which the production map below reads rather than spelling twice. `infra`
82
+ * is the retired apex api and cdn hung off; `alias` the alias layer's. `app` is the suffix every
83
+ * interface is on behind Access, see spec/architecture/services.md; `panel`, `keeper` and `host`
84
+ * are infra's, see infra's spec/architecture/host.md; `ledger` is where every service records its
85
+ * tasks, see ledger.md; `shot` is the public scope a capture's pictures are named under, see
86
+ * shot.md.
87
+ */
88
+ const INTERNAL = {
89
+ app: "https://canmi.app",
90
+ infra: "https://ffoni.com",
91
+ alias: "https://ill.li",
92
+ ...INFRA,
93
+ ledger: `${API.private}/ledger`,
94
+ cron: `${API.private}/cron`,
95
+ shot: `${API.public}/v1/shot`,
96
+ api: API,
97
+ status: {
98
+ canonical: "https://status.canmi.app",
99
+ mirror: "https://canmi.vercel.app"
100
+ }
101
+ };
102
+ const URLS = {
103
+ apps: {
104
+ development,
105
+ production: {
106
+ site: SITE,
107
+ api: `${API.public}/v1/${SITE_SCOPE}`,
108
+ alias: INTERNAL.alias,
109
+ symlink: "https://symlink.si",
110
+ cdn: "https://cdn.monoflake.com",
111
+ panel: INTERNAL.panel
112
+ }
113
+ },
114
+ source: SOURCE,
115
+ internal: INTERNAL,
116
+ contact: CONTACT,
117
+ external: {
118
+ ...EXTERNAL,
119
+ doh: {
120
+ cloudflare: "https://1.1.1.1/dns-query",
121
+ google: "https://8.8.8.8/resolve"
122
+ },
123
+ geolite: {
124
+ city: "https://github.com/P3TERX/GeoLite.mmdb/releases/latest/download/GeoLite2-City.mmdb",
125
+ asn: "https://github.com/P3TERX/GeoLite.mmdb/releases/latest/download/GeoLite2-ASN.mmdb",
126
+ maxmind: "https://www.maxmind.com"
127
+ }
128
+ }
129
+ };
130
+ /**
131
+ * The service layer's hostnames, every one bound to the gateway, and the codes a deployment's own
132
+ * hostname is spelled from: `{service}-{region}-{provider}` under `deployments`. A provider or a
133
+ * region is added here before anything is placed on it. See spec/architecture/gateway.md.
134
+ */
135
+ const GATEWAY = {
136
+ domains: ["monoflake.com", "monoflake.net"],
137
+ api: "api.monoflake.com",
138
+ cdn: "cdn.monoflake.com",
139
+ deployments: "ixc.one",
140
+ alias: "ill.li",
141
+ symlink: "symlink.si",
142
+ retired: {
143
+ api: "api.ffoni.com",
144
+ cdn: "cdn.ffoni.com"
145
+ },
146
+ providers: {
147
+ int: "our own machines",
148
+ cf: "Cloudflare",
149
+ vcl: "Vercel"
150
+ },
151
+ regions: {
152
+ rdu: "the machine at home, by Raleigh-Durham",
153
+ glo: "everywhere, as a Worker runs"
154
+ }
155
+ };
156
+ /**
157
+ * Every hostname the gateway answers at home, as a certificate and a router name them: a wildcard
158
+ * over each zone it owns below the apex, and the two apexes it is. The retired hosts are left out:
159
+ * the house never asks them. See infra's spec/architecture/host.md, "The inside side answers the
160
+ * internal gateway alone".
161
+ */
162
+ const GATEWAY_HOSTS = [
163
+ ...GATEWAY.domains.map((domain) => `*.${domain}`),
164
+ `*.${GATEWAY.deployments}`,
165
+ GATEWAY.alias,
166
+ GATEWAY.symlink
167
+ ];
168
+ /**
169
+ * The names the gateway answers at home, exactly, as the house's resolver answers them: the API and
170
+ * CDN hosts of each domain and the two apexes, and a deployment's own name, read as the profiles
171
+ * read it, from the registered regions and providers. Nothing else in those zones is the gateway's,
172
+ * so nothing else is answered with the node. See infra's spec/architecture/host.md, "The resolver
173
+ * answers the gateway's names, and passes the rest on".
174
+ */
175
+ const GATEWAY_NAMES = {
176
+ exact: [
177
+ ...GATEWAY.domains.flatMap((domain) => [`api.${domain}`, `cdn.${domain}`]),
178
+ GATEWAY.alias,
179
+ GATEWAY.symlink
180
+ ],
181
+ deployments: {
182
+ zone: GATEWAY.deployments,
183
+ regions: Object.keys(GATEWAY.regions),
184
+ providers: Object.keys(GATEWAY.providers)
185
+ }
186
+ };
187
+ /**
188
+ * Where each consumer's pages are served, by its service code: what a declaration's `cors.origins`
189
+ * names, so no `service.toml` spells an origin. The status page has three doors, the platform's
190
+ * own among them. See spec/architecture/gateway.md, "A route names who may call it by service
191
+ * code".
192
+ */
193
+ const PAGE_ORIGINS = {
194
+ site: [URLS.apps.production.site],
195
+ status: [
196
+ INTERNAL.status.canonical,
197
+ INTERNAL.status.mirror,
198
+ INTERNAL.app
199
+ ]
200
+ };
201
+ function pickUrls(isDev) {
202
+ return isDev ? URLS.apps.development : URLS.apps.production;
203
+ }
204
+ /**
205
+ * The same map as `pickUrls`, as a page served by the site should ask for it.
206
+ *
207
+ * Two functions because two consumers want opposite things from the development entry: a
208
+ * worker wants origins it can put in a CORS list or a redirect, while a page wants paths, since
209
+ * the host it should ask is whichever one it was opened from and need not be `localhost`.
210
+ * Identical to `pickUrls` in production, where nothing is proxied.
211
+ */
212
+ function pageUrls(isDev) {
213
+ return isDev ? {
214
+ ...URLS.apps.development,
215
+ ...DEVELOPMENT_PROXY_PATHS
216
+ } : URLS.apps.production;
217
+ }
218
+ //#endregion
219
+ export { BOUND_PORTS, DEPLOY_SOURCES, DEVELOPMENT_PORTS, DEVELOPMENT_PROXY_PATHS, GATEWAY, GATEWAY_HOSTS, GATEWAY_NAMES, GITHUB_OWNER, LOOPBACK_HOST, PAGE_ORIGINS, PINNED_PORTS, PORT_OFFSET, URLS, developmentUrl, developmentUrls, isDevHost, loopbackUrl, normalizePath, normalizedLocation, pageUrls, pickUrls };
@@ -0,0 +1,92 @@
1
+ import { recordKey, storageKey } from "../../artifacts/src/index.js";
2
+ import { Fetcher, R2Bucket } from "@cloudflare/workers-types";
3
+ //#region store/src/index.d.ts
4
+ export type Bindings = {
5
+ STORE?: R2Bucket;
6
+ /** Present only under `wrangler dev --assets`; see the dev task in mise.toml. */
7
+ ASSETS?: Fetcher;
8
+ };
9
+ export type Found = {
10
+ body: ReadableStream;
11
+ contentType: string;
12
+ etag?: string;
13
+ /** What was served, when a range was asked for and satisfied. Absent for a whole object. */
14
+ partial?: {
15
+ offset: number;
16
+ length: number;
17
+ total: number;
18
+ };
19
+ };
20
+ /**
21
+ * A range that names nothing inside the object.
22
+ *
23
+ * Its own result rather than a null, because the two mean opposite things to a caller: a missing
24
+ * object is 404 and a range past the end of a present one is 416, and 416 has to report the size
25
+ * so the client can ask again. Answering 404 for the second would send a browser looking for a
26
+ * file it already found.
27
+ */
28
+ export type Unsatisfiable = {
29
+ unsatisfiable: true;
30
+ total: number;
31
+ };
32
+ export declare function isUnsatisfiable(value: Found | Unsatisfiable | null): value is Unsatisfiable;
33
+ /**
34
+ * Read an object, or the part of one a `Range` header asks for.
35
+ *
36
+ * `range` is the header verbatim, parsed here in the one place with a grammar to obey -- see
37
+ * web's spec/architecture/data.md, "Assets are addressed by their content", for why the worker
38
+ * resolves it rather than the bucket, and what an unparseable or multipart request gets instead.
39
+ */
40
+ export declare function read(env: Bindings, key: string): Promise<Found | null>;
41
+ export declare function read(env: Bindings, key: string, range: string | null | undefined): Promise<Found | Unsatisfiable | null>;
42
+ /** What a head reports. `uploaded` is null only where the store keeps no date; see `measure`. */
43
+ export type Measured = {
44
+ size: number;
45
+ uploaded: Date | null;
46
+ };
47
+ /**
48
+ * What is known about an object under a key, without reading a byte of it.
49
+ *
50
+ * A caller that has to refuse work before paying for it needs the size first: an isolate gets
51
+ * 128 MB for its heap and its WebAssembly together, so a length that arrives alongside the bytes
52
+ * arrives too late to be a limit. Null is no such object, which makes this a presence check too.
53
+ * The date rides along because the same head already carries it, and a caller wanting both
54
+ * should not spend a second round trip on the second one.
55
+ */
56
+ export declare function measure(env: Bindings, key: string): Promise<Measured | null>;
57
+ export declare function isContentId(value: string): boolean;
58
+ /**
59
+ * A stored object as an HTTP response, with ETag only when the store supplied one.
60
+ *
61
+ * `Accept-Ranges` on every one of them, because every object here is served through a route that
62
+ * can answer a range -- a player seeking, a `<video>` element probing for duration, a resumed
63
+ * download. The header is what tells a client it may ask; without it a browser fetches whole
64
+ * files to read a byte near the end of them.
65
+ */
66
+ export declare function toResponse(found: Found): Response;
67
+ /**
68
+ * The answer to a range that names nothing inside the object.
69
+ *
70
+ * 416 carries the size so the client can ask again knowing it, which is the whole reason this is
71
+ * not a 404: the object is there, the question was wrong.
72
+ */
73
+ export declare function unsatisfiableResponse(total: number): Response;
74
+ /**
75
+ * Bytes already in hand, answered as a `Range` asked for them.
76
+ *
77
+ * For a body that was derived rather than stored: there is no object to ask the bucket for a part
78
+ * of, so the artifact is produced whole and the slice is taken here. The grammar stays in this
79
+ * module -- one parser, one set of spellings -- and a header it does not implement is served
80
+ * whole, which is what a recipient is allowed to do. See spec/architecture/delivery.md.
81
+ */
82
+ export declare function rangedResponse(bytes: Uint8Array, contentType: string, range: string | null | undefined): Response;
83
+ /**
84
+ * Content type from the key, for objects stored without one.
85
+ *
86
+ * R2 keeps whatever `httpMetadata` was set at upload, and rclone does set it, but an object
87
+ * put by hand through the dashboard has none. Serving those as `application/octet-stream`
88
+ * makes a browser download a favicon instead of drawing it.
89
+ */
90
+ export declare function contentTypeFor(key: string): string;
91
+ //#endregion
92
+ export { recordKey, storageKey };