@bleedingdev/modern-js-app-tools 3.5.0-ultramodern.28 → 3.5.0-ultramodern.29
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/dist/cjs/index.js +50 -44
- package/dist/cjs/plugins/backendFederationBuild.js +347 -0
- package/dist/cjs/plugins/deploy/platforms/cloudflare-output-contract.js +91 -0
- package/dist/cjs/plugins/deploy/platforms/cloudflare-output-plan.js +93 -0
- package/dist/cjs/plugins/deploy/platforms/cloudflare-output-verifier.js +402 -0
- package/dist/cjs/plugins/deploy/platforms/cloudflare.js +152 -27
- package/dist/cjs/plugins/deploy/platforms/templates/cloudflare-entry.mjs +30 -19
- package/dist/esm/index.mjs +2 -0
- package/dist/esm/plugins/backendFederationBuild.mjs +296 -0
- package/dist/esm/plugins/deploy/platforms/cloudflare-output-contract.mjs +17 -0
- package/dist/esm/plugins/deploy/platforms/cloudflare-output-plan.mjs +45 -0
- package/dist/esm/plugins/deploy/platforms/cloudflare-output-verifier.mjs +347 -0
- package/dist/esm/plugins/deploy/platforms/cloudflare.mjs +152 -27
- package/dist/esm/plugins/deploy/platforms/templates/cloudflare-entry.mjs +30 -19
- package/dist/esm-node/index.mjs +2 -0
- package/dist/esm-node/plugins/backendFederationBuild.mjs +297 -0
- package/dist/esm-node/plugins/deploy/platforms/cloudflare-output-contract.mjs +18 -0
- package/dist/esm-node/plugins/deploy/platforms/cloudflare-output-plan.mjs +46 -0
- package/dist/esm-node/plugins/deploy/platforms/cloudflare-output-verifier.mjs +348 -0
- package/dist/esm-node/plugins/deploy/platforms/cloudflare.mjs +152 -27
- package/dist/esm-node/plugins/deploy/platforms/templates/cloudflare-entry.mjs +30 -19
- package/dist/types/plugins/backendFederationBuild.d.ts +11 -0
- package/dist/types/plugins/deploy/platforms/cloudflare-output-contract.d.ts +13 -0
- package/dist/types/plugins/deploy/platforms/cloudflare-output-plan.d.ts +33 -0
- package/dist/types/plugins/deploy/platforms/cloudflare-output-verifier.d.ts +32 -0
- package/dist/types/types/config/cloudflareDeploy.d.ts +11 -0
- package/dist/types/types/config/deploy.d.ts +9 -2
- package/package.json +17 -11
|
@@ -2,7 +2,7 @@ const ASSETS_BINDING = 'ASSETS';
|
|
|
2
2
|
const MODERN_WORKER_MANIFEST = p_workerManifest;
|
|
3
3
|
const WORKER_MODULE_LOADERS = p_workerModuleLoaders;
|
|
4
4
|
const workerModulePromises = new Map();
|
|
5
|
-
const
|
|
5
|
+
const effectBffDispatcherPromises = new Map();
|
|
6
6
|
let effectEdgeRuntimePromise;
|
|
7
7
|
const remoteJsonPromises = new Map();
|
|
8
8
|
const CORS_POLICY = MODERN_WORKER_MANIFEST.security?.cors || {};
|
|
@@ -152,17 +152,7 @@ async function createCorsPreflightResponse(request, env) {
|
|
|
152
152
|
status: 204
|
|
153
153
|
});
|
|
154
154
|
}
|
|
155
|
-
|
|
156
|
-
const assets = env?.[ASSETS_BINDING];
|
|
157
|
-
if (!assets || 'function' != typeof assets.fetch) return null;
|
|
158
|
-
const assetResponse = await assets.fetch(new Request(request.url, {
|
|
159
|
-
method: 'HEAD'
|
|
160
|
-
}));
|
|
161
|
-
if (!assetResponse || 404 === assetResponse.status) return null;
|
|
162
|
-
return new Response(null, {
|
|
163
|
-
headers: ASSET_CORS_HEADERS,
|
|
164
|
-
status: 204
|
|
165
|
-
});
|
|
155
|
+
return null;
|
|
166
156
|
}
|
|
167
157
|
async function fetchAsset(request, env) {
|
|
168
158
|
if ('GET' !== request.method && 'HEAD' !== request.method) return null;
|
|
@@ -798,17 +788,17 @@ async function dispatchBffRequest(request, env) {
|
|
|
798
788
|
const defaultExport = workerModule.default;
|
|
799
789
|
const runtime = getRuntimeModule(workerModule);
|
|
800
790
|
if ('effect' === bff.runtimeFramework) {
|
|
801
|
-
let
|
|
802
|
-
if (!
|
|
803
|
-
const {
|
|
804
|
-
|
|
791
|
+
let effectDispatcherPromise = effectBffDispatcherPromises.get(bff.worker);
|
|
792
|
+
if (!effectDispatcherPromise) {
|
|
793
|
+
const { createEffectBffEdgeDispatcher } = await loadEffectEdgeRuntime();
|
|
794
|
+
effectDispatcherPromise = createEffectBffEdgeDispatcher({
|
|
805
795
|
module: runtime,
|
|
806
796
|
prefix: bff.prefix
|
|
807
797
|
});
|
|
808
|
-
|
|
798
|
+
effectBffDispatcherPromises.set(bff.worker, effectDispatcherPromise);
|
|
809
799
|
}
|
|
810
|
-
const
|
|
811
|
-
return
|
|
800
|
+
const effectDispatcher = await effectDispatcherPromise;
|
|
801
|
+
return effectDispatcher.dispatch(request, {
|
|
812
802
|
env
|
|
813
803
|
});
|
|
814
804
|
}
|
|
@@ -836,12 +826,33 @@ async function dispatchBffRequest(request, env) {
|
|
|
836
826
|
};
|
|
837
827
|
return handler(mountedRequest, effectContext);
|
|
838
828
|
}
|
|
829
|
+
async function dispatchServiceBindingRequest(request, env) {
|
|
830
|
+
const serviceBindings = MODERN_WORKER_MANIFEST.serviceBindings;
|
|
831
|
+
if (!Array.isArray(serviceBindings) || 0 === serviceBindings.length) return null;
|
|
832
|
+
const pathname = new URL(request.url).pathname;
|
|
833
|
+
for (const binding of serviceBindings){
|
|
834
|
+
if (!binding?.binding || !binding?.prefix) continue;
|
|
835
|
+
if (!matchesPrefix(pathname, binding.prefix)) continue;
|
|
836
|
+
const service = env?.[binding.binding];
|
|
837
|
+
if (!service || 'function' != typeof service.fetch) return new Response(`Cloudflare service binding not available: ${binding.binding}`, {
|
|
838
|
+
status: 502,
|
|
839
|
+
headers: {
|
|
840
|
+
'content-type': 'text/plain; charset=utf-8',
|
|
841
|
+
'x-modern-js-service-binding': binding.binding
|
|
842
|
+
}
|
|
843
|
+
});
|
|
844
|
+
return service.fetch(request);
|
|
845
|
+
}
|
|
846
|
+
return null;
|
|
847
|
+
}
|
|
839
848
|
export default {
|
|
840
849
|
async fetch (request, env, ctx) {
|
|
841
850
|
const corsPreflightResponse = await createCorsPreflightResponse(request, env);
|
|
842
851
|
if (corsPreflightResponse) return finalizeResponseForRequest(corsPreflightResponse, request);
|
|
843
852
|
const bffResponse = await dispatchBffRequest(request, env);
|
|
844
853
|
if (bffResponse) return finalizeResponseForRequest(withAppCorsHeaders(bffResponse, request), request);
|
|
854
|
+
const serviceBindingResponse = await dispatchServiceBindingRequest(request, env);
|
|
855
|
+
if (serviceBindingResponse) return finalizeResponseForRequest(withAppCorsHeaders(serviceBindingResponse, request), request);
|
|
845
856
|
const route = findRoute(request);
|
|
846
857
|
const { pathname } = new URL(request.url);
|
|
847
858
|
if (isAssetLikePathname(pathname) && !routeMatchesExactly(route, pathname)) {
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { AppTools, CliPlugin } from '../types';
|
|
2
|
+
export type BackendFederationArtifactResult = {
|
|
3
|
+
appId: string;
|
|
4
|
+
manifestPath: string;
|
|
5
|
+
containerPath: string;
|
|
6
|
+
remoteName: string;
|
|
7
|
+
remoteType: string;
|
|
8
|
+
};
|
|
9
|
+
export declare const emitBackendFederationArtifacts: (appDirectory: string, distDirectory: string) => Promise<BackendFederationArtifactResult | undefined>;
|
|
10
|
+
export default _default;
|
|
11
|
+
declare function _default(): CliPlugin<AppTools>;
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
export declare const CLOUDFLARE_WORKER_ENTRY = "server/index.mjs";
|
|
2
|
+
export declare const CLOUDFLARE_WORKER_MANIFEST = "server/modern-worker-manifest.json";
|
|
3
|
+
export declare const CLOUDFLARE_WRANGLER_CONFIG_FILE = "wrangler.json";
|
|
4
|
+
export declare const CLOUDFLARE_OUTPUT_PACKAGE_FILE = "package.json";
|
|
5
|
+
export declare const CLOUDFLARE_WORKER_PACKAGE_FILE = "worker/package.json";
|
|
6
|
+
export declare const CLOUDFLARE_ASSETS_BINDING = "ASSETS";
|
|
7
|
+
export declare const CLOUDFLARE_PUBLIC_ASSETS_DIRECTORY = "public";
|
|
8
|
+
export declare const CLOUDFLARE_WORKER_BUNDLE_DIRECTORY = "worker";
|
|
9
|
+
export declare const CLOUDFLARE_RUNTIME_TYPE = "cloudflare-module-worker";
|
|
10
|
+
export declare const CLOUDFLARE_OUTPUT_PACKAGE_TYPE = "module";
|
|
11
|
+
export declare const CLOUDFLARE_WORKER_PACKAGE_TYPE = "commonjs";
|
|
12
|
+
export declare const CLOUDFLARE_WORKER_BUNDLE_FORMAT = "commonjs";
|
|
13
|
+
export declare const CLOUDFLARE_REQUIRED_COMPATIBILITY_FLAGS: readonly ['nodejs_compat', 'global_fetch_strictly_public'];
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { CLOUDFLARE_ASSETS_BINDING, CLOUDFLARE_OUTPUT_PACKAGE_TYPE, CLOUDFLARE_PUBLIC_ASSETS_DIRECTORY, CLOUDFLARE_REQUIRED_COMPATIBILITY_FLAGS, CLOUDFLARE_WORKER_ENTRY, CLOUDFLARE_WORKER_PACKAGE_TYPE } from './cloudflare-output-contract';
|
|
2
|
+
export type CloudflareOutputPlan = {
|
|
3
|
+
outputDirectory: string;
|
|
4
|
+
requiredFiles: string[];
|
|
5
|
+
publicLeakDirectories: string[];
|
|
6
|
+
paths: {
|
|
7
|
+
workerEntry: string;
|
|
8
|
+
workerManifest: string;
|
|
9
|
+
wranglerConfig: string;
|
|
10
|
+
outputPackage: string;
|
|
11
|
+
workerPackage: string;
|
|
12
|
+
publicAssets: string;
|
|
13
|
+
workerBundle: string;
|
|
14
|
+
};
|
|
15
|
+
packages: {
|
|
16
|
+
output: {
|
|
17
|
+
type: typeof CLOUDFLARE_OUTPUT_PACKAGE_TYPE;
|
|
18
|
+
};
|
|
19
|
+
worker: {
|
|
20
|
+
type: typeof CLOUDFLARE_WORKER_PACKAGE_TYPE;
|
|
21
|
+
};
|
|
22
|
+
};
|
|
23
|
+
wrangler: {
|
|
24
|
+
main: typeof CLOUDFLARE_WORKER_ENTRY;
|
|
25
|
+
assets: {
|
|
26
|
+
binding: typeof CLOUDFLARE_ASSETS_BINDING;
|
|
27
|
+
directory: `./${typeof CLOUDFLARE_PUBLIC_ASSETS_DIRECTORY}`;
|
|
28
|
+
run_worker_first: true;
|
|
29
|
+
};
|
|
30
|
+
requiredCompatibilityFlags: typeof CLOUDFLARE_REQUIRED_COMPATIBILITY_FLAGS;
|
|
31
|
+
};
|
|
32
|
+
};
|
|
33
|
+
export declare function createCloudflareOutputPlan(outputDirectory: string): CloudflareOutputPlan;
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
export type CloudflareOutputVerifierIssueCode = 'missing-file' | 'invalid-manifest' | 'invalid-wrangler' | 'invalid-package' | 'public-output-leak' | 'missing-worker-bundle' | 'invalid-worker-bundle' | 'worker-import-failed' | 'delivery-unit-drift' | 'missing-delivery-unit' | 'forbidden-mutation-pattern';
|
|
2
|
+
export interface CloudflareOutputVerifierIssue {
|
|
3
|
+
code: CloudflareOutputVerifierIssueCode;
|
|
4
|
+
message: string;
|
|
5
|
+
path?: string;
|
|
6
|
+
}
|
|
7
|
+
export interface CloudflareDeliveryUnitIdentity {
|
|
8
|
+
unitId: string;
|
|
9
|
+
buildMarker: string;
|
|
10
|
+
sourceRevision: string;
|
|
11
|
+
}
|
|
12
|
+
export interface VerifyCloudflareOutputOptions {
|
|
13
|
+
outputDirectory: string;
|
|
14
|
+
importWorker?: boolean;
|
|
15
|
+
/**
|
|
16
|
+
* Topology-declared delivery-unit record (from the workspace compact config).
|
|
17
|
+
* When provided, the Cloudflare worker manifest must carry a matching
|
|
18
|
+
* `deliveryUnit` stamp so the deployed worker snapshot is proven to derive
|
|
19
|
+
* from the same delivery unit as the Node/API surfaces (ADR-0019 lane D).
|
|
20
|
+
*/
|
|
21
|
+
deliveryUnit?: CloudflareDeliveryUnitIdentity;
|
|
22
|
+
}
|
|
23
|
+
export interface VerifyCloudflareOutputMutationPolicyOptions {
|
|
24
|
+
scanRoots: string[];
|
|
25
|
+
}
|
|
26
|
+
export interface CloudflareOutputVerifierResult {
|
|
27
|
+
ok: boolean;
|
|
28
|
+
issues: CloudflareOutputVerifierIssue[];
|
|
29
|
+
}
|
|
30
|
+
export declare const verifyCloudflareOutputMutationPolicy: (options: VerifyCloudflareOutputMutationPolicyOptions) => Promise<CloudflareOutputVerifierResult>;
|
|
31
|
+
export declare const verifyCloudflareOutput: (options: VerifyCloudflareOutputOptions) => Promise<CloudflareOutputVerifierResult>;
|
|
32
|
+
export declare const assertCloudflareOutput: (options: VerifyCloudflareOutputOptions) => Promise<void>;
|
|
@@ -52,6 +52,17 @@ export interface CloudflareWorkerD1DatabaseConfig {
|
|
|
52
52
|
*/
|
|
53
53
|
remote?: boolean;
|
|
54
54
|
}
|
|
55
|
+
export interface CloudflareWorkerServiceBindingConfig {
|
|
56
|
+
/** Worker binding name exposed on the module worker `env` object. */
|
|
57
|
+
binding: string;
|
|
58
|
+
/** Target Cloudflare Worker service name. */
|
|
59
|
+
service: string;
|
|
60
|
+
/**
|
|
61
|
+
* Optional application path prefix that Modern.js should dispatch to this
|
|
62
|
+
* service binding with `env[binding].fetch(request)`.
|
|
63
|
+
*/
|
|
64
|
+
prefix?: string;
|
|
65
|
+
}
|
|
55
66
|
export interface CloudflareWorkerSecurityCspConfig {
|
|
56
67
|
mode?: CloudflareWorkerSecurityCspMode;
|
|
57
68
|
directives?: Record<string, string[] | string | false>;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import type { CloudflareWorkerArtifactConfig, CloudflareWorkerD1DatabaseConfig, CloudflareWorkerPublicAssetConfig, CloudflareWorkerSecurityConfig, DeployTarget, JsonValue } from './cloudflareDeploy';
|
|
2
|
-
export type { CloudflareWorkerArtifactConfig, CloudflareWorkerD1DatabaseConfig, CloudflareWorkerPublicAssetConfig, CloudflareWorkerSecurityConfig, CloudflareWorkerSecurityCorsConfig, CloudflareWorkerSecurityCspConfig, CloudflareWorkerSecurityCspMode, CloudflareWorkerSecurityNoindexConfig, DeployTarget, JsonValue, } from './cloudflareDeploy';
|
|
1
|
+
import type { CloudflareWorkerArtifactConfig, CloudflareWorkerD1DatabaseConfig, CloudflareWorkerPublicAssetConfig, CloudflareWorkerSecurityConfig, CloudflareWorkerServiceBindingConfig, DeployTarget, JsonValue } from './cloudflareDeploy';
|
|
2
|
+
export type { CloudflareWorkerArtifactConfig, CloudflareWorkerD1DatabaseConfig, CloudflareWorkerPublicAssetConfig, CloudflareWorkerSecurityConfig, CloudflareWorkerSecurityCorsConfig, CloudflareWorkerSecurityCspConfig, CloudflareWorkerSecurityCspMode, CloudflareWorkerSecurityNoindexConfig, CloudflareWorkerServiceBindingConfig, DeployTarget, JsonValue, } from './cloudflareDeploy';
|
|
3
3
|
export interface MicroFrontend {
|
|
4
4
|
/**
|
|
5
5
|
* Specifies whether to enable the HTML entry.
|
|
@@ -59,6 +59,13 @@ export interface DeployUserConfig {
|
|
|
59
59
|
* directories into `.output`.
|
|
60
60
|
*/
|
|
61
61
|
d1Databases?: CloudflareWorkerD1DatabaseConfig[];
|
|
62
|
+
/**
|
|
63
|
+
* First-class Cloudflare service bindings. Modern.js writes these to
|
|
64
|
+
* `wrangler.json` as `services`; when a binding also has `prefix`,
|
|
65
|
+
* the generated Worker dispatches matching requests through
|
|
66
|
+
* `env[binding].fetch(request)`.
|
|
67
|
+
*/
|
|
68
|
+
services?: CloudflareWorkerServiceBindingConfig[];
|
|
62
69
|
/**
|
|
63
70
|
* Dist output paths that must not be copied into Cloudflare public assets.
|
|
64
71
|
* Entries are slash-normalized path prefixes relative to the app dist root.
|
package/package.json
CHANGED
|
@@ -17,7 +17,7 @@
|
|
|
17
17
|
"modern",
|
|
18
18
|
"modern.js"
|
|
19
19
|
],
|
|
20
|
-
"version": "3.5.0-ultramodern.
|
|
20
|
+
"version": "3.5.0-ultramodern.29",
|
|
21
21
|
"types": "./dist/types/index.d.ts",
|
|
22
22
|
"main": "./dist/cjs/index.js",
|
|
23
23
|
"exports": {
|
|
@@ -45,6 +45,12 @@
|
|
|
45
45
|
"require": "./dist/cjs/run/index.js",
|
|
46
46
|
"default": "./dist/cjs/run/index.js"
|
|
47
47
|
},
|
|
48
|
+
"./cloudflare-output-verifier": {
|
|
49
|
+
"types": "./dist/types/plugins/deploy/platforms/cloudflare-output-verifier.d.ts",
|
|
50
|
+
"import": "./dist/esm-node/plugins/deploy/platforms/cloudflare-output-verifier.mjs",
|
|
51
|
+
"require": "./dist/cjs/plugins/deploy/platforms/cloudflare-output-verifier.js",
|
|
52
|
+
"default": "./dist/cjs/plugins/deploy/platforms/cloudflare-output-verifier.js"
|
|
53
|
+
},
|
|
48
54
|
"./types": {
|
|
49
55
|
"types": "./lib/types.d.ts",
|
|
50
56
|
"default": "./lib/types.d.ts"
|
|
@@ -90,16 +96,16 @@
|
|
|
90
96
|
"ndepe": "^0.1.13",
|
|
91
97
|
"pkg-types": "^2.3.1",
|
|
92
98
|
"std-env": "4.1.0",
|
|
93
|
-
"@modern-js/builder": "npm:@bleedingdev/modern-js-builder@3.5.0-ultramodern.
|
|
94
|
-
"@modern-js/
|
|
95
|
-
"@modern-js/
|
|
96
|
-
"@modern-js/plugin": "npm:@bleedingdev/modern-js-plugin@3.5.0-ultramodern.
|
|
97
|
-
"@modern-js/server": "npm:@bleedingdev/modern-js-server@3.5.0-ultramodern.
|
|
98
|
-
"@modern-js/
|
|
99
|
-
"@modern-js/
|
|
100
|
-
"@modern-js/
|
|
101
|
-
"@modern-js/
|
|
102
|
-
"@modern-js/utils": "npm:@bleedingdev/modern-js-utils@3.5.0-ultramodern.
|
|
99
|
+
"@modern-js/builder": "npm:@bleedingdev/modern-js-builder@3.5.0-ultramodern.29",
|
|
100
|
+
"@modern-js/plugin": "npm:@bleedingdev/modern-js-plugin@3.5.0-ultramodern.29",
|
|
101
|
+
"@modern-js/prod-server": "npm:@bleedingdev/modern-js-prod-server@3.5.0-ultramodern.29",
|
|
102
|
+
"@modern-js/plugin-data-loader": "npm:@bleedingdev/modern-js-plugin-data-loader@3.5.0-ultramodern.29",
|
|
103
|
+
"@modern-js/server": "npm:@bleedingdev/modern-js-server@3.5.0-ultramodern.29",
|
|
104
|
+
"@modern-js/i18n-utils": "npm:@bleedingdev/modern-js-i18n-utils@3.5.0-ultramodern.29",
|
|
105
|
+
"@modern-js/server-core": "npm:@bleedingdev/modern-js-server-core@3.5.0-ultramodern.29",
|
|
106
|
+
"@modern-js/types": "npm:@bleedingdev/modern-js-types@3.5.0-ultramodern.29",
|
|
107
|
+
"@modern-js/utils": "npm:@bleedingdev/modern-js-utils@3.5.0-ultramodern.29",
|
|
108
|
+
"@modern-js/server-utils": "npm:@bleedingdev/modern-js-server-utils@3.5.0-ultramodern.29"
|
|
103
109
|
},
|
|
104
110
|
"devDependencies": {
|
|
105
111
|
"@rslib/core": "0.23.1",
|