@bleedingdev/modern-js-app-tools-extensions 3.9.0-ultramodern.2 → 3.9.0-ultramodern.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/dist/cjs/backend-federation-build/codegen.js +267 -0
- package/dist/cjs/backend-federation-build/config.js +239 -0
- package/dist/cjs/backend-federation-build/emit.js +154 -0
- package/dist/cjs/backend-federation-build/index.js +53 -0
- package/dist/cjs/build-config/build-environment.js +129 -0
- package/dist/cjs/build-config/precompress/plugin.js +124 -0
- package/dist/cjs/build-config/precompress/types.js +18 -0
- package/dist/cjs/build-config/public.js +43 -0
- package/dist/cjs/build-config/remote-address.js +58 -0
- package/dist/cjs/cloudflare/artifacts.js +8 -19
- package/dist/cjs/cloudflare/constants.js +1 -1
- package/dist/cjs/cloudflare/delivery-unit.js +23 -42
- package/dist/cjs/cloudflare/index.js +10 -2
- package/dist/cjs/cloudflare/worker-manifest.js +13 -4
- package/dist/cjs/cloudflare/wrangler-config.js +35 -7
- package/dist/cjs/cloudflare-builder.js +252 -75
- package/dist/cjs/cloudflare-output-contract.js +69 -3
- package/dist/cjs/cloudflare-output-verifier/identity.js +29 -27
- package/dist/cjs/cloudflare-output-verifier/index.js +10 -0
- package/dist/cjs/cloudflare-output-verifier/manifest.js +46 -0
- package/dist/cjs/cloudflare-output-verifier/mutation-policy.js +7 -1
- package/dist/cjs/cloudflare-output-verifier/worker-bundles.js +14 -6
- package/dist/cjs/config.js +34 -1
- package/dist/cjs/deploy-output/npmAliases.js +251 -0
- package/dist/cjs/deploy-output/plugin.js +97 -0
- package/dist/cjs/deploy-output/public-assets.js +146 -0
- package/dist/cjs/deploy-output/target.js +104 -0
- package/dist/cjs/deploy-output/trace-files.js +90 -0
- package/dist/cjs/native-type-checker.js +193 -0
- package/dist/cjs/policy-defaults.js +101 -0
- package/dist/cjs/release-envelope/framework-output.js +153 -79
- package/dist/cjs/release-envelope/index.js +10 -4
- package/dist/cjs/release-envelope/plugin.js +18 -13
- package/dist/cjs/release-identity.js +5 -6
- package/dist/cjs/runtime-package-resolution.js +118 -0
- package/dist/cjs/templates/cloudflare-entry.001-bootstrap-security.mjs +0 -3
- package/dist/cjs/templates/cloudflare-entry.002-assets-routes.mjs +1 -1
- package/dist/cjs/templates/cloudflare-entry.004-rendering-css.mjs +5 -1
- package/dist/cjs/templates/cloudflare-entry.005-worker-dispatch.mjs +98 -10
- package/dist/cjs/templates/cloudflare-entry.006-fetch-handler.mjs +9 -2
- package/dist/cjs/templates/cloudflare-worker-route-data.mjs +1069 -0
- package/dist/esm/backend-federation-build/codegen.mjs +216 -0
- package/dist/esm/backend-federation-build/config.mjs +163 -0
- package/dist/esm/backend-federation-build/emit.mjs +103 -0
- package/dist/esm/backend-federation-build/index.mjs +1 -0
- package/dist/esm/build-config/build-environment.mjs +88 -0
- package/dist/esm/build-config/precompress/plugin.mjs +76 -0
- package/dist/esm/build-config/precompress/types.mjs +0 -0
- package/dist/esm/build-config/public.mjs +1 -0
- package/dist/esm/build-config/remote-address.mjs +20 -0
- package/dist/esm/cloudflare/artifacts.mjs +8 -19
- package/dist/esm/cloudflare/constants.mjs +1 -1
- package/dist/esm/cloudflare/delivery-unit.mjs +17 -36
- package/dist/esm/cloudflare/index.mjs +10 -2
- package/dist/esm/cloudflare/worker-manifest.mjs +13 -4
- package/dist/esm/cloudflare/wrangler-config.mjs +35 -7
- package/dist/esm/cloudflare-builder.mjs +246 -75
- package/dist/esm/cloudflare-output-contract.mjs +59 -2
- package/dist/esm/cloudflare-output-verifier/identity.mjs +27 -25
- package/dist/esm/cloudflare-output-verifier/index.mjs +10 -0
- package/dist/esm/cloudflare-output-verifier/manifest.mjs +46 -0
- package/dist/esm/cloudflare-output-verifier/mutation-policy.mjs +7 -1
- package/dist/esm/cloudflare-output-verifier/worker-bundles.mjs +15 -7
- package/dist/esm/config.mjs +3 -0
- package/dist/esm/deploy-output/npmAliases.mjs +199 -0
- package/dist/esm/deploy-output/plugin.mjs +46 -0
- package/dist/esm/deploy-output/public-assets.mjs +82 -0
- package/dist/esm/deploy-output/target.mjs +57 -0
- package/dist/esm/deploy-output/trace-files.mjs +38 -0
- package/dist/esm/native-type-checker.mjs +142 -0
- package/dist/esm/policy-defaults.mjs +45 -0
- package/dist/esm/release-envelope/framework-output.mjs +130 -56
- package/dist/esm/release-envelope/index.mjs +10 -4
- package/dist/esm/release-envelope/plugin.mjs +18 -13
- package/dist/esm/release-identity.mjs +5 -6
- package/dist/esm/runtime-package-resolution.mjs +60 -0
- package/dist/esm/templates/cloudflare-entry.001-bootstrap-security.mjs +0 -3
- package/dist/esm/templates/cloudflare-entry.002-assets-routes.mjs +1 -1
- package/dist/esm/templates/cloudflare-entry.004-rendering-css.mjs +5 -1
- package/dist/esm/templates/cloudflare-entry.005-worker-dispatch.mjs +98 -10
- package/dist/esm/templates/cloudflare-entry.006-fetch-handler.mjs +9 -2
- package/dist/esm/templates/cloudflare-worker-route-data.mjs +1069 -0
- package/dist/esm-node/backend-federation-build/codegen.mjs +217 -0
- package/dist/esm-node/backend-federation-build/config.mjs +164 -0
- package/dist/esm-node/backend-federation-build/emit.mjs +104 -0
- package/dist/esm-node/backend-federation-build/index.mjs +2 -0
- package/dist/esm-node/build-config/build-environment.mjs +89 -0
- package/dist/esm-node/build-config/precompress/plugin.mjs +77 -0
- package/dist/esm-node/build-config/precompress/types.mjs +1 -0
- package/dist/esm-node/build-config/public.mjs +2 -0
- package/dist/esm-node/build-config/remote-address.mjs +21 -0
- package/dist/esm-node/cloudflare/artifacts.mjs +8 -19
- package/dist/esm-node/cloudflare/constants.mjs +1 -1
- package/dist/esm-node/cloudflare/delivery-unit.mjs +17 -36
- package/dist/esm-node/cloudflare/index.mjs +10 -2
- package/dist/esm-node/cloudflare/worker-manifest.mjs +13 -4
- package/dist/esm-node/cloudflare/wrangler-config.mjs +35 -7
- package/dist/esm-node/cloudflare-builder.mjs +246 -75
- package/dist/esm-node/cloudflare-output-contract.mjs +59 -2
- package/dist/esm-node/cloudflare-output-verifier/identity.mjs +27 -25
- package/dist/esm-node/cloudflare-output-verifier/index.mjs +10 -0
- package/dist/esm-node/cloudflare-output-verifier/manifest.mjs +46 -0
- package/dist/esm-node/cloudflare-output-verifier/mutation-policy.mjs +7 -1
- package/dist/esm-node/cloudflare-output-verifier/worker-bundles.mjs +15 -7
- package/dist/esm-node/config.mjs +3 -0
- package/dist/esm-node/deploy-output/npmAliases.mjs +200 -0
- package/dist/esm-node/deploy-output/plugin.mjs +49 -0
- package/dist/esm-node/deploy-output/public-assets.mjs +83 -0
- package/dist/esm-node/deploy-output/target.mjs +58 -0
- package/dist/esm-node/deploy-output/trace-files.mjs +39 -0
- package/dist/esm-node/native-type-checker.mjs +143 -0
- package/dist/esm-node/policy-defaults.mjs +46 -0
- package/dist/esm-node/release-envelope/framework-output.mjs +130 -56
- package/dist/esm-node/release-envelope/index.mjs +10 -4
- package/dist/esm-node/release-envelope/plugin.mjs +18 -13
- package/dist/esm-node/release-identity.mjs +5 -6
- package/dist/esm-node/runtime-package-resolution.mjs +61 -0
- package/dist/esm-node/templates/cloudflare-entry.001-bootstrap-security.mjs +0 -3
- package/dist/esm-node/templates/cloudflare-entry.002-assets-routes.mjs +1 -1
- package/dist/esm-node/templates/cloudflare-entry.004-rendering-css.mjs +5 -1
- package/dist/esm-node/templates/cloudflare-entry.005-worker-dispatch.mjs +98 -10
- package/dist/esm-node/templates/cloudflare-entry.006-fetch-handler.mjs +9 -2
- package/dist/esm-node/templates/cloudflare-worker-route-data.mjs +1069 -0
- package/dist/types/backend-federation-build/codegen.d.ts +116 -0
- package/dist/types/backend-federation-build/config.d.ts +121 -0
- package/dist/types/backend-federation-build/emit.d.ts +21 -0
- package/dist/types/backend-federation-build/index.d.ts +2 -0
- package/dist/types/build-config/build-environment.d.ts +14 -0
- package/dist/types/build-config/precompress/plugin.d.ts +4 -0
- package/dist/types/build-config/precompress/types.d.ts +19 -0
- package/dist/types/build-config/public.d.ts +2 -0
- package/dist/types/build-config/remote-address.d.ts +3 -0
- package/dist/types/cloudflare/artifacts.d.ts +7 -6
- package/dist/types/cloudflare/constants.d.ts +1 -1
- package/dist/types/cloudflare/delivery-unit.d.ts +3 -3
- package/dist/types/cloudflare/worker-manifest.d.ts +2 -2
- package/dist/types/cloudflare/wrangler-config.d.ts +6 -0
- package/dist/types/cloudflare-builder.d.ts +49 -9
- package/dist/types/cloudflare-output-contract.d.ts +4 -1
- package/dist/types/cloudflare-output-verifier/identity.d.ts +1 -1
- package/dist/types/cloudflare-output-verifier/worker-bundles.d.ts +2 -2
- package/dist/types/config.d.ts +29 -1
- package/dist/types/deploy-output/npmAliases.d.ts +14 -0
- package/dist/types/deploy-output/plugin.d.ts +35 -0
- package/dist/types/deploy-output/public-assets.d.ts +51 -0
- package/dist/types/deploy-output/target.d.ts +29 -0
- package/dist/types/deploy-output/trace-files.d.ts +17 -0
- package/dist/types/native-type-checker.d.ts +15 -0
- package/dist/types/policy-defaults.d.ts +46 -0
- package/dist/types/precompress/LICENSE +20 -0
- package/dist/types/precompress/index.d.ts +76 -0
- package/dist/types/release-envelope/framework-output.d.ts +8 -3
- package/dist/types/release-envelope/plugin.d.ts +7 -7
- package/dist/types/runtime-package-resolution.d.ts +28 -0
- package/dist/types/templates/cloudflare-worker-route-data.d.mts +14 -0
- package/package.json +97 -15
- package/src/backend-federation-build/codegen.ts +254 -0
- package/src/backend-federation-build/config.ts +492 -0
- package/src/backend-federation-build/emit.ts +213 -0
- package/src/backend-federation-build/index.ts +2 -0
- package/src/build-config/build-environment.ts +160 -0
- package/src/build-config/precompress/plugin.ts +140 -0
- package/src/build-config/precompress/types.ts +26 -0
- package/src/build-config/public.ts +5 -0
- package/src/build-config/remote-address.ts +33 -0
- package/src/cloudflare/artifacts.ts +22 -43
- package/src/cloudflare/constants.ts +1 -1
- package/src/cloudflare/delivery-unit.ts +42 -53
- package/src/cloudflare/index.ts +24 -11
- package/src/cloudflare/worker-manifest.ts +20 -3
- package/src/cloudflare/wrangler-config.ts +86 -10
- package/src/cloudflare-builder.ts +475 -151
- package/src/cloudflare-output-contract.ts +70 -0
- package/src/cloudflare-output-verifier/identity.ts +5 -1
- package/src/cloudflare-output-verifier/index.ts +20 -0
- package/src/cloudflare-output-verifier/manifest.ts +77 -0
- package/src/cloudflare-output-verifier/mutation-policy.ts +11 -1
- package/src/cloudflare-output-verifier/worker-bundles.ts +32 -14
- package/src/config.ts +34 -6
- package/src/deploy-output/npmAliases.ts +382 -0
- package/src/deploy-output/plugin.ts +86 -0
- package/src/deploy-output/public-assets.ts +224 -0
- package/src/deploy-output/target.ts +106 -0
- package/src/deploy-output/trace-files.ts +67 -0
- package/src/native-type-checker.ts +183 -0
- package/src/policy-defaults.ts +127 -0
- package/src/release-envelope/framework-output.ts +346 -94
- package/src/release-envelope/index.ts +26 -5
- package/src/release-envelope/plugin.ts +43 -40
- package/src/release-identity.ts +13 -2
- package/src/runtime-package-resolution.ts +115 -0
- package/src/templates/cloudflare-entry.001-bootstrap-security.mjs +0 -3
- package/src/templates/cloudflare-entry.002-assets-routes.mjs +1 -1
- package/src/templates/cloudflare-entry.004-rendering-css.mjs +5 -1
- package/src/templates/cloudflare-entry.005-worker-dispatch.mjs +98 -10
- package/src/templates/cloudflare-entry.006-fetch-handler.mjs +9 -2
- package/src/templates/cloudflare-worker-route-data.mjs +1069 -0
- package/dist/cjs/templates/cloudflare-worker-fs-promises.mjs +0 -11
- package/dist/cjs/templates/cloudflare-worker-loadable-server.mjs +0 -281
- package/dist/cjs/templates/cloudflare-worker-mf-ssr-runtime-plugin.mjs +0 -14
- package/dist/cjs/templates/cloudflare-worker-path.mjs +0 -98
- package/dist/esm/templates/cloudflare-worker-fs-promises.mjs +0 -11
- package/dist/esm/templates/cloudflare-worker-loadable-server.mjs +0 -281
- package/dist/esm/templates/cloudflare-worker-mf-ssr-runtime-plugin.mjs +0 -14
- package/dist/esm/templates/cloudflare-worker-path.mjs +0 -98
- package/dist/esm-node/templates/cloudflare-worker-fs-promises.mjs +0 -11
- package/dist/esm-node/templates/cloudflare-worker-loadable-server.mjs +0 -281
- package/dist/esm-node/templates/cloudflare-worker-mf-ssr-runtime-plugin.mjs +0 -14
- package/dist/esm-node/templates/cloudflare-worker-path.mjs +0 -98
- package/dist/types/templates/cloudflare-worker-fs-promises.d.mts +0 -5
- package/dist/types/templates/cloudflare-worker-loadable-server.d.mts +0 -48
- package/dist/types/templates/cloudflare-worker-mf-ssr-runtime-plugin.d.mts +0 -13
- package/dist/types/templates/cloudflare-worker-path.d.mts +0 -21
- package/src/templates/cloudflare-worker-fs-promises.mjs +0 -11
- package/src/templates/cloudflare-worker-loadable-server.mjs +0 -281
- package/src/templates/cloudflare-worker-mf-ssr-runtime-plugin.mjs +0 -14
- package/src/templates/cloudflare-worker-path.mjs +0 -98
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
import { getArgv } from '@modern-js/utils';
|
|
2
|
+
import { provider as detectedProvider } from 'std-env';
|
|
3
|
+
|
|
4
|
+
export const DEPLOY_TARGETS = [
|
|
5
|
+
'node',
|
|
6
|
+
'vercel',
|
|
7
|
+
'netlify',
|
|
8
|
+
'ghPages',
|
|
9
|
+
'cloudflare',
|
|
10
|
+
] as const;
|
|
11
|
+
|
|
12
|
+
export type DeployTarget = (typeof DEPLOY_TARGETS)[number];
|
|
13
|
+
|
|
14
|
+
export const DEPLOY_TARGET_FLAG = '--deploy-target';
|
|
15
|
+
|
|
16
|
+
const providerDeployTargets: Partial<Record<string, DeployTarget>> = {
|
|
17
|
+
vercel: 'vercel',
|
|
18
|
+
netlify: 'netlify',
|
|
19
|
+
cloudflare: 'cloudflare',
|
|
20
|
+
cloudflare_pages: 'cloudflare',
|
|
21
|
+
cloudflare_workers: 'cloudflare',
|
|
22
|
+
};
|
|
23
|
+
|
|
24
|
+
export interface ResolvedDeployTarget {
|
|
25
|
+
target: DeployTarget;
|
|
26
|
+
/** The flag, `deploy.target` or `MODERNJS_DEPLOY` chose the target. */
|
|
27
|
+
explicit: boolean;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
export interface ResolveDeployTargetOptions {
|
|
31
|
+
argv?: readonly string[];
|
|
32
|
+
configTarget?: string;
|
|
33
|
+
env?: string;
|
|
34
|
+
provider?: string;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
const readDeployTargetFlag = (argv: readonly string[]) => {
|
|
38
|
+
for (const [index, arg] of argv.entries()) {
|
|
39
|
+
if (arg === DEPLOY_TARGET_FLAG) {
|
|
40
|
+
const value = argv[index + 1];
|
|
41
|
+
if (value === undefined || value.startsWith('-')) {
|
|
42
|
+
throw new Error(`${DEPLOY_TARGET_FLAG} needs a value.`);
|
|
43
|
+
}
|
|
44
|
+
return value;
|
|
45
|
+
}
|
|
46
|
+
if (arg.startsWith(`${DEPLOY_TARGET_FLAG}=`)) {
|
|
47
|
+
return arg.slice(DEPLOY_TARGET_FLAG.length + 1);
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
return undefined;
|
|
51
|
+
};
|
|
52
|
+
|
|
53
|
+
const assertDeployTarget = (target: string, source: string): DeployTarget => {
|
|
54
|
+
if (!(DEPLOY_TARGETS as readonly string[]).includes(target)) {
|
|
55
|
+
throw new Error(
|
|
56
|
+
`Unknown deploy target '${target}' from ${source}. Use one of: ${DEPLOY_TARGETS.join(', ')}.`,
|
|
57
|
+
);
|
|
58
|
+
}
|
|
59
|
+
return target as DeployTarget;
|
|
60
|
+
};
|
|
61
|
+
|
|
62
|
+
/**
|
|
63
|
+
* The one deploy-target resolver: `--deploy-target` > `deploy.target` >
|
|
64
|
+
* `MODERNJS_DEPLOY` > detected CI provider > `node`. app-tools stores the
|
|
65
|
+
* result in the app context once; config files that branch on the target call
|
|
66
|
+
* it without `configTarget`.
|
|
67
|
+
*/
|
|
68
|
+
export const resolveDeployTarget = ({
|
|
69
|
+
argv = getArgv(),
|
|
70
|
+
configTarget,
|
|
71
|
+
env = process.env.MODERNJS_DEPLOY,
|
|
72
|
+
provider = detectedProvider,
|
|
73
|
+
}: ResolveDeployTargetOptions = {}): ResolvedDeployTarget => {
|
|
74
|
+
const explicit = (
|
|
75
|
+
[
|
|
76
|
+
[readDeployTargetFlag(argv), DEPLOY_TARGET_FLAG],
|
|
77
|
+
[configTarget, 'deploy.target'],
|
|
78
|
+
[env, 'MODERNJS_DEPLOY'],
|
|
79
|
+
] as const
|
|
80
|
+
).find(([target]) => target);
|
|
81
|
+
if (explicit?.[0]) {
|
|
82
|
+
return {
|
|
83
|
+
target: assertDeployTarget(explicit[0], explicit[1]),
|
|
84
|
+
explicit: true,
|
|
85
|
+
};
|
|
86
|
+
}
|
|
87
|
+
return {
|
|
88
|
+
target: (provider && providerDeployTargets[provider]) || 'node',
|
|
89
|
+
explicit: false,
|
|
90
|
+
};
|
|
91
|
+
};
|
|
92
|
+
|
|
93
|
+
/**
|
|
94
|
+
* The target `modern deploy` stages. Apps under another CLI meta name deploy
|
|
95
|
+
* only when a flag, config or env chose the target explicitly.
|
|
96
|
+
*/
|
|
97
|
+
export const getDeployingTarget = ({
|
|
98
|
+
deployTarget,
|
|
99
|
+
metaName,
|
|
100
|
+
}: {
|
|
101
|
+
deployTarget?: ResolvedDeployTarget;
|
|
102
|
+
metaName: string;
|
|
103
|
+
}): DeployTarget | undefined =>
|
|
104
|
+
deployTarget && (metaName === 'modern-js' || deployTarget.explicit)
|
|
105
|
+
? deployTarget.target
|
|
106
|
+
: undefined;
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
import os from 'node:os';
|
|
2
|
+
import path from 'node:path';
|
|
3
|
+
import { type NodeFileTraceResult, nodeFileTrace } from '@vercel/nft';
|
|
4
|
+
|
|
5
|
+
// Directories owned by the build host rather than the app. nft statically
|
|
6
|
+
// evaluates `os.homedir()`, `os.tmpdir()` and literal system paths, so code
|
|
7
|
+
// like `fs.readFileSync(path.join(os.homedir(), name))` becomes a glob of the
|
|
8
|
+
// whole home directory. With `base: '/'` that glob walks the machine.
|
|
9
|
+
const SYSTEM_ROOTS =
|
|
10
|
+
process.platform === 'win32'
|
|
11
|
+
? []
|
|
12
|
+
: ['/dev', '/etc', '/proc', '/run', '/sys', '/var/run'];
|
|
13
|
+
|
|
14
|
+
const GLOB_SEGMENT = /[*?[{]/;
|
|
15
|
+
|
|
16
|
+
const isInside = (parent: string, child: string) =>
|
|
17
|
+
child === parent || child.startsWith(`${parent}${path.sep}`);
|
|
18
|
+
|
|
19
|
+
const globRoot = (absolutePattern: string) => {
|
|
20
|
+
const { root } = path.parse(absolutePattern);
|
|
21
|
+
const segments = absolutePattern.slice(root.length).split(path.sep);
|
|
22
|
+
const index = segments.findIndex(segment => GLOB_SEGMENT.test(segment));
|
|
23
|
+
return index === -1
|
|
24
|
+
? undefined
|
|
25
|
+
: path.join(root, ...segments.slice(0, index));
|
|
26
|
+
};
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* Builds the nft `ignore` predicate for a trace rooted at `base`: skip every
|
|
30
|
+
* path under a system root, and skip globs that would enumerate the file
|
|
31
|
+
* system root, the home directory or the temp directory as a whole. Files
|
|
32
|
+
* inside home or temp are still traced, since package stores can live there.
|
|
33
|
+
*/
|
|
34
|
+
export const createBuildHostIgnore = (base: string) => {
|
|
35
|
+
const wholeDirectories = new Set([
|
|
36
|
+
path.parse(path.resolve(base)).root,
|
|
37
|
+
path.resolve(os.homedir()),
|
|
38
|
+
path.resolve(os.tmpdir()),
|
|
39
|
+
]);
|
|
40
|
+
return (relativePath: string) => {
|
|
41
|
+
const absolutePath = path.resolve(base, relativePath);
|
|
42
|
+
if (SYSTEM_ROOTS.some(root => isInside(root, absolutePath))) {
|
|
43
|
+
return true;
|
|
44
|
+
}
|
|
45
|
+
const root = globRoot(absolutePath);
|
|
46
|
+
return root !== undefined && wholeDirectories.has(root);
|
|
47
|
+
};
|
|
48
|
+
};
|
|
49
|
+
|
|
50
|
+
/**
|
|
51
|
+
* `traceFiles` implementation for ndepe's `nodeDepEmit`, tracing with the
|
|
52
|
+
* `@vercel/nft` release app-tools-extensions depends on instead of the one ndepe pins.
|
|
53
|
+
*/
|
|
54
|
+
export const traceDeployFiles = ({
|
|
55
|
+
entryFiles,
|
|
56
|
+
sourceDir,
|
|
57
|
+
base = '/',
|
|
58
|
+
}: {
|
|
59
|
+
entryFiles: string[];
|
|
60
|
+
sourceDir: string;
|
|
61
|
+
base?: string;
|
|
62
|
+
}): Promise<NodeFileTraceResult> =>
|
|
63
|
+
nodeFileTrace(entryFiles, {
|
|
64
|
+
base,
|
|
65
|
+
processCwd: sourceDir,
|
|
66
|
+
ignore: createBuildHostIgnore(base),
|
|
67
|
+
});
|
|
@@ -0,0 +1,183 @@
|
|
|
1
|
+
import { execFile } from 'node:child_process';
|
|
2
|
+
import { existsSync, realpathSync } from 'node:fs';
|
|
3
|
+
import path from 'node:path';
|
|
4
|
+
import { promisify } from 'node:util';
|
|
5
|
+
import { refreshTsgoCheckerConfig } from '@modern-js/builder';
|
|
6
|
+
import type { Rspack, RspackChain } from '@rsbuild/core';
|
|
7
|
+
|
|
8
|
+
const execute = promisify(execFile);
|
|
9
|
+
const name = 'UltramodernNativeTypeChecker';
|
|
10
|
+
|
|
11
|
+
// Windows file events expand 8.3 aliases; register the same native path spelling.
|
|
12
|
+
// A path that does not exist yet (a project tsconfig mid-edit) cannot be
|
|
13
|
+
// realpathed; it is registered as spelled so its return still triggers a build.
|
|
14
|
+
const watchDependencyPath = (file: string): string => {
|
|
15
|
+
if (process.platform !== 'win32') return file;
|
|
16
|
+
try {
|
|
17
|
+
return realpathSync.native(file);
|
|
18
|
+
} catch {
|
|
19
|
+
return file;
|
|
20
|
+
}
|
|
21
|
+
};
|
|
22
|
+
|
|
23
|
+
export class UltramodernNativeTypeChecker {
|
|
24
|
+
constructor(
|
|
25
|
+
private readonly options: {
|
|
26
|
+
compiler: () => string;
|
|
27
|
+
configFile: string;
|
|
28
|
+
build: boolean;
|
|
29
|
+
},
|
|
30
|
+
) {}
|
|
31
|
+
|
|
32
|
+
async check(): Promise<void> {
|
|
33
|
+
const { configFile, build } = this.options;
|
|
34
|
+
if (!build) {
|
|
35
|
+
const config = JSON.parse(
|
|
36
|
+
await this.run(['--showConfig', '--project', configFile]),
|
|
37
|
+
) as { references?: { path: string }[] };
|
|
38
|
+
// Project mode consumes referenced declarations but never builds them.
|
|
39
|
+
// Prepare only the references using their own emit contracts, then keep
|
|
40
|
+
// the app itself in no-emit mode. This also refreshes stale declarations.
|
|
41
|
+
if (config.references?.length) {
|
|
42
|
+
await this.run([
|
|
43
|
+
'--build',
|
|
44
|
+
...config.references.map(reference =>
|
|
45
|
+
path.resolve(path.dirname(configFile), reference.path),
|
|
46
|
+
),
|
|
47
|
+
'--stopBuildOnErrors',
|
|
48
|
+
'--pretty',
|
|
49
|
+
'false',
|
|
50
|
+
]);
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
const args = build
|
|
54
|
+
? ['--build', configFile, '--stopBuildOnErrors']
|
|
55
|
+
: ['--project', configFile, '--noEmit'];
|
|
56
|
+
await this.run([...args, '--pretty', 'false']);
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
private async run(args: string[]): Promise<string> {
|
|
60
|
+
try {
|
|
61
|
+
const result = await execute(this.options.compiler(), args, {
|
|
62
|
+
cwd: path.dirname(this.options.configFile),
|
|
63
|
+
maxBuffer: 16 * 1024 * 1024,
|
|
64
|
+
});
|
|
65
|
+
return result.stdout;
|
|
66
|
+
} catch (cause) {
|
|
67
|
+
const output = cause as { stdout?: string; stderr?: string };
|
|
68
|
+
const diagnostics = `${output.stdout ?? ''}${output.stderr ?? ''}`;
|
|
69
|
+
throw new Error(
|
|
70
|
+
`${name} failed:\n${diagnostics || (cause instanceof Error ? cause.message : String(cause))}`,
|
|
71
|
+
{ cause },
|
|
72
|
+
);
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
private async watchInputs(): Promise<{
|
|
77
|
+
inputs: Set<string>;
|
|
78
|
+
missing: Set<string>;
|
|
79
|
+
}> {
|
|
80
|
+
const inputs = new Set<string>();
|
|
81
|
+
const missing = new Set<string>();
|
|
82
|
+
const projects = [this.options.configFile];
|
|
83
|
+
const visited = new Set<string>();
|
|
84
|
+
for (const configFile of projects) {
|
|
85
|
+
if (visited.has(configFile)) continue;
|
|
86
|
+
visited.add(configFile);
|
|
87
|
+
// Registered before it is parsed: a referenced config that is absent or
|
|
88
|
+
// unparsable right now must still be watched, or creating or repairing
|
|
89
|
+
// it never re-triggers the compilation. `check()` reports the error.
|
|
90
|
+
inputs.add(configFile);
|
|
91
|
+
if (!existsSync(configFile)) {
|
|
92
|
+
missing.add(configFile);
|
|
93
|
+
continue;
|
|
94
|
+
}
|
|
95
|
+
let config: { files?: string[]; references?: { path: string }[] };
|
|
96
|
+
try {
|
|
97
|
+
config = JSON.parse(
|
|
98
|
+
await this.run(['--showConfig', '--project', configFile]),
|
|
99
|
+
);
|
|
100
|
+
} catch {
|
|
101
|
+
continue;
|
|
102
|
+
}
|
|
103
|
+
const directory = path.dirname(configFile);
|
|
104
|
+
for (const file of config.files ?? [])
|
|
105
|
+
inputs.add(path.resolve(directory, file));
|
|
106
|
+
for (const reference of config.references ?? []) {
|
|
107
|
+
const target = path.resolve(directory, reference.path);
|
|
108
|
+
projects.push(
|
|
109
|
+
path.extname(target) === '.json'
|
|
110
|
+
? target
|
|
111
|
+
: path.join(target, 'tsconfig.json'),
|
|
112
|
+
);
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
return { inputs, missing };
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
apply(compiler: Rspack.Compiler): void {
|
|
119
|
+
compiler.hooks.thisCompilation.tap(name, compilation => {
|
|
120
|
+
compilation.hooks.processAssets.tapPromise(name, async () => {
|
|
121
|
+
try {
|
|
122
|
+
compilation.fileDependencies.add(
|
|
123
|
+
watchDependencyPath(this.options.configFile),
|
|
124
|
+
);
|
|
125
|
+
// A generated checker config restates values TypeScript does not
|
|
126
|
+
// inherit through `extends` (project references above all). Rebuild
|
|
127
|
+
// it from the project's own tsconfig before every check, and watch
|
|
128
|
+
// that tsconfig, so an edit during `modern dev` reaches the next
|
|
129
|
+
// compilation instead of the next restart.
|
|
130
|
+
const projectConfigFile = refreshTsgoCheckerConfig(
|
|
131
|
+
this.options.configFile,
|
|
132
|
+
);
|
|
133
|
+
if (projectConfigFile) {
|
|
134
|
+
const watched = watchDependencyPath(projectConfigFile);
|
|
135
|
+
compilation.fileDependencies.add(watched);
|
|
136
|
+
// Absent mid-edit: a missing dependency makes its (re)appearance
|
|
137
|
+
// a rebuild trigger, so the dev server recovers on its own.
|
|
138
|
+
if (!existsSync(projectConfigFile)) {
|
|
139
|
+
compilation.missingDependencies.add(watched);
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
const { inputs, missing } = await this.watchInputs();
|
|
143
|
+
for (const file of inputs)
|
|
144
|
+
compilation.fileDependencies.add(watchDependencyPath(file));
|
|
145
|
+
for (const file of missing)
|
|
146
|
+
compilation.missingDependencies.add(watchDependencyPath(file));
|
|
147
|
+
await this.check();
|
|
148
|
+
} catch (cause) {
|
|
149
|
+
compilation.errors.push(
|
|
150
|
+
new Error(cause instanceof Error ? cause.message : String(cause), {
|
|
151
|
+
cause,
|
|
152
|
+
}),
|
|
153
|
+
);
|
|
154
|
+
}
|
|
155
|
+
});
|
|
156
|
+
});
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
/** Preserve project-reference emit contracts in the native Effect compiler. */
|
|
161
|
+
export function configureUltramodernTypeChecker(
|
|
162
|
+
chain: RspackChain,
|
|
163
|
+
pluginId: string,
|
|
164
|
+
resolveCompiler: (configFile: string) => string,
|
|
165
|
+
): void {
|
|
166
|
+
if (!chain.plugins.has(pluginId)) return;
|
|
167
|
+
const options = chain.plugin(pluginId).get('args')?.[0] as
|
|
168
|
+
| { typescript?: { configFile?: string; build?: boolean; tsgo?: boolean } }
|
|
169
|
+
| undefined;
|
|
170
|
+
const typescript = options?.typescript;
|
|
171
|
+
if (typescript?.tsgo === false) return;
|
|
172
|
+
if (!typescript?.configFile) {
|
|
173
|
+
throw new Error(`${name} requires the configured TypeScript project.`);
|
|
174
|
+
}
|
|
175
|
+
const configFile = path.resolve(typescript.configFile);
|
|
176
|
+
chain.plugin(pluginId).use(UltramodernNativeTypeChecker, [
|
|
177
|
+
{
|
|
178
|
+
build: typescript.build === true,
|
|
179
|
+
compiler: () => resolveCompiler(configFile),
|
|
180
|
+
configFile,
|
|
181
|
+
},
|
|
182
|
+
]);
|
|
183
|
+
}
|
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
import {
|
|
2
|
+
collectRuntimePackageModuleDirectories,
|
|
3
|
+
createRuntimePackageResolutionPlugin,
|
|
4
|
+
} from './runtime-package-resolution';
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* The fork's renderer policy (head rendering, HTML template assembly and asset
|
|
8
|
+
* ordering) and server policy (localised loaders, error responses, telemetry,
|
|
9
|
+
* module-federation CSS and asset cache headers, static serving) are the
|
|
10
|
+
* default behaviour of an UltraModern.js app.
|
|
11
|
+
*
|
|
12
|
+
* They live in their own packages so they can also be composed explicitly, but
|
|
13
|
+
* a plain `appTools()` app gets them without opting in — that is what this fork
|
|
14
|
+
* has always done. Pass `appTools({ rendererExtensions: false })` or
|
|
15
|
+
* `appTools({ serverExtensions: false })` to run without them.
|
|
16
|
+
*/
|
|
17
|
+
export const RENDERER_EXTENSIONS_PACKAGE =
|
|
18
|
+
'@modern-js/runtime-renderer-extensions';
|
|
19
|
+
|
|
20
|
+
export const RENDERER_EXTENSIONS_PLUGIN_NAME = 'rendererHead';
|
|
21
|
+
|
|
22
|
+
export const SERVER_EXTENSIONS_PLUGIN_NAME =
|
|
23
|
+
'@modern-js/app-tools/server-plugin';
|
|
24
|
+
|
|
25
|
+
export interface PolicyDefaultsOptions {
|
|
26
|
+
/** Default `true`. Set to `false` to drop the fork's renderer policy. */
|
|
27
|
+
rendererExtensions?: boolean;
|
|
28
|
+
/** Default `true`. Set to `false` to drop the fork's server policy. */
|
|
29
|
+
serverExtensions?: boolean;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
type RuntimePluginDescriptor = {
|
|
33
|
+
name?: string;
|
|
34
|
+
path: string;
|
|
35
|
+
config?: unknown;
|
|
36
|
+
};
|
|
37
|
+
|
|
38
|
+
type ServerPluginDescriptor = { name: string };
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* The subset of the CLI plugin API these defaults use. Typed structurally, and
|
|
42
|
+
* loosely at the hook boundary, so this package stays free of a dependency on
|
|
43
|
+
* the solution that consumes it — which depends on this one.
|
|
44
|
+
*/
|
|
45
|
+
export interface PolicyDefaultsPluginApi {
|
|
46
|
+
_internalRuntimePlugins(fn: (input: any) => any): void;
|
|
47
|
+
_internalServerPlugins(fn: (input: any) => any): void;
|
|
48
|
+
modifyResolvedConfig(fn: (config: any) => any): void;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
type RuntimePluginsInput = {
|
|
52
|
+
entrypoint: unknown;
|
|
53
|
+
plugins: RuntimePluginDescriptor[];
|
|
54
|
+
};
|
|
55
|
+
|
|
56
|
+
type ServerPluginsInput = { plugins: ServerPluginDescriptor[] };
|
|
57
|
+
|
|
58
|
+
export const POLICY_DEFAULTS_PLUGIN_NAME =
|
|
59
|
+
'@modern-js/ultramodern-policy-defaults';
|
|
60
|
+
|
|
61
|
+
/** Registers the fork's default renderer and server policy. */
|
|
62
|
+
export const applyPolicyDefaults = (
|
|
63
|
+
api: PolicyDefaultsPluginApi,
|
|
64
|
+
options: PolicyDefaultsOptions = {},
|
|
65
|
+
): void => {
|
|
66
|
+
if (options.rendererExtensions !== false) {
|
|
67
|
+
api._internalRuntimePlugins(
|
|
68
|
+
({ entrypoint, plugins }: RuntimePluginsInput) => {
|
|
69
|
+
// An explicit composition (`ultramodernAppTools()`) may already have
|
|
70
|
+
// registered it; the descriptor list must stay free of duplicates.
|
|
71
|
+
if (
|
|
72
|
+
!plugins.some(plugin => plugin.path === RENDERER_EXTENSIONS_PACKAGE)
|
|
73
|
+
) {
|
|
74
|
+
plugins.push({
|
|
75
|
+
name: RENDERER_EXTENSIONS_PLUGIN_NAME,
|
|
76
|
+
path: RENDERER_EXTENSIONS_PACKAGE,
|
|
77
|
+
config: {},
|
|
78
|
+
});
|
|
79
|
+
}
|
|
80
|
+
return { entrypoint, plugins };
|
|
81
|
+
},
|
|
82
|
+
);
|
|
83
|
+
|
|
84
|
+
const moduleDirectories = collectRuntimePackageModuleDirectories(
|
|
85
|
+
[RENDERER_EXTENSIONS_PACKAGE],
|
|
86
|
+
import.meta.url,
|
|
87
|
+
);
|
|
88
|
+
if (moduleDirectories.length > 0) {
|
|
89
|
+
api.modifyResolvedConfig(config => ({
|
|
90
|
+
...config,
|
|
91
|
+
builderPlugins: [
|
|
92
|
+
...(config.builderPlugins ?? []),
|
|
93
|
+
createRuntimePackageResolutionPlugin(moduleDirectories),
|
|
94
|
+
],
|
|
95
|
+
}));
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
if (options.serverExtensions !== false) {
|
|
100
|
+
api._internalServerPlugins(({ plugins }: ServerPluginsInput) => {
|
|
101
|
+
if (
|
|
102
|
+
!plugins.some(plugin => plugin.name === SERVER_EXTENSIONS_PLUGIN_NAME)
|
|
103
|
+
) {
|
|
104
|
+
plugins.push({ name: SERVER_EXTENSIONS_PLUGIN_NAME });
|
|
105
|
+
}
|
|
106
|
+
return { plugins };
|
|
107
|
+
});
|
|
108
|
+
}
|
|
109
|
+
};
|
|
110
|
+
|
|
111
|
+
/**
|
|
112
|
+
* The fork defaults as a CLI plugin.
|
|
113
|
+
*
|
|
114
|
+
* The descriptor this registers may land before the ones it wraps — CLI
|
|
115
|
+
* ordering cannot be constrained here without a cycle, because the plugins
|
|
116
|
+
* that emit those descriptors are themselves ordered after `appTools()`.
|
|
117
|
+
* Ordering is settled on the runtime side instead: `rendererHeadPlugin`
|
|
118
|
+
* declares the runtime plugins that run before it.
|
|
119
|
+
*/
|
|
120
|
+
export const createPolicyDefaultsPlugin = (
|
|
121
|
+
options: PolicyDefaultsOptions = {},
|
|
122
|
+
) => ({
|
|
123
|
+
name: POLICY_DEFAULTS_PLUGIN_NAME,
|
|
124
|
+
setup(api: PolicyDefaultsPluginApi) {
|
|
125
|
+
applyPolicyDefaults(api, options);
|
|
126
|
+
},
|
|
127
|
+
});
|