@pulse-compute/assets 0.0.0 → 1.0.0-beta.2
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 +31 -1
- package/as/README.md +12 -0
- package/as/index.as.ts +54 -0
- package/conformance/native.json +7 -0
- package/dist/asset-bucket.d.ts +85 -0
- package/dist/asset-bucket.d.ts.map +1 -0
- package/dist/asset-bucket.js +226 -0
- package/dist/asset-bucket.js.map +1 -0
- package/dist/asset-context.d.ts +34 -0
- package/dist/asset-context.d.ts.map +1 -0
- package/dist/asset-context.js +29 -0
- package/dist/asset-context.js.map +1 -0
- package/dist/asset-manager.d.ts +54 -0
- package/dist/asset-manager.d.ts.map +1 -0
- package/dist/asset-manager.js +257 -0
- package/dist/asset-manager.js.map +1 -0
- package/dist/errors.d.ts +14 -0
- package/dist/errors.d.ts.map +1 -0
- package/dist/errors.js +25 -0
- package/dist/errors.js.map +1 -0
- package/dist/index.d.ts +7 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +7 -0
- package/dist/index.js.map +1 -0
- package/dist/internal/package-runtime.d.ts +9 -0
- package/dist/internal/package-runtime.d.ts.map +1 -0
- package/dist/internal/package-runtime.js +14 -0
- package/dist/internal/package-runtime.js.map +1 -0
- package/dist/portable.d.ts +33 -0
- package/dist/portable.d.ts.map +1 -0
- package/dist/portable.js +98 -0
- package/dist/portable.js.map +1 -0
- package/dist/pulsewasm-compiler-types.d.ts +26 -0
- package/dist/pulsewasm-compiler-types.d.ts.map +1 -0
- package/dist/pulsewasm-compiler-types.js +9 -0
- package/dist/pulsewasm-compiler-types.js.map +1 -0
- package/dist/pulsewasm.d.ts +35 -0
- package/dist/pulsewasm.d.ts.map +1 -0
- package/dist/pulsewasm.js +34 -0
- package/dist/pulsewasm.js.map +1 -0
- package/dist/response-ownership.d.ts +3 -0
- package/dist/response-ownership.d.ts.map +1 -0
- package/dist/response-ownership.js +13 -0
- package/dist/response-ownership.js.map +1 -0
- package/dist/sigv4.d.ts +19 -0
- package/dist/sigv4.d.ts.map +1 -0
- package/dist/sigv4.js +123 -0
- package/dist/sigv4.js.map +1 -0
- package/package.json +59 -5
- package/pulse.package.json +69 -0
- package/pulsewasm.compiler.cjs +1660 -0
- package/pulsewasm.manifest.cjs +60 -0
package/README.md
CHANGED
|
@@ -1,3 +1,33 @@
|
|
|
1
1
|
# @pulse-compute/assets
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
<!-- pulse-package-status:start -->
|
|
4
|
+
> **Support tier:** Supported provider/extension surface<br>
|
|
5
|
+
> **Audience:** Applications using JavaScript asset middleware or the package-owned lowerable asset lookup capability.<br>
|
|
6
|
+
> **Install directly:** Yes, only when the application uses the assets capability.<br>
|
|
7
|
+
> **Supported entry points:** `@pulse-compute/assets`<br>
|
|
8
|
+
> **Stability:** The package root is the supported JavaScript API and canonical Native authoring surface; /pulsewasm remains a compatibility subpath, while manifest/compiler subpaths are toolchain integration.<br>
|
|
9
|
+
> **npm:** [`@pulse-compute/assets`](https://www.npmjs.com/package/@pulse-compute/assets)<br>
|
|
10
|
+
> **Canonical documentation:** [Package guide](https://pulsecompute.io/v1.0.0-beta.2/packages/assets/)
|
|
11
|
+
>
|
|
12
|
+
> This release-status block is generated from the synchronized `Pulse 1.0.0-beta.2` package policy.
|
|
13
|
+
<!-- pulse-package-status:end -->
|
|
14
|
+
|
|
15
|
+
The normal package root is the supported JavaScript API and canonical Native authoring surface:
|
|
16
|
+
|
|
17
|
+
```ts
|
|
18
|
+
import { assets } from '@pulse-compute/assets'
|
|
19
|
+
|
|
20
|
+
const found = await assets.lookup(ctx, 'public', '/app.js', { method: 'GET' })
|
|
21
|
+
return assets.respond(found)
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
`assets.lookup()` is a request-bound package effect owned by the internal `pulse.assets` contract and may be directly awaited or included in `ctx.parallel({ ... })`. JavaScript executes the actual package implementation; supported Native calls are recognized by the trusted package compiler and lowered to `assets.lookup`.
|
|
25
|
+
|
|
26
|
+
The same root exports `createAssets`, `AssetManager`, `AssetBucket`, and `signSigV4` for direct JavaScript local, hosted, and S3-compatible asset middleware. Hosted and bucket modes preserve upstream Web response streams. Local mode follows the restored reference behavior; a broader resource-bound policy belongs at the shared core request/response boundary.
|
|
27
|
+
|
|
28
|
+
`@pulse-compute/assets/pulsewasm` remains a compatibility-only lowerable
|
|
29
|
+
facade. Direct JavaScript execution of that subpath throws
|
|
30
|
+
`PulseWasmAssetsLoweringError`; applications should use the normal package
|
|
31
|
+
root. Manifest and compiler exports are toolchain integration. Migration
|
|
32
|
+
guidance is published at
|
|
33
|
+
<https://pulsecompute.io/v1.0.0-beta.2/guides/compatibility-imports/>.
|
package/as/README.md
ADDED
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
# PulseWasm assets sidecar
|
|
2
|
+
|
|
3
|
+
This directory contains the package-owned AssemblyScript sidecar declared by `../pulsewasm.manifest.cjs`.
|
|
4
|
+
|
|
5
|
+
The stable exports are:
|
|
6
|
+
|
|
7
|
+
- `pulse_assets_lookup`
|
|
8
|
+
- `pulse_assets_respond`
|
|
9
|
+
|
|
10
|
+
They delegate to the corresponding `pulse_assets_host` imports and form the compiled-Wasm ABI used by synchronized provider integration tests. Asset payload validation and canonical effect construction remain in the package compiler builder; provider execution remains in provider packages.
|
|
11
|
+
|
|
12
|
+
This sidecar is an implementation surface, not an application-author entry point.
|
package/as/index.as.ts
ADDED
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* PulseWasm assets AssemblyScript sidecar.
|
|
3
|
+
*
|
|
4
|
+
* This package-owned sidecar is intentionally tiny. User code lowers
|
|
5
|
+
* assets.lookup/respond into these stable exports; the exports delegate to
|
|
6
|
+
* host-owned provider imports. Keeping the AS surface explicit lets package-out
|
|
7
|
+
* tests validate the link ABI without materializing JS asset objects in Wasm.
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
export const PULSE_ASSETS_METHOD_GET: i32 = 1;
|
|
11
|
+
export const PULSE_ASSETS_METHOD_HEAD: i32 = 2;
|
|
12
|
+
export const PULSE_ASSETS_EFFECT_TERMINAL_RESPONSE: i32 = 1;
|
|
13
|
+
|
|
14
|
+
@external("pulse_assets_host", "lookup")
|
|
15
|
+
declare function __pulse_assets_host_lookup(
|
|
16
|
+
storePtr: usize,
|
|
17
|
+
storeLen: i32,
|
|
18
|
+
keyPtr: usize,
|
|
19
|
+
keyLen: i32,
|
|
20
|
+
method: i32,
|
|
21
|
+
optionsRef: i32
|
|
22
|
+
): i32;
|
|
23
|
+
|
|
24
|
+
@external("pulse_assets_host", "respond")
|
|
25
|
+
declare function __pulse_assets_host_respond(assetHandle: i32, optionsRef: i32): i32;
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* Lowering target for assets.lookup(store, key, options).
|
|
29
|
+
*
|
|
30
|
+
* The generated caller passes string pointers/lengths and a static method code.
|
|
31
|
+
* The host/provider owns the lookup result handle. Returning a handle keeps the
|
|
32
|
+
* AS sidecar narrow and avoids materializing arbitrary JS objects in Wasm.
|
|
33
|
+
*/
|
|
34
|
+
export function pulse_assets_lookup(
|
|
35
|
+
storePtr: usize,
|
|
36
|
+
storeLen: i32,
|
|
37
|
+
keyPtr: usize,
|
|
38
|
+
keyLen: i32,
|
|
39
|
+
method: i32,
|
|
40
|
+
optionsRef: i32
|
|
41
|
+
): i32 {
|
|
42
|
+
return __pulse_assets_host_lookup(storePtr, storeLen, keyPtr, keyLen, method, optionsRef);
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
/**
|
|
46
|
+
* Lowering target for assets.respond(assetHandle, options).
|
|
47
|
+
*
|
|
48
|
+
* The first compiled path treats this as a terminal asset response effect, not a
|
|
49
|
+
* continuation boundary. That keeps the assets lifecycle independent from
|
|
50
|
+
* ctx.resolve resume semantics until a later pass deliberately adds it.
|
|
51
|
+
*/
|
|
52
|
+
export function pulse_assets_respond(assetHandle: i32, optionsRef: i32): i32 {
|
|
53
|
+
return __pulse_assets_host_respond(assetHandle, optionsRef);
|
|
54
|
+
}
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
import type { PulseContext, RouterNext } from '@pulse-compute/runtime';
|
|
2
|
+
import { type SecretValue, type SigV4Credentials } from './sigv4.js';
|
|
3
|
+
import { type AssetBucketContext, type AssetBucketRouteContext, type LegacyAssetBucketRouteContext, type RouteNext } from './asset-context.js';
|
|
4
|
+
export type { AssetBucketContext, AssetBucketRouteContext, LegacyAssetBucketRouteContext, RouteNext, } from './asset-context.js';
|
|
5
|
+
export type AssetBucketMethod = 'GET' | 'HEAD';
|
|
6
|
+
export type AssetBucketResponseContext = {
|
|
7
|
+
request: Request;
|
|
8
|
+
key: string;
|
|
9
|
+
upstream: Response;
|
|
10
|
+
};
|
|
11
|
+
export type AssetBucketSignerInput = {
|
|
12
|
+
method: string;
|
|
13
|
+
url: URL;
|
|
14
|
+
headers: Headers;
|
|
15
|
+
credentials: SigV4Credentials;
|
|
16
|
+
region: string;
|
|
17
|
+
service: string;
|
|
18
|
+
};
|
|
19
|
+
export type AssetBucketSigner = (input: AssetBucketSignerInput) => Promise<Request>;
|
|
20
|
+
export type AssetBucketOptions = {
|
|
21
|
+
endpoint: string;
|
|
22
|
+
bucket: string;
|
|
23
|
+
credentials: {
|
|
24
|
+
key: SecretValue;
|
|
25
|
+
secret: SecretValue;
|
|
26
|
+
token?: SecretValue | undefined;
|
|
27
|
+
};
|
|
28
|
+
region?: string | undefined;
|
|
29
|
+
service?: string | undefined;
|
|
30
|
+
prefix?: string | undefined;
|
|
31
|
+
basePath?: string | undefined;
|
|
32
|
+
ttl?: number | false | undefined;
|
|
33
|
+
immutable?: boolean | undefined;
|
|
34
|
+
pathStyle?: boolean | undefined;
|
|
35
|
+
methods?: AssetBucketMethod[] | undefined;
|
|
36
|
+
passThroughOn404?: boolean | undefined;
|
|
37
|
+
passThroughOnError?: boolean | undefined;
|
|
38
|
+
signer?: "sigv4" | AssetBucketSigner | undefined;
|
|
39
|
+
fetch?: typeof fetch | undefined;
|
|
40
|
+
mapKey?: ((ctx: AssetBucketContext) => string | Promise<string>) | undefined;
|
|
41
|
+
setHeaders?: ((ctx: AssetBucketResponseContext) => HeadersInit | void | Promise<HeadersInit | void>) | undefined;
|
|
42
|
+
};
|
|
43
|
+
export type AssetBucketMiddleware = ((ctx: PulseContext, next: RouterNext) => Promise<Response>) & ((ctx: LegacyAssetBucketRouteContext, next?: RouteNext) => Promise<Response | void>);
|
|
44
|
+
export type AssetBucketInstance = AssetBucketMiddleware & {
|
|
45
|
+
readonly core: AssetBucketCore;
|
|
46
|
+
handle: AssetBucketMiddleware;
|
|
47
|
+
resolveKey(ctx: AssetBucketRouteContext): Promise<string>;
|
|
48
|
+
};
|
|
49
|
+
export interface AssetBucketConstructor {
|
|
50
|
+
new (options: AssetBucketOptions): AssetBucketInstance;
|
|
51
|
+
(options: AssetBucketOptions): AssetBucketInstance;
|
|
52
|
+
}
|
|
53
|
+
type ResolvedOptions = {
|
|
54
|
+
endpoint: URL;
|
|
55
|
+
bucket: string;
|
|
56
|
+
credentials: AssetBucketOptions["credentials"];
|
|
57
|
+
region: string;
|
|
58
|
+
service: string;
|
|
59
|
+
prefix: string;
|
|
60
|
+
basePath?: string | undefined;
|
|
61
|
+
ttl: number | false;
|
|
62
|
+
immutable: boolean;
|
|
63
|
+
pathStyle: boolean;
|
|
64
|
+
methods: ReadonlySet<AssetBucketMethod>;
|
|
65
|
+
passThroughOn404: boolean;
|
|
66
|
+
passThroughOnError: boolean;
|
|
67
|
+
signer: "sigv4" | AssetBucketSigner;
|
|
68
|
+
fetch: typeof fetch;
|
|
69
|
+
mapKey?: AssetBucketOptions["mapKey"] | undefined;
|
|
70
|
+
setHeaders?: AssetBucketOptions["setHeaders"] | undefined;
|
|
71
|
+
};
|
|
72
|
+
export declare class AssetBucketCore {
|
|
73
|
+
readonly options: ResolvedOptions;
|
|
74
|
+
constructor(options: AssetBucketOptions);
|
|
75
|
+
handle(ctx: AssetBucketRouteContext, next?: RouteNext): Promise<Response | void>;
|
|
76
|
+
resolveKey(ctx: AssetBucketRouteContext): Promise<string>;
|
|
77
|
+
private fetchObject;
|
|
78
|
+
private objectUrl;
|
|
79
|
+
private forwardHeaders;
|
|
80
|
+
private sign;
|
|
81
|
+
private toResponse;
|
|
82
|
+
private pass;
|
|
83
|
+
}
|
|
84
|
+
export declare const AssetBucket: AssetBucketConstructor;
|
|
85
|
+
//# sourceMappingURL=asset-bucket.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"asset-bucket.d.ts","sourceRoot":"","sources":["../src/asset-bucket.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,UAAU,EAAE,MAAM,wBAAwB,CAAC;AAEvE,OAAO,EAA0B,KAAK,WAAW,EAAE,KAAK,gBAAgB,EAAE,MAAM,YAAY,CAAC;AAE7F,OAAO,EAEL,KAAK,kBAAkB,EACvB,KAAK,uBAAuB,EAC5B,KAAK,6BAA6B,EAClC,KAAK,SAAS,EACf,MAAM,oBAAoB,CAAC;AAE5B,YAAY,EACV,kBAAkB,EAClB,uBAAuB,EACvB,6BAA6B,EAC7B,SAAS,GACV,MAAM,oBAAoB,CAAC;AAE5B,MAAM,MAAM,iBAAiB,GAAG,KAAK,GAAG,MAAM,CAAC;AAE/C,MAAM,MAAM,0BAA0B,GAAG;IACvC,OAAO,EAAE,OAAO,CAAC;IACjB,GAAG,EAAE,MAAM,CAAC;IACZ,QAAQ,EAAE,QAAQ,CAAC;CACpB,CAAC;AAEF,MAAM,MAAM,sBAAsB,GAAG;IACnC,MAAM,EAAE,MAAM,CAAC;IACf,GAAG,EAAE,GAAG,CAAC;IACT,OAAO,EAAE,OAAO,CAAC;IACjB,WAAW,EAAE,gBAAgB,CAAC;IAC9B,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,MAAM,CAAC;CACjB,CAAC;AAEF,MAAM,MAAM,iBAAiB,GAAG,CAAC,KAAK,EAAE,sBAAsB,KAAK,OAAO,CAAC,OAAO,CAAC,CAAC;AAEpF,MAAM,MAAM,kBAAkB,GAAG;IAC/B,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,MAAM,CAAC;IACf,WAAW,EAAE;QACX,GAAG,EAAE,WAAW,CAAC;QACjB,MAAM,EAAE,WAAW,CAAC;QACpB,KAAK,CAAC,EAAE,WAAW,GAAG,SAAS,CAAC;KACjC,CAAC;IAEF,MAAM,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAC5B,OAAO,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAC7B,MAAM,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAC5B,QAAQ,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAC9B,GAAG,CAAC,EAAE,MAAM,GAAG,KAAK,GAAG,SAAS,CAAC;IACjC,SAAS,CAAC,EAAE,OAAO,GAAG,SAAS,CAAC;IAChC,SAAS,CAAC,EAAE,OAAO,GAAG,SAAS,CAAC;IAEhC,OAAO,CAAC,EAAE,iBAAiB,EAAE,GAAG,SAAS,CAAC;IAC1C,gBAAgB,CAAC,EAAE,OAAO,GAAG,SAAS,CAAC;IACvC,kBAAkB,CAAC,EAAE,OAAO,GAAG,SAAS,CAAC;IAEzC,MAAM,CAAC,EAAE,OAAO,GAAG,iBAAiB,GAAG,SAAS,CAAC;IACjD,KAAK,CAAC,EAAE,OAAO,KAAK,GAAG,SAAS,CAAC;IAEjC,MAAM,CAAC,EAAE,CAAC,CAAC,GAAG,EAAE,kBAAkB,KAAK,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC,GAAG,SAAS,CAAC;IAC7E,UAAU,CAAC,EACP,CAAC,CAAC,GAAG,EAAE,0BAA0B,KAAK,WAAW,GAAG,IAAI,GAAG,OAAO,CAAC,WAAW,GAAG,IAAI,CAAC,CAAC,GACvF,SAAS,CAAC;CACf,CAAC;AAEF,MAAM,MAAM,qBAAqB,GAC7B,CAAC,CAAC,GAAG,EAAE,YAAY,EAAE,IAAI,EAAE,UAAU,KAAK,OAAO,CAAC,QAAQ,CAAC,CAAC,GAC5D,CAAC,CAAC,GAAG,EAAE,6BAA6B,EAAE,IAAI,CAAC,EAAE,SAAS,KAAK,OAAO,CAAC,QAAQ,GAAG,IAAI,CAAC,CAAC,CAAC;AAEzF,MAAM,MAAM,mBAAmB,GAAG,qBAAqB,GAAG;IACxD,QAAQ,CAAC,IAAI,EAAE,eAAe,CAAC;IAC/B,MAAM,EAAE,qBAAqB,CAAC;IAC9B,UAAU,CAAC,GAAG,EAAE,uBAAuB,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC;CAC3D,CAAC;AAEF,MAAM,WAAW,sBAAsB;IACrC,KAAK,OAAO,EAAE,kBAAkB,GAAG,mBAAmB,CAAC;IACvD,CAAC,OAAO,EAAE,kBAAkB,GAAG,mBAAmB,CAAC;CACpD;AAuED,KAAK,eAAe,GAAG;IACrB,QAAQ,EAAE,GAAG,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf,WAAW,EAAE,kBAAkB,CAAC,aAAa,CAAC,CAAC;IAC/C,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAC9B,GAAG,EAAE,MAAM,GAAG,KAAK,CAAC;IACpB,SAAS,EAAE,OAAO,CAAC;IACnB,SAAS,EAAE,OAAO,CAAC;IACnB,OAAO,EAAE,WAAW,CAAC,iBAAiB,CAAC,CAAC;IACxC,gBAAgB,EAAE,OAAO,CAAC;IAC1B,kBAAkB,EAAE,OAAO,CAAC;IAC5B,MAAM,EAAE,OAAO,GAAG,iBAAiB,CAAC;IACpC,KAAK,EAAE,OAAO,KAAK,CAAC;IACpB,MAAM,CAAC,EAAE,kBAAkB,CAAC,QAAQ,CAAC,GAAG,SAAS,CAAC;IAClD,UAAU,CAAC,EAAE,kBAAkB,CAAC,YAAY,CAAC,GAAG,SAAS,CAAC;CAC3D,CAAC;AAkCF,qBAAa,eAAe;IAC1B,QAAQ,CAAC,OAAO,EAAE,eAAe,CAAC;gBAEtB,OAAO,EAAE,kBAAkB;IAIjC,MAAM,CAAC,GAAG,EAAE,uBAAuB,EAAE,IAAI,CAAC,EAAE,SAAS,GAAG,OAAO,CAAC,QAAQ,GAAG,IAAI,CAAC;IA2BhF,UAAU,CAAC,GAAG,EAAE,uBAAuB,GAAG,OAAO,CAAC,MAAM,CAAC;YAcjD,WAAW;IAOzB,OAAO,CAAC,SAAS;IAcjB,OAAO,CAAC,cAAc;YASR,IAAI;YAsBJ,UAAU;YAiBV,IAAI;CAGnB;AAiBD,eAAO,MAAM,WAAW,EAAE,sBAKY,CAAC"}
|
|
@@ -0,0 +1,226 @@
|
|
|
1
|
+
import { AssetBucketConfigError, AssetBucketFetchError } from './errors.js';
|
|
2
|
+
import { encodeS3Key, signSigV4 } from './sigv4.js';
|
|
3
|
+
import { cancelResponseBody } from './response-ownership.js';
|
|
4
|
+
import { normalizeAssetContext, } from './asset-context.js';
|
|
5
|
+
const DEFAULT_TTL = 3600;
|
|
6
|
+
const IMMUTABLE_TTL = 31536000;
|
|
7
|
+
const FORWARDED_HEADERS = [
|
|
8
|
+
"range",
|
|
9
|
+
"if-match",
|
|
10
|
+
"if-none-match",
|
|
11
|
+
"if-modified-since",
|
|
12
|
+
"if-unmodified-since",
|
|
13
|
+
];
|
|
14
|
+
function trimSlashes(value) {
|
|
15
|
+
return value.replace(/^\/+|\/+$/g, "");
|
|
16
|
+
}
|
|
17
|
+
function normalizePrefix(prefix) {
|
|
18
|
+
if (!prefix)
|
|
19
|
+
return "";
|
|
20
|
+
const clean = trimSlashes(prefix);
|
|
21
|
+
return clean ? `${clean}/` : "";
|
|
22
|
+
}
|
|
23
|
+
function normalizeBasePath(basePath) {
|
|
24
|
+
if (!basePath)
|
|
25
|
+
return undefined;
|
|
26
|
+
const clean = `/${trimSlashes(basePath)}`;
|
|
27
|
+
return clean === "/" ? undefined : clean;
|
|
28
|
+
}
|
|
29
|
+
function joinPath(...parts) {
|
|
30
|
+
return parts
|
|
31
|
+
.map((part) => trimSlashes(part))
|
|
32
|
+
.filter(Boolean)
|
|
33
|
+
.join("/");
|
|
34
|
+
}
|
|
35
|
+
function normalizeEndpoint(endpoint) {
|
|
36
|
+
try {
|
|
37
|
+
return new URL(endpoint.endsWith("/") ? endpoint : `${endpoint}/`);
|
|
38
|
+
}
|
|
39
|
+
catch {
|
|
40
|
+
throw new AssetBucketConfigError(`Invalid endpoint URL: ${endpoint}`);
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
function normalizedContext(ctx) {
|
|
44
|
+
return normalizeAssetContext(ctx);
|
|
45
|
+
}
|
|
46
|
+
function stripBasePath(pathname, basePath) {
|
|
47
|
+
if (!basePath)
|
|
48
|
+
return pathname;
|
|
49
|
+
if (pathname === basePath)
|
|
50
|
+
return "/";
|
|
51
|
+
if (pathname.startsWith(`${basePath}/`)) {
|
|
52
|
+
return pathname.slice(basePath.length);
|
|
53
|
+
}
|
|
54
|
+
return pathname;
|
|
55
|
+
}
|
|
56
|
+
function applyHeaders(target, headers) {
|
|
57
|
+
if (!headers)
|
|
58
|
+
return;
|
|
59
|
+
new Headers(headers).forEach((value, key) => target.set(key, value));
|
|
60
|
+
}
|
|
61
|
+
function makeCacheControl(options) {
|
|
62
|
+
if (options.immutable) {
|
|
63
|
+
const ttl = options.ttl === false ? IMMUTABLE_TTL : options.ttl;
|
|
64
|
+
return `public, max-age=${ttl}, immutable`;
|
|
65
|
+
}
|
|
66
|
+
if (options.ttl === false)
|
|
67
|
+
return undefined;
|
|
68
|
+
return `public, max-age=${options.ttl}`;
|
|
69
|
+
}
|
|
70
|
+
function resolveOptions(options) {
|
|
71
|
+
if (!options.endpoint)
|
|
72
|
+
throw new AssetBucketConfigError("AssetBucket requires endpoint");
|
|
73
|
+
if (!options.bucket)
|
|
74
|
+
throw new AssetBucketConfigError("AssetBucket requires bucket");
|
|
75
|
+
if (!options.credentials?.key)
|
|
76
|
+
throw new AssetBucketConfigError("AssetBucket requires credentials.key");
|
|
77
|
+
if (!options.credentials?.secret)
|
|
78
|
+
throw new AssetBucketConfigError("AssetBucket requires credentials.secret");
|
|
79
|
+
const fetchImpl = options.fetch ?? globalThis.fetch;
|
|
80
|
+
if (typeof fetchImpl !== "function") {
|
|
81
|
+
throw new AssetBucketConfigError("AssetBucket requires a fetch implementation");
|
|
82
|
+
}
|
|
83
|
+
return {
|
|
84
|
+
endpoint: normalizeEndpoint(options.endpoint),
|
|
85
|
+
bucket: options.bucket,
|
|
86
|
+
credentials: options.credentials,
|
|
87
|
+
region: options.region ?? "us-east-1",
|
|
88
|
+
service: options.service ?? "s3",
|
|
89
|
+
prefix: normalizePrefix(options.prefix),
|
|
90
|
+
basePath: normalizeBasePath(options.basePath),
|
|
91
|
+
ttl: options.ttl ?? DEFAULT_TTL,
|
|
92
|
+
immutable: options.immutable ?? false,
|
|
93
|
+
pathStyle: options.pathStyle ?? true,
|
|
94
|
+
methods: new Set(options.methods ?? ["GET", "HEAD"]),
|
|
95
|
+
passThroughOn404: options.passThroughOn404 ?? true,
|
|
96
|
+
passThroughOnError: options.passThroughOnError ?? false,
|
|
97
|
+
signer: options.signer ?? "sigv4",
|
|
98
|
+
fetch: fetchImpl,
|
|
99
|
+
mapKey: options.mapKey,
|
|
100
|
+
setHeaders: options.setHeaders,
|
|
101
|
+
};
|
|
102
|
+
}
|
|
103
|
+
export class AssetBucketCore {
|
|
104
|
+
options;
|
|
105
|
+
constructor(options) {
|
|
106
|
+
this.options = resolveOptions(options);
|
|
107
|
+
}
|
|
108
|
+
async handle(ctx, next) {
|
|
109
|
+
const normalized = normalizedContext(ctx);
|
|
110
|
+
const method = normalized.request.method.toUpperCase();
|
|
111
|
+
if (!this.options.methods.has(method)) {
|
|
112
|
+
return this.pass(next);
|
|
113
|
+
}
|
|
114
|
+
try {
|
|
115
|
+
const key = await this.resolveKey(ctx);
|
|
116
|
+
if (!key)
|
|
117
|
+
return this.pass(next);
|
|
118
|
+
const upstream = await this.fetchObject(normalized.request, key, method);
|
|
119
|
+
if (upstream.status === 404 && this.options.passThroughOn404) {
|
|
120
|
+
await cancelResponseBody(upstream);
|
|
121
|
+
return this.pass(next);
|
|
122
|
+
}
|
|
123
|
+
return await this.toResponse(normalized.request, key, upstream);
|
|
124
|
+
}
|
|
125
|
+
catch (cause) {
|
|
126
|
+
if (this.options.passThroughOnError)
|
|
127
|
+
return this.pass(next);
|
|
128
|
+
if (cause instanceof AssetBucketConfigError)
|
|
129
|
+
throw cause;
|
|
130
|
+
throw new AssetBucketFetchError("AssetBucket failed to fetch asset", { cause });
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
async resolveKey(ctx) {
|
|
134
|
+
const normalized = normalizedContext(ctx);
|
|
135
|
+
if (this.options.mapKey) {
|
|
136
|
+
return normalizeObjectKey(await this.options.mapKey(normalized));
|
|
137
|
+
}
|
|
138
|
+
let relative = normalized.path.relative || new URL(normalized.request.url).pathname;
|
|
139
|
+
relative = stripBasePath(relative, this.options.basePath);
|
|
140
|
+
relative = relative.replace(/^\/+/, "");
|
|
141
|
+
const key = `${this.options.prefix}${relative}`;
|
|
142
|
+
return normalizeObjectKey(key);
|
|
143
|
+
}
|
|
144
|
+
async fetchObject(request, key, method) {
|
|
145
|
+
const url = this.objectUrl(key);
|
|
146
|
+
const headers = this.forwardHeaders(request.headers);
|
|
147
|
+
const signed = await this.sign({ method, url, headers });
|
|
148
|
+
return await this.options.fetch(signed);
|
|
149
|
+
}
|
|
150
|
+
objectUrl(key) {
|
|
151
|
+
const endpoint = new URL(this.options.endpoint.toString());
|
|
152
|
+
const encodedKey = encodeS3Key(key);
|
|
153
|
+
if (this.options.pathStyle) {
|
|
154
|
+
endpoint.pathname = joinPath(endpoint.pathname, this.options.bucket, encodedKey);
|
|
155
|
+
return endpoint;
|
|
156
|
+
}
|
|
157
|
+
endpoint.hostname = `${this.options.bucket}.${endpoint.hostname}`;
|
|
158
|
+
endpoint.pathname = joinPath(endpoint.pathname, encodedKey);
|
|
159
|
+
return endpoint;
|
|
160
|
+
}
|
|
161
|
+
forwardHeaders(source) {
|
|
162
|
+
const headers = new Headers();
|
|
163
|
+
for (const name of FORWARDED_HEADERS) {
|
|
164
|
+
const value = source.get(name);
|
|
165
|
+
if (value !== null)
|
|
166
|
+
headers.set(name, value);
|
|
167
|
+
}
|
|
168
|
+
return headers;
|
|
169
|
+
}
|
|
170
|
+
async sign(input) {
|
|
171
|
+
if (typeof this.options.signer === "function") {
|
|
172
|
+
return await this.options.signer({
|
|
173
|
+
method: input.method,
|
|
174
|
+
url: input.url,
|
|
175
|
+
headers: input.headers,
|
|
176
|
+
credentials: this.options.credentials,
|
|
177
|
+
region: this.options.region,
|
|
178
|
+
service: this.options.service,
|
|
179
|
+
});
|
|
180
|
+
}
|
|
181
|
+
return await signSigV4({
|
|
182
|
+
method: input.method,
|
|
183
|
+
url: input.url,
|
|
184
|
+
headers: input.headers,
|
|
185
|
+
credentials: this.options.credentials,
|
|
186
|
+
region: this.options.region,
|
|
187
|
+
service: this.options.service,
|
|
188
|
+
});
|
|
189
|
+
}
|
|
190
|
+
async toResponse(request, key, upstream) {
|
|
191
|
+
const headers = new Headers(upstream.headers);
|
|
192
|
+
const cacheControl = makeCacheControl({ ttl: this.options.ttl, immutable: this.options.immutable });
|
|
193
|
+
if (cacheControl)
|
|
194
|
+
headers.set("cache-control", cacheControl);
|
|
195
|
+
const extraHeaders = await this.options.setHeaders?.({ request, key, upstream });
|
|
196
|
+
applyHeaders(headers, extraHeaders);
|
|
197
|
+
const isHead = request.method.toUpperCase() === "HEAD";
|
|
198
|
+
if (isHead)
|
|
199
|
+
await cancelResponseBody(upstream);
|
|
200
|
+
return new Response(isHead ? null : upstream.body, {
|
|
201
|
+
status: upstream.status,
|
|
202
|
+
statusText: upstream.statusText,
|
|
203
|
+
headers,
|
|
204
|
+
});
|
|
205
|
+
}
|
|
206
|
+
async pass(next) {
|
|
207
|
+
return next ? await next() : undefined;
|
|
208
|
+
}
|
|
209
|
+
}
|
|
210
|
+
function normalizeObjectKey(key) {
|
|
211
|
+
return key.replace(/^\/+/, "").replace(/\/+/g, "/");
|
|
212
|
+
}
|
|
213
|
+
function createAssetBucket(options) {
|
|
214
|
+
const core = new AssetBucketCore(options);
|
|
215
|
+
const middleware = core.handle.bind(core);
|
|
216
|
+
Object.defineProperties(middleware, {
|
|
217
|
+
core: { value: core, enumerable: false },
|
|
218
|
+
handle: { value: middleware, enumerable: false },
|
|
219
|
+
resolveKey: { value: core.resolveKey.bind(core), enumerable: false },
|
|
220
|
+
});
|
|
221
|
+
return middleware;
|
|
222
|
+
}
|
|
223
|
+
export const AssetBucket = function AssetBucket(options) {
|
|
224
|
+
return createAssetBucket(options);
|
|
225
|
+
};
|
|
226
|
+
//# sourceMappingURL=asset-bucket.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"asset-bucket.js","sourceRoot":"","sources":["../src/asset-bucket.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import type { PulseContext } from '@pulse-compute/runtime';
|
|
2
|
+
export type RouteNext = () => Promise<Response | void> | Response | void;
|
|
3
|
+
export type LegacyAssetBucketRouteContext = {
|
|
4
|
+
request: Request;
|
|
5
|
+
params?: Readonly<Record<string, string>> | undefined;
|
|
6
|
+
state?: Record<string, unknown> | undefined;
|
|
7
|
+
path?: {
|
|
8
|
+
absolute?: string | undefined;
|
|
9
|
+
relative?: string | undefined;
|
|
10
|
+
} | undefined;
|
|
11
|
+
raw?: {
|
|
12
|
+
request?: unknown;
|
|
13
|
+
response?: unknown;
|
|
14
|
+
env?: unknown;
|
|
15
|
+
[key: string]: unknown;
|
|
16
|
+
} | undefined;
|
|
17
|
+
};
|
|
18
|
+
export type AssetBucketRouteContext = PulseContext | LegacyAssetBucketRouteContext;
|
|
19
|
+
export type AssetBucketContext = {
|
|
20
|
+
request: Request;
|
|
21
|
+
params: Readonly<Record<string, string>>;
|
|
22
|
+
path: {
|
|
23
|
+
absolute: string;
|
|
24
|
+
relative: string;
|
|
25
|
+
};
|
|
26
|
+
raw: {
|
|
27
|
+
request?: unknown;
|
|
28
|
+
response?: unknown;
|
|
29
|
+
env?: unknown;
|
|
30
|
+
[key: string]: unknown;
|
|
31
|
+
};
|
|
32
|
+
};
|
|
33
|
+
export declare function normalizeAssetContext(ctx: AssetBucketRouteContext): AssetBucketContext;
|
|
34
|
+
//# sourceMappingURL=asset-context.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"asset-context.d.ts","sourceRoot":"","sources":["../src/asset-context.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,wBAAwB,CAAC;AAG3D,MAAM,MAAM,SAAS,GAAG,MAAM,OAAO,CAAC,QAAQ,GAAG,IAAI,CAAC,GAAG,QAAQ,GAAG,IAAI,CAAC;AAEzE,MAAM,MAAM,6BAA6B,GAAG;IAC1C,OAAO,EAAE,OAAO,CAAC;IACjB,MAAM,CAAC,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,GAAG,SAAS,CAAC;IACtD,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,SAAS,CAAC;IAC5C,IAAI,CAAC,EAAE;QACL,QAAQ,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;QAC9B,QAAQ,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;KAC/B,GAAG,SAAS,CAAC;IACd,GAAG,CAAC,EAAE;QACJ,OAAO,CAAC,EAAE,OAAO,CAAC;QAClB,QAAQ,CAAC,EAAE,OAAO,CAAC;QACnB,GAAG,CAAC,EAAE,OAAO,CAAC;QACd,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;KACxB,GAAG,SAAS,CAAC;CACf,CAAC;AAEF,MAAM,MAAM,uBAAuB,GAAG,YAAY,GAAG,6BAA6B,CAAC;AAEnF,MAAM,MAAM,kBAAkB,GAAG;IAC/B,OAAO,EAAE,OAAO,CAAC;IACjB,MAAM,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC;IACzC,IAAI,EAAE;QACJ,QAAQ,EAAE,MAAM,CAAC;QACjB,QAAQ,EAAE,MAAM,CAAC;KAClB,CAAC;IACF,GAAG,EAAE;QACH,OAAO,CAAC,EAAE,OAAO,CAAC;QAClB,QAAQ,CAAC,EAAE,OAAO,CAAC;QACnB,GAAG,CAAC,EAAE,OAAO,CAAC;QACd,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;KACxB,CAAC;CACH,CAAC;AAMF,wBAAgB,qBAAqB,CAAC,GAAG,EAAE,uBAAuB,GAAG,kBAAkB,CAuBtF"}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { pulseAssetsRuntime } from './internal/package-runtime.js';
|
|
2
|
+
function isPulseContext(value) {
|
|
3
|
+
return Boolean(value && typeof value === 'object' && 'req' in value && 'state' in value);
|
|
4
|
+
}
|
|
5
|
+
export function normalizeAssetContext(ctx) {
|
|
6
|
+
if (isPulseContext(ctx)) {
|
|
7
|
+
const view = pulseAssetsRuntime.context(ctx);
|
|
8
|
+
return {
|
|
9
|
+
request: view.request,
|
|
10
|
+
params: view.params,
|
|
11
|
+
path: view.path,
|
|
12
|
+
raw: {},
|
|
13
|
+
};
|
|
14
|
+
}
|
|
15
|
+
if (!ctx || !(ctx.request instanceof Request)) {
|
|
16
|
+
throw new TypeError('Pulse Assets middleware requires a PulseContext or legacy request context.');
|
|
17
|
+
}
|
|
18
|
+
const url = new URL(ctx.request.url);
|
|
19
|
+
return {
|
|
20
|
+
request: ctx.request,
|
|
21
|
+
params: ctx.params ?? {},
|
|
22
|
+
path: {
|
|
23
|
+
absolute: ctx.path?.absolute ?? url.pathname,
|
|
24
|
+
relative: ctx.path?.relative ?? url.pathname,
|
|
25
|
+
},
|
|
26
|
+
raw: ctx.raw ?? {},
|
|
27
|
+
};
|
|
28
|
+
}
|
|
29
|
+
//# sourceMappingURL=asset-context.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"asset-context.js","sourceRoot":"","sources":["../src/asset-context.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,kBAAkB,EAAE,MAAM,+BAA+B,CAAC;AAqCnE,SAAS,cAAc,CAAC,KAA8B;IACpD,OAAO,OAAO,CAAC,KAAK,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,IAAI,KAAK,IAAI,OAAO,IAAI,KAAK,CAAC,CAAC;AAC3F,CAAC;AAED,MAAM,UAAU,qBAAqB,CAAC,GAA4B;IAChE,IAAI,cAAc,CAAC,GAAG,CAAC,EAAE,CAAC;QACxB,MAAM,IAAI,GAAG,kBAAkB,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;QAC7C,OAAO;YACL,OAAO,EAAE,IAAI,CAAC,OAAO;YACrB,MAAM,EAAE,IAAI,CAAC,MAAM;YACnB,IAAI,EAAE,IAAI,CAAC,IAAI;YACf,GAAG,EAAE,EAAE;SACR,CAAC;IACJ,CAAC;IACD,IAAI,CAAC,GAAG,IAAI,CAAC,CAAC,GAAG,CAAC,OAAO,YAAY,OAAO,CAAC,EAAE,CAAC;QAC9C,MAAM,IAAI,SAAS,CAAC,4EAA4E,CAAC,CAAC;IACpG,CAAC;IACD,MAAM,GAAG,GAAG,IAAI,GAAG,CAAC,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;IACrC,OAAO;QACL,OAAO,EAAE,GAAG,CAAC,OAAO;QACpB,MAAM,EAAE,GAAG,CAAC,MAAM,IAAI,EAAE;QACxB,IAAI,EAAE;YACJ,QAAQ,EAAE,GAAG,CAAC,IAAI,EAAE,QAAQ,IAAI,GAAG,CAAC,QAAQ;YAC5C,QAAQ,EAAE,GAAG,CAAC,IAAI,EAAE,QAAQ,IAAI,GAAG,CAAC,QAAQ;SAC7C;QACD,GAAG,EAAE,GAAG,CAAC,GAAG,IAAI,EAAE;KACnB,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import { type AssetBucketMethod, type AssetBucketOptions, type AssetBucketRouteContext, type RouteNext } from './asset-bucket.js';
|
|
2
|
+
import type { PulseContext, RouterNext } from '@pulse-compute/runtime';
|
|
3
|
+
import { type LegacyAssetBucketRouteContext } from './asset-context.js';
|
|
4
|
+
export type AssetCacheOptions = {
|
|
5
|
+
ttl?: number | false | undefined;
|
|
6
|
+
immutable?: boolean | undefined;
|
|
7
|
+
passThroughOn404?: boolean | undefined;
|
|
8
|
+
passThroughOnError?: boolean | undefined;
|
|
9
|
+
methods?: AssetBucketMethod[] | undefined;
|
|
10
|
+
};
|
|
11
|
+
export type LocalAssetsConfig = AssetCacheOptions & {
|
|
12
|
+
mode: 'local';
|
|
13
|
+
dir: string;
|
|
14
|
+
prefix?: string | undefined;
|
|
15
|
+
index?: string | false | undefined;
|
|
16
|
+
fetch?: typeof fetch | undefined;
|
|
17
|
+
contentTypes?: Record<string, string> | undefined;
|
|
18
|
+
};
|
|
19
|
+
export type HostedAssetsConfig = AssetCacheOptions & {
|
|
20
|
+
mode: 'hosted';
|
|
21
|
+
origin: string;
|
|
22
|
+
prefix?: string | undefined;
|
|
23
|
+
headers?: HeadersInit | undefined;
|
|
24
|
+
fetch?: typeof fetch | undefined;
|
|
25
|
+
};
|
|
26
|
+
export type BucketAssetsConfig = AssetCacheOptions & AssetBucketOptions & {
|
|
27
|
+
mode: 'bucket';
|
|
28
|
+
};
|
|
29
|
+
export type AssetsConfig = LocalAssetsConfig | HostedAssetsConfig | BucketAssetsConfig;
|
|
30
|
+
export type AssetManagerMiddleware = ((ctx: PulseContext, next: RouterNext) => Promise<Response>) & ((ctx: LegacyAssetBucketRouteContext, next?: RouteNext) => Promise<Response | void>);
|
|
31
|
+
export type AssetManagerInstance = AssetManagerMiddleware & {
|
|
32
|
+
readonly core: AssetManagerCore;
|
|
33
|
+
handle: AssetManagerMiddleware;
|
|
34
|
+
resolveKey(ctx: AssetBucketRouteContext): Promise<string>;
|
|
35
|
+
};
|
|
36
|
+
export interface AssetManagerConstructor {
|
|
37
|
+
new (config: AssetsConfig): AssetManagerInstance;
|
|
38
|
+
(config: AssetsConfig): AssetManagerInstance;
|
|
39
|
+
}
|
|
40
|
+
export declare class AssetManagerCore {
|
|
41
|
+
readonly config: AssetsConfig;
|
|
42
|
+
private readonly bucket?;
|
|
43
|
+
constructor(config: AssetsConfig);
|
|
44
|
+
handle(ctx: AssetBucketRouteContext, next?: RouteNext): Promise<Response | void>;
|
|
45
|
+
resolveKey(ctx: AssetBucketRouteContext): Promise<string>;
|
|
46
|
+
private allowed;
|
|
47
|
+
private handleLocal;
|
|
48
|
+
private handleHosted;
|
|
49
|
+
private handleMiss;
|
|
50
|
+
private pass;
|
|
51
|
+
}
|
|
52
|
+
export declare const AssetManager: AssetManagerConstructor;
|
|
53
|
+
export declare function createAssets(config: AssetsConfig): AssetManagerInstance;
|
|
54
|
+
//# sourceMappingURL=asset-manager.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"asset-manager.d.ts","sourceRoot":"","sources":["../src/asset-manager.ts"],"names":[],"mappings":"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"}
|