@astrale-os/adapter-cloudflare 0.5.0-beta.2 → 0.5.0-beta.21
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 +11 -0
- package/dist/adapter.d.ts +17 -0
- package/dist/adapter.js +140 -0
- package/dist/build/artifact.d.ts +8 -0
- package/dist/build/artifact.js +179 -0
- package/dist/build/closure.d.ts +2 -0
- package/dist/build/closure.js +22 -0
- package/dist/build/codegen/execution.d.ts +13 -0
- package/dist/build/codegen/execution.js +44 -0
- package/dist/build/codegen/gateway.d.ts +1 -0
- package/dist/build/codegen/gateway.js +7 -0
- package/dist/build/codegen/merge.d.ts +0 -1
- package/dist/build/codegen/merge.js +0 -1
- package/dist/build/codegen/wrangler.d.ts +10 -1
- package/dist/build/codegen/wrangler.js +22 -16
- package/dist/build/configuration.d.ts +9 -0
- package/dist/build/configuration.js +40 -0
- package/dist/build/frontend-v1.d.ts +16 -0
- package/dist/build/frontend-v1.js +133 -0
- package/dist/build/index.d.ts +8 -16
- package/dist/build/index.js +8 -16
- package/dist/build/metafile.d.ts +5 -0
- package/dist/build/metafile.js +14 -0
- package/dist/build/parse-output.d.ts +0 -1
- package/dist/build/parse-output.js +0 -1
- package/dist/build/qualification.d.ts +5 -0
- package/dist/build/qualification.js +7 -0
- package/dist/build/roots.d.ts +2 -0
- package/dist/build/roots.js +34 -0
- package/dist/build/wrangler-cli.d.ts +53 -34
- package/dist/build/wrangler-cli.js +284 -111
- package/dist/cloudflare.d.ts +1 -34
- package/dist/cloudflare.js +1 -205
- package/dist/deploy/deploy.d.ts +17 -0
- package/dist/deploy/deploy.js +207 -0
- package/dist/deploy/index.d.ts +1 -0
- package/dist/deploy/index.js +1 -0
- package/dist/identity/binding.d.ts +2 -0
- package/dist/identity/binding.js +2 -0
- package/dist/identity/material.d.ts +7 -0
- package/dist/identity/material.js +42 -0
- package/dist/identity/secret.d.ts +3 -0
- package/dist/identity/secret.js +7 -0
- package/dist/identity/source.d.ts +26 -0
- package/dist/identity/source.js +98 -0
- package/dist/index.d.ts +3 -4
- package/dist/index.js +3 -4
- package/dist/params.d.ts +18 -5
- package/dist/params.js +0 -1
- package/dist/release/index.d.ts +2 -0
- package/dist/release/index.js +2 -0
- package/dist/release/namespace.d.ts +2 -0
- package/dist/release/namespace.js +6 -0
- package/dist/release/target.d.ts +2 -0
- package/dist/release/target.js +9 -0
- package/dist/worker/entry.d.ts +34 -0
- package/dist/worker/entry.js +157 -0
- package/dist/worker/fetch.d.ts +11 -0
- package/dist/worker/fetch.js +31 -0
- package/dist/worker/gateway.d.ts +15 -0
- package/dist/worker/gateway.js +26 -0
- package/dist/worker/identity.d.ts +7 -0
- package/dist/worker/identity.js +23 -0
- package/dist/worker/index.d.ts +3 -48
- package/dist/worker/index.js +3 -186
- package/package.json +21 -18
- package/template/astrale.config.ts +19 -11
- package/dist/build/codegen/identity.d.ts +0 -10
- package/dist/build/codegen/identity.d.ts.map +0 -1
- package/dist/build/codegen/identity.js +0 -32
- package/dist/build/codegen/identity.js.map +0 -1
- package/dist/build/codegen/merge.d.ts.map +0 -1
- package/dist/build/codegen/merge.js.map +0 -1
- package/dist/build/codegen/worker.d.ts +0 -12
- package/dist/build/codegen/worker.d.ts.map +0 -1
- package/dist/build/codegen/worker.js +0 -40
- package/dist/build/codegen/worker.js.map +0 -1
- package/dist/build/codegen/wrangler.d.ts.map +0 -1
- package/dist/build/codegen/wrangler.js.map +0 -1
- package/dist/build/frontend.d.ts +0 -26
- package/dist/build/frontend.d.ts.map +0 -1
- package/dist/build/frontend.js +0 -263
- package/dist/build/frontend.js.map +0 -1
- package/dist/build/index.d.ts.map +0 -1
- package/dist/build/index.js.map +0 -1
- package/dist/build/parse-output.d.ts.map +0 -1
- package/dist/build/parse-output.js.map +0 -1
- package/dist/build/prepare.d.ts +0 -18
- package/dist/build/prepare.d.ts.map +0 -1
- package/dist/build/prepare.js +0 -117
- package/dist/build/prepare.js.map +0 -1
- package/dist/build/worker.d.ts +0 -15
- package/dist/build/worker.d.ts.map +0 -1
- package/dist/build/worker.js +0 -21
- package/dist/build/worker.js.map +0 -1
- package/dist/build/wrangler-cli.d.ts.map +0 -1
- package/dist/build/wrangler-cli.js.map +0 -1
- package/dist/cloudflare.d.ts.map +0 -1
- package/dist/cloudflare.js.map +0 -1
- package/dist/index.d.ts.map +0 -1
- package/dist/index.js.map +0 -1
- package/dist/params.d.ts.map +0 -1
- package/dist/params.js.map +0 -1
- package/dist/worker/index.d.ts.map +0 -1
- package/dist/worker/index.js.map +0 -1
- package/src/build/codegen/identity.ts +0 -40
- package/src/build/codegen/merge.ts +0 -92
- package/src/build/codegen/worker.ts +0 -53
- package/src/build/codegen/wrangler.ts +0 -127
- package/src/build/frontend.ts +0 -324
- package/src/build/index.ts +0 -29
- package/src/build/parse-output.ts +0 -60
- package/src/build/prepare.ts +0 -161
- package/src/build/worker.ts +0 -37
- package/src/build/wrangler-cli.ts +0 -362
- package/src/cloudflare.ts +0 -251
- package/src/index.ts +0 -21
- package/src/params.ts +0 -92
- package/src/worker/index.ts +0 -276
- package/src/worker/tsconfig.json +0 -10
package/src/params.ts
DELETED
|
@@ -1,92 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* `CloudflareParams` — the provider-typed config for the Cloudflare adapter.
|
|
3
|
-
*
|
|
4
|
-
* One type covers every env; per-env differences are just optional fields. The
|
|
5
|
-
* same `{ dev, prod, canary, … }` map a developer writes in `astrale.config.ts`
|
|
6
|
-
* is `Record<string, CloudflareParams>`.
|
|
7
|
-
*
|
|
8
|
-
* Three deployment shapes fall out of which fields are set:
|
|
9
|
-
* • dev (local) — `watch()` runs `wrangler dev`; URL = http://localhost:<port>
|
|
10
|
-
* • dev-remote — `deploy()` with no `route`; URL = https://<name>.<sub>.workers.dev
|
|
11
|
-
* • remote (custom) — `deploy()` with `route`; URL = https://<route>
|
|
12
|
-
*/
|
|
13
|
-
export interface CloudflareParams {
|
|
14
|
-
/**
|
|
15
|
-
* Custom route / hostname for a routed deploy, e.g. `'crm.acme.dev'`. Omit to
|
|
16
|
-
* deploy to `*.workers.dev`. Ignored by local `wrangler dev` (URL is
|
|
17
|
-
* localhost) but still used as the placeholder base domain there.
|
|
18
|
-
*/
|
|
19
|
-
readonly route?: string
|
|
20
|
-
/** Gitignored secrets file (whole contents = secrets), e.g. `'.env.dev'`. */
|
|
21
|
-
readonly secrets?: string
|
|
22
|
-
/** Local dev port for `wrangler dev`. Default 8787. */
|
|
23
|
-
readonly port?: number
|
|
24
|
-
/**
|
|
25
|
-
* Public URL the dev server is reached through (tunnel / sandbox preview /
|
|
26
|
-
* reverse proxy), e.g. `'https://my-box.preview.dev'`. Sets BOTH effects an
|
|
27
|
-
* off-localhost dev needs: wrangler binds 0.0.0.0 (reachable from outside)
|
|
28
|
-
* and `WORKER_URL` is pinned to this URL so the worker's per-request-Host
|
|
29
|
-
* identity (`iss`) doesn't drift to the proxy's internal hostname.
|
|
30
|
-
* Usually injected by `pnpm dev --host <url>` rather than written here.
|
|
31
|
-
*/
|
|
32
|
-
readonly host?: string
|
|
33
|
-
/** Override the Worker name. Default: derived from the domain origin. */
|
|
34
|
-
readonly workerName?: string
|
|
35
|
-
/** Run `wrangler dev --remote` (edge isolate) instead of local workerd. */
|
|
36
|
-
readonly remote?: boolean
|
|
37
|
-
/** Extra plain (non-secret) vars to inject as Worker vars. */
|
|
38
|
-
readonly vars?: Record<string, string>
|
|
39
|
-
/**
|
|
40
|
-
* Escape hatch: raw wrangler config deep-merged over the generated base. Use
|
|
41
|
-
* it to declare extra bindings the adapter has no typed field for — KV, R2,
|
|
42
|
-
* D1, queues, service bindings, extra `compatibility_flags`, cron `triggers`,
|
|
43
|
-
* Hyperdrive, etc.
|
|
44
|
-
*
|
|
45
|
-
* wrangler: {
|
|
46
|
-
* kv_namespaces: [{ binding: 'CACHE', id: '<kv-id>' }],
|
|
47
|
-
* r2_buckets: [{ binding: 'FILES', bucket_name: 'my-bucket' }],
|
|
48
|
-
* }
|
|
49
|
-
*
|
|
50
|
-
* The merge is additive: arrays concat (so your `services` keep the adapter's
|
|
51
|
-
* `SELF` binding and your `compatibility_flags` keep `nodejs_compat`); new
|
|
52
|
-
* keys are added as-is. The adapter-owned keys `name`, `main`, `assets`,
|
|
53
|
-
* `routes` are rejected — use `workerName` and `route` instead. Avoid
|
|
54
|
-
* the reserved binding names `SELF` and `ASSETS`. Durable Objects need extra
|
|
55
|
-
* worker-entry codegen and aren't supported through this field yet.
|
|
56
|
-
*/
|
|
57
|
-
readonly wrangler?: Record<string, unknown>
|
|
58
|
-
/**
|
|
59
|
-
* Route subrequests to platform INSTANCE hostnames through a service binding
|
|
60
|
-
* instead of the public edge. A Cloudflare Worker can't fetch a same-zone
|
|
61
|
-
* hostname served by another Worker — Cloudflare 522s it — so without this the
|
|
62
|
-
* worker can't fetch an instance kernel's JWKS to verify an inbound credential
|
|
63
|
-
* from that instance, and every cross-instance call (install hooks, the GUI's
|
|
64
|
-
* delegated calls, authed views) fails with `2002 Credential verification
|
|
65
|
-
* failed`. Point it at a router Worker that reaches those hosts internally
|
|
66
|
-
* (Astrale: `admin-router`).
|
|
67
|
-
*
|
|
68
|
-
* Wires BOTH halves the SDK needs: the `<binding>` service binding in the
|
|
69
|
-
* generated wrangler config, and a `routeSubrequest` predicate in the worker
|
|
70
|
-
* entry that diverts matching hosts through it.
|
|
71
|
-
*
|
|
72
|
-
* ON BY DEFAULT (targets `admin-router`) so every adapter-deployed worker can
|
|
73
|
-
* verify cross-instance credentials out of the box. Pass `false` to disable
|
|
74
|
-
* (a domain that never talks to another instance, or an account without a
|
|
75
|
-
* router), or an object to override the target / binding name / host match.
|
|
76
|
-
*
|
|
77
|
-
* router: false // opt out
|
|
78
|
-
* router: { service: 'my-router' } // override target
|
|
79
|
-
*/
|
|
80
|
-
readonly router?:
|
|
81
|
-
| false
|
|
82
|
-
| {
|
|
83
|
-
/** Router Worker the binding targets. Default `'admin-router'`. */
|
|
84
|
-
readonly service?: string
|
|
85
|
-
/** Service-binding name the worker reads. Default `'ROUTER'`. */
|
|
86
|
-
readonly binding?: string
|
|
87
|
-
/** Host suffix that marks an instance host. Default `'.astrale.ai'`. */
|
|
88
|
-
readonly hostSuffix?: string
|
|
89
|
-
/** Min dot-separated label count for an instance host. Default `4` (`<slug>.<region>.astrale.ai`). */
|
|
90
|
-
readonly minLabels?: number
|
|
91
|
-
}
|
|
92
|
-
}
|
package/src/worker/index.ts
DELETED
|
@@ -1,276 +0,0 @@
|
|
|
1
|
-
import type { schema } from '@astrale-os/kernel-dsl/v1'
|
|
2
|
-
import type { DomainDefinition, FrontendRoute } from '@astrale-os/sdk'
|
|
3
|
-
import type {
|
|
4
|
-
Application,
|
|
5
|
-
RemoteDeploymentInput,
|
|
6
|
-
RemoteIdentityInput,
|
|
7
|
-
} from '@astrale-os/sdk/server'
|
|
8
|
-
import type { ExecutionContext, Hono } from 'hono'
|
|
9
|
-
|
|
10
|
-
import { issuer } from '@astrale-os/kernel-core/auth'
|
|
11
|
-
import { createRemoteApplication } from '@astrale-os/sdk/server'
|
|
12
|
-
import { Hono as HonoApplication } from 'hono'
|
|
13
|
-
|
|
14
|
-
const MAXIMUM_CACHED_APPLICATIONS = 4
|
|
15
|
-
const APPLICATION_CLOSE_TIMEOUT_MS = 5_000
|
|
16
|
-
|
|
17
|
-
/** SDK-owned Publication manifest passed through without adapter interpretation. */
|
|
18
|
-
export type CloudflareManifest = NonNullable<RemoteDeploymentInput['manifest']>
|
|
19
|
-
|
|
20
|
-
export interface Fetcher {
|
|
21
|
-
fetch(request: Request): Response | Promise<Response>
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
/** Adapter-owned bindings generated into every Cloudflare deployment. */
|
|
25
|
-
export interface CloudflareAdapterBindings {
|
|
26
|
-
/** Native Cloudflare deployment metadata (direct Wrangler deployments). */
|
|
27
|
-
readonly ASTRALE_VERSION_METADATA?: {
|
|
28
|
-
readonly id: string
|
|
29
|
-
readonly tag: string
|
|
30
|
-
readonly timestamp: string
|
|
31
|
-
}
|
|
32
|
-
/** Content-derived generation supplied by providers without version metadata. */
|
|
33
|
-
readonly ASTRALE_DEPLOYMENT_VERSION?: string
|
|
34
|
-
readonly WORKER_URL?: string
|
|
35
|
-
readonly ASSETS?: Fetcher
|
|
36
|
-
readonly SELF?: Fetcher
|
|
37
|
-
readonly FRONTEND_DEV_URL?: string
|
|
38
|
-
readonly DISPATCHER?: { get(name: string): Fetcher }
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
export interface CloudflareWorkerConfig<
|
|
42
|
-
S extends schema.DomainSchema,
|
|
43
|
-
Bindings extends CloudflareAdapterBindings,
|
|
44
|
-
Environment,
|
|
45
|
-
> {
|
|
46
|
-
readonly definition: DomainDefinition<S>
|
|
47
|
-
readonly privateKey:
|
|
48
|
-
| RemoteIdentityInput['privateKey']
|
|
49
|
-
| ((bindings: Bindings) => RemoteIdentityInput['privateKey'])
|
|
50
|
-
/** Compose provider bindings into the exact Domain environment once per deployment generation. */
|
|
51
|
-
readonly resolveEnvironment?: (bindings: Bindings) => Environment | Promise<Environment>
|
|
52
|
-
readonly manifest?: CloudflareManifest
|
|
53
|
-
readonly resolveUrl?: (bindings: Bindings, requestOrigin: string) => string
|
|
54
|
-
readonly selfBinding?: (bindings: Bindings) => Fetcher | null | undefined
|
|
55
|
-
readonly routeSubrequest?: (url: URL, bindings: Bindings) => Fetcher | null | undefined
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
export interface CloudflareWorker<Environment> {
|
|
59
|
-
fetch(
|
|
60
|
-
request: Request,
|
|
61
|
-
environment: Environment,
|
|
62
|
-
executionContext?: ExecutionContext,
|
|
63
|
-
): Response | Promise<Response>
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
interface CachedApplication<Environment> {
|
|
67
|
-
readonly origin: string
|
|
68
|
-
readonly application: Application<Hono>
|
|
69
|
-
readonly environment: Environment
|
|
70
|
-
}
|
|
71
|
-
|
|
72
|
-
/**
|
|
73
|
-
* Compose one Cloudflare module Worker without request-global mutation.
|
|
74
|
-
* Environment bindings are captured once per immutable serving URL/version generation.
|
|
75
|
-
*/
|
|
76
|
-
export function cloudflareWorkerEntry<
|
|
77
|
-
Bindings extends CloudflareAdapterBindings,
|
|
78
|
-
Environment = Bindings,
|
|
79
|
-
>() {
|
|
80
|
-
return function <const S extends schema.DomainSchema>(
|
|
81
|
-
config: CloudflareWorkerConfig<S, Bindings, Environment>,
|
|
82
|
-
): CloudflareWorker<Bindings> {
|
|
83
|
-
const applications = new Map<string, CachedApplication<Environment>>()
|
|
84
|
-
|
|
85
|
-
const applicationFor = async (
|
|
86
|
-
url: string,
|
|
87
|
-
bindings: Bindings,
|
|
88
|
-
): Promise<CachedApplication<Environment>> => {
|
|
89
|
-
const version = deploymentVersion(bindings)
|
|
90
|
-
const key = `${url}\u0000${version}`
|
|
91
|
-
const cached = applications.get(key)
|
|
92
|
-
if (cached !== undefined) return cached
|
|
93
|
-
const environment =
|
|
94
|
-
config.resolveEnvironment === undefined
|
|
95
|
-
? (bindings as unknown as Environment)
|
|
96
|
-
: await config.resolveEnvironment(bindings)
|
|
97
|
-
|
|
98
|
-
const routedFetch: typeof fetch = async (input, init) => {
|
|
99
|
-
const request = new Request(input, init)
|
|
100
|
-
const destination = new URL(request.url)
|
|
101
|
-
if (destination.origin === new URL(url).origin) {
|
|
102
|
-
const self = config.selfBinding?.(bindings)
|
|
103
|
-
if (self !== null && self !== undefined) return self.fetch(request)
|
|
104
|
-
return serving.app.fetch(request, environment)
|
|
105
|
-
}
|
|
106
|
-
const route = config.routeSubrequest?.(destination, bindings)
|
|
107
|
-
return route === null || route === undefined ? fetch(request) : route.fetch(request)
|
|
108
|
-
}
|
|
109
|
-
|
|
110
|
-
const deploymentQuery = `deployment=${encodeURIComponent(version)}`
|
|
111
|
-
const issuerId = issuer.accept(url)
|
|
112
|
-
const host = new HonoApplication()
|
|
113
|
-
host.get('/meta', (context) =>
|
|
114
|
-
context.json({
|
|
115
|
-
origin: config.definition.schema.origin,
|
|
116
|
-
issuer: issuerId,
|
|
117
|
-
schemaRevision: config.definition.domain.$.revision,
|
|
118
|
-
deploymentVersion: version,
|
|
119
|
-
}),
|
|
120
|
-
)
|
|
121
|
-
const serving: Application<Hono> = createRemoteApplication({
|
|
122
|
-
definition: config.definition,
|
|
123
|
-
environment,
|
|
124
|
-
identity: {
|
|
125
|
-
issuer: issuerId,
|
|
126
|
-
subject: config.definition.schema.origin,
|
|
127
|
-
privateKey:
|
|
128
|
-
typeof config.privateKey === 'function'
|
|
129
|
-
? config.privateKey(bindings)
|
|
130
|
-
: config.privateKey,
|
|
131
|
-
fetch: routedFetch,
|
|
132
|
-
...(new URL(url).protocol === 'http:' ? { allowInsecureHttp: true } : {}),
|
|
133
|
-
},
|
|
134
|
-
deployment: {
|
|
135
|
-
bundleHref: `${url}/.well-known/astrale/domain.bundle.json?${deploymentQuery}`,
|
|
136
|
-
endpoint: { http: `${url}/invoke` },
|
|
137
|
-
...(config.definition.frontend === undefined
|
|
138
|
-
? {}
|
|
139
|
-
: { frontendBaseHref: url, frontendCacheKey: version }),
|
|
140
|
-
...(config.manifest === undefined ? {} : { manifest: config.manifest }),
|
|
141
|
-
installation: {
|
|
142
|
-
href: `${url}/install`,
|
|
143
|
-
method: 'POST',
|
|
144
|
-
authentication: { kind: 'public' },
|
|
145
|
-
},
|
|
146
|
-
},
|
|
147
|
-
app: host,
|
|
148
|
-
server: {
|
|
149
|
-
path: '/invoke',
|
|
150
|
-
health: { probe: { check: () => true } },
|
|
151
|
-
limits: {
|
|
152
|
-
maximumRequestBytes: 1024 * 1024,
|
|
153
|
-
maximumPublicationBytes: 1024 * 1024,
|
|
154
|
-
maximumBundleBytes: 8 * 1024 * 1024,
|
|
155
|
-
maximumInstallationBytes: 8 * 1024 * 1024,
|
|
156
|
-
invocationTimeoutMs: 30_000,
|
|
157
|
-
},
|
|
158
|
-
},
|
|
159
|
-
})
|
|
160
|
-
const created = Object.freeze({
|
|
161
|
-
origin: new URL(url).origin,
|
|
162
|
-
application: serving,
|
|
163
|
-
environment,
|
|
164
|
-
})
|
|
165
|
-
if (applications.size >= MAXIMUM_CACHED_APPLICATIONS) {
|
|
166
|
-
const oldest = applications.keys().next().value
|
|
167
|
-
if (oldest !== undefined) {
|
|
168
|
-
const evicted = applications.get(oldest)
|
|
169
|
-
applications.delete(oldest)
|
|
170
|
-
if (evicted !== undefined) {
|
|
171
|
-
try {
|
|
172
|
-
await closeEvictedApplication(evicted.application)
|
|
173
|
-
} catch (cause) {
|
|
174
|
-
await serving
|
|
175
|
-
.close({ deadline: Date.now() + APPLICATION_CLOSE_TIMEOUT_MS })
|
|
176
|
-
.catch(() => undefined)
|
|
177
|
-
throw cause
|
|
178
|
-
}
|
|
179
|
-
}
|
|
180
|
-
}
|
|
181
|
-
}
|
|
182
|
-
applications.set(key, created)
|
|
183
|
-
return created
|
|
184
|
-
}
|
|
185
|
-
|
|
186
|
-
return Object.freeze({
|
|
187
|
-
async fetch(request: Request, bindings: Bindings, executionContext?: ExecutionContext) {
|
|
188
|
-
const requestUrl = new URL(request.url)
|
|
189
|
-
if (config.definition.frontend !== undefined) {
|
|
190
|
-
const asset = await frontendAsset(config.definition, bindings, requestUrl, request)
|
|
191
|
-
if (asset !== undefined) return asset
|
|
192
|
-
}
|
|
193
|
-
const publicUrl = canonicalServingUrl(
|
|
194
|
-
config.resolveUrl?.(bindings, requestOrigin(requestUrl, request)) ??
|
|
195
|
-
bindings.WORKER_URL ??
|
|
196
|
-
requestOrigin(requestUrl, request),
|
|
197
|
-
)
|
|
198
|
-
const serving = await applicationFor(publicUrl, bindings)
|
|
199
|
-
return serving.application.app.fetch(request, serving.environment, executionContext)
|
|
200
|
-
},
|
|
201
|
-
})
|
|
202
|
-
}
|
|
203
|
-
}
|
|
204
|
-
|
|
205
|
-
/** Close an evicted Application before its environment bindings leave the cache. */
|
|
206
|
-
export function closeEvictedApplication(
|
|
207
|
-
application: Pick<Application, 'close'>,
|
|
208
|
-
now: () => number = Date.now,
|
|
209
|
-
): Promise<void> {
|
|
210
|
-
return application.close({ deadline: now() + APPLICATION_CLOSE_TIMEOUT_MS })
|
|
211
|
-
}
|
|
212
|
-
|
|
213
|
-
async function frontendAsset<S extends schema.DomainSchema>(
|
|
214
|
-
definition: DomainDefinition<S>,
|
|
215
|
-
environment: CloudflareAdapterBindings,
|
|
216
|
-
url: URL,
|
|
217
|
-
request: Request,
|
|
218
|
-
): Promise<Response | undefined> {
|
|
219
|
-
const frontend = definition.frontend
|
|
220
|
-
if (frontend === undefined || frontend.source.kind === 'external') return undefined
|
|
221
|
-
const routes = frontend.routes as Readonly<Record<string, FrontendRoute>>
|
|
222
|
-
const route = Object.values(routes).find((candidate) => candidate.path === url.pathname)
|
|
223
|
-
const staticAsset = url.pathname.startsWith('/assets/')
|
|
224
|
-
if (route === undefined && !staticAsset) return undefined
|
|
225
|
-
if (request.method !== 'GET' && request.method !== 'HEAD') return undefined
|
|
226
|
-
const binding = environment.ASSETS
|
|
227
|
-
if (binding === undefined) return undefined
|
|
228
|
-
const dev = environment.FRONTEND_DEV_URL?.replace(/\/+$/u, '')
|
|
229
|
-
if (dev !== undefined && dev.length > 0) {
|
|
230
|
-
return fetch(new Request(`${dev}${url.pathname}${url.search}`, request))
|
|
231
|
-
}
|
|
232
|
-
const path =
|
|
233
|
-
route === undefined ? `${url.pathname}${url.search}` : `/${route.document}${url.search}`
|
|
234
|
-
return binding.fetch(new Request(new URL(path, url.origin), request))
|
|
235
|
-
}
|
|
236
|
-
|
|
237
|
-
function requestOrigin(url: URL, request: Request): string {
|
|
238
|
-
if (url.protocol !== 'http:') return url.origin
|
|
239
|
-
const forwarded = request.headers.get('x-forwarded-proto')?.split(',')[0]?.trim().toLowerCase()
|
|
240
|
-
return forwarded === 'https' ? `https://${url.host}` : url.origin
|
|
241
|
-
}
|
|
242
|
-
|
|
243
|
-
function canonicalServingUrl(input: string): string {
|
|
244
|
-
let url: URL
|
|
245
|
-
try {
|
|
246
|
-
url = new URL(input)
|
|
247
|
-
} catch (cause) {
|
|
248
|
-
throw new TypeError('Cloudflare Worker serving URL is invalid.', { cause })
|
|
249
|
-
}
|
|
250
|
-
if (
|
|
251
|
-
(url.protocol !== 'https:' && url.protocol !== 'http:') ||
|
|
252
|
-
url.username !== '' ||
|
|
253
|
-
url.password !== '' ||
|
|
254
|
-
url.pathname !== '/' ||
|
|
255
|
-
url.search !== '' ||
|
|
256
|
-
url.hash !== ''
|
|
257
|
-
) {
|
|
258
|
-
throw new TypeError('Cloudflare Worker serving URL must be one HTTP(S) origin.')
|
|
259
|
-
}
|
|
260
|
-
return url.origin
|
|
261
|
-
}
|
|
262
|
-
|
|
263
|
-
function deploymentVersion(environment: CloudflareAdapterBindings): string {
|
|
264
|
-
const input = environment.ASTRALE_VERSION_METADATA
|
|
265
|
-
if (
|
|
266
|
-
input !== null &&
|
|
267
|
-
typeof input === 'object' &&
|
|
268
|
-
typeof input.id === 'string' &&
|
|
269
|
-
input.id.length > 0
|
|
270
|
-
) {
|
|
271
|
-
return input.id
|
|
272
|
-
}
|
|
273
|
-
const fallback = environment.ASTRALE_DEPLOYMENT_VERSION
|
|
274
|
-
if (typeof fallback === 'string' && fallback.length > 0) return fallback
|
|
275
|
-
throw new TypeError('Cloudflare Worker deployment version is unavailable.')
|
|
276
|
-
}
|