@bleedingdev/modern-js-app-tools-extensions 3.9.3-ultramodern.4 → 3.9.3-ultramodern.6
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/release-identity.js +1 -1
- package/dist/cjs/renderer-build-identity.js +12 -6
- package/dist/esm/release-identity.mjs +1 -1
- package/dist/esm/renderer-build-identity.mjs +12 -6
- package/dist/esm-node/release-identity.mjs +1 -1
- package/dist/esm-node/renderer-build-identity.mjs +12 -6
- package/dist/types/release-identity.d.ts +10 -0
- package/dist/types/renderer-build-identity.d.ts +12 -3
- package/package.json +16 -16
- package/src/release-identity.ts +11 -2
- package/src/renderer-build-identity.ts +46 -20
|
@@ -54,7 +54,7 @@ const gitOutput = (workspaceRoot, args)=>{
|
|
|
54
54
|
return;
|
|
55
55
|
}
|
|
56
56
|
};
|
|
57
|
-
const createUltramodernReleaseBuildMarker = ({ generationBuildMarker, sourceRevision, unitId })=>(0, external_node_crypto_namespaceObject.createHash)('sha256').update(`${BUILD_MARKER_NAMESPACE}:${unitId}:${generationBuildMarker}:${sourceRevision}`).digest('hex')
|
|
57
|
+
const createUltramodernReleaseBuildMarker = ({ generationBuildMarker, sourceRevision, unitId })=>(0, external_node_crypto_namespaceObject.createHash)('sha256').update(`${BUILD_MARKER_NAMESPACE}:${unitId}:${generationBuildMarker}:${sourceRevision}`).digest('hex');
|
|
58
58
|
const resolveUltramodernSourceRevision = (workspaceRoot = process.cwd(), configuredSourceRevision, environment = process.env)=>{
|
|
59
59
|
const configuredArgumentValue = configuredSourceRevision?.trim();
|
|
60
60
|
const configuredEnvironmentValue = environment.ULTRAMODERN_SOURCE_REVISION?.trim();
|
|
@@ -54,6 +54,7 @@ const LOCKFILES = [
|
|
|
54
54
|
'bun.lock',
|
|
55
55
|
'bun.lockb'
|
|
56
56
|
];
|
|
57
|
+
const RELEASE_BUILD_MARKER_PATTERN = /^[a-f0-9]{64}$/u;
|
|
57
58
|
const processNonce = (0, external_node_crypto_namespaceObject.randomUUID)();
|
|
58
59
|
const sha256 = (value)=>(0, external_node_crypto_namespaceObject.createHash)('sha256').update(value).digest('hex');
|
|
59
60
|
function rendererProfileKey(profile) {
|
|
@@ -98,16 +99,21 @@ function resolveRendererBuildIdentities(options) {
|
|
|
98
99
|
const projectRoot = external_node_path_default().resolve(options.projectRoot);
|
|
99
100
|
const appId = options.appId ?? JSON.parse(external_node_fs_default().readFileSync(external_node_path_default().join(projectRoot, 'package.json'), 'utf8')).name;
|
|
100
101
|
if ('string' != typeof appId || !appId || appId.trim() !== appId) throw new Error('Renderer application identity requires a delivery artifact appId or a package name.');
|
|
101
|
-
const
|
|
102
|
-
if (void 0 !==
|
|
102
|
+
const { deliveryUnit } = options;
|
|
103
|
+
if (void 0 !== deliveryUnit && ('string' != typeof deliveryUnit.unitId || !deliveryUnit.unitId || deliveryUnit.unitId.trim() !== deliveryUnit.unitId)) throw new Error('Renderer delivery-unit identity requires a nonempty trimmed unitId.');
|
|
103
104
|
const profileKey = rendererProfileKey(options.profile);
|
|
104
|
-
const sourceRevision = (0, external_release_identity_js_namespaceObject.resolveUltramodernSourceRevision)(projectRoot, options.sourceRevision);
|
|
105
|
-
const
|
|
105
|
+
const sourceRevision = (0, external_release_identity_js_namespaceObject.resolveUltramodernSourceRevision)(projectRoot, deliveryUnit ? deliveryUnit.sourceRevision : options.sourceRevision);
|
|
106
|
+
const promotable = 'production' === options.mode && 'workspace' !== sourceRevision;
|
|
107
|
+
let buildId;
|
|
108
|
+
if (promotable && deliveryUnit) {
|
|
109
|
+
if (deliveryUnit.sourceRevision !== sourceRevision || !RELEASE_BUILD_MARKER_PATTERN.test(deliveryUnit.buildMarker)) throw new Error(`Renderer delivery unit ${deliveryUnit.unitId} must carry the release identity of source revision ${sourceRevision}.`);
|
|
110
|
+
buildId = deliveryUnit.buildMarker;
|
|
111
|
+
} else buildId = sha256(JSON.stringify([
|
|
106
112
|
appId,
|
|
107
|
-
unitId ?? null,
|
|
113
|
+
deliveryUnit?.unitId ?? null,
|
|
108
114
|
profileKey,
|
|
109
115
|
lockfileHash(projectRoot),
|
|
110
|
-
|
|
116
|
+
promotable ? sourceRevision : processNonce
|
|
111
117
|
]));
|
|
112
118
|
const identities = Object.fromEntries(entries.map((entryName)=>[
|
|
113
119
|
entryName,
|
|
@@ -20,7 +20,7 @@ const gitOutput = (workspaceRoot, args)=>{
|
|
|
20
20
|
return;
|
|
21
21
|
}
|
|
22
22
|
};
|
|
23
|
-
const createUltramodernReleaseBuildMarker = ({ generationBuildMarker, sourceRevision, unitId })=>createHash('sha256').update(`${BUILD_MARKER_NAMESPACE}:${unitId}:${generationBuildMarker}:${sourceRevision}`).digest('hex')
|
|
23
|
+
const createUltramodernReleaseBuildMarker = ({ generationBuildMarker, sourceRevision, unitId })=>createHash('sha256').update(`${BUILD_MARKER_NAMESPACE}:${unitId}:${generationBuildMarker}:${sourceRevision}`).digest('hex');
|
|
24
24
|
const resolveUltramodernSourceRevision = (workspaceRoot = process.cwd(), configuredSourceRevision, environment = process.env)=>{
|
|
25
25
|
const configuredArgumentValue = configuredSourceRevision?.trim();
|
|
26
26
|
const configuredEnvironmentValue = environment.ULTRAMODERN_SOURCE_REVISION?.trim();
|
|
@@ -10,6 +10,7 @@ const LOCKFILES = [
|
|
|
10
10
|
'bun.lock',
|
|
11
11
|
'bun.lockb'
|
|
12
12
|
];
|
|
13
|
+
const RELEASE_BUILD_MARKER_PATTERN = /^[a-f0-9]{64}$/u;
|
|
13
14
|
const processNonce = randomUUID();
|
|
14
15
|
const sha256 = (value)=>createHash('sha256').update(value).digest('hex');
|
|
15
16
|
function rendererProfileKey(profile) {
|
|
@@ -54,16 +55,21 @@ function resolveRendererBuildIdentities(options) {
|
|
|
54
55
|
const projectRoot = node_path.resolve(options.projectRoot);
|
|
55
56
|
const appId = options.appId ?? JSON.parse(node_fs.readFileSync(node_path.join(projectRoot, 'package.json'), 'utf8')).name;
|
|
56
57
|
if ('string' != typeof appId || !appId || appId.trim() !== appId) throw new Error('Renderer application identity requires a delivery artifact appId or a package name.');
|
|
57
|
-
const
|
|
58
|
-
if (void 0 !==
|
|
58
|
+
const { deliveryUnit } = options;
|
|
59
|
+
if (void 0 !== deliveryUnit && ('string' != typeof deliveryUnit.unitId || !deliveryUnit.unitId || deliveryUnit.unitId.trim() !== deliveryUnit.unitId)) throw new Error('Renderer delivery-unit identity requires a nonempty trimmed unitId.');
|
|
59
60
|
const profileKey = rendererProfileKey(options.profile);
|
|
60
|
-
const sourceRevision = resolveUltramodernSourceRevision(projectRoot, options.sourceRevision);
|
|
61
|
-
const
|
|
61
|
+
const sourceRevision = resolveUltramodernSourceRevision(projectRoot, deliveryUnit ? deliveryUnit.sourceRevision : options.sourceRevision);
|
|
62
|
+
const promotable = 'production' === options.mode && 'workspace' !== sourceRevision;
|
|
63
|
+
let buildId;
|
|
64
|
+
if (promotable && deliveryUnit) {
|
|
65
|
+
if (deliveryUnit.sourceRevision !== sourceRevision || !RELEASE_BUILD_MARKER_PATTERN.test(deliveryUnit.buildMarker)) throw new Error(`Renderer delivery unit ${deliveryUnit.unitId} must carry the release identity of source revision ${sourceRevision}.`);
|
|
66
|
+
buildId = deliveryUnit.buildMarker;
|
|
67
|
+
} else buildId = sha256(JSON.stringify([
|
|
62
68
|
appId,
|
|
63
|
-
unitId ?? null,
|
|
69
|
+
deliveryUnit?.unitId ?? null,
|
|
64
70
|
profileKey,
|
|
65
71
|
lockfileHash(projectRoot),
|
|
66
|
-
|
|
72
|
+
promotable ? sourceRevision : processNonce
|
|
67
73
|
]));
|
|
68
74
|
const identities = Object.fromEntries(entries.map((entryName)=>[
|
|
69
75
|
entryName,
|
|
@@ -21,7 +21,7 @@ const gitOutput = (workspaceRoot, args)=>{
|
|
|
21
21
|
return;
|
|
22
22
|
}
|
|
23
23
|
};
|
|
24
|
-
const createUltramodernReleaseBuildMarker = ({ generationBuildMarker, sourceRevision, unitId })=>createHash('sha256').update(`${BUILD_MARKER_NAMESPACE}:${unitId}:${generationBuildMarker}:${sourceRevision}`).digest('hex')
|
|
24
|
+
const createUltramodernReleaseBuildMarker = ({ generationBuildMarker, sourceRevision, unitId })=>createHash('sha256').update(`${BUILD_MARKER_NAMESPACE}:${unitId}:${generationBuildMarker}:${sourceRevision}`).digest('hex');
|
|
25
25
|
const resolveUltramodernSourceRevision = (workspaceRoot = process.cwd(), configuredSourceRevision, environment = process.env)=>{
|
|
26
26
|
const configuredArgumentValue = configuredSourceRevision?.trim();
|
|
27
27
|
const configuredEnvironmentValue = environment.ULTRAMODERN_SOURCE_REVISION?.trim();
|
|
@@ -11,6 +11,7 @@ const LOCKFILES = [
|
|
|
11
11
|
'bun.lock',
|
|
12
12
|
'bun.lockb'
|
|
13
13
|
];
|
|
14
|
+
const RELEASE_BUILD_MARKER_PATTERN = /^[a-f0-9]{64}$/u;
|
|
14
15
|
const processNonce = randomUUID();
|
|
15
16
|
const sha256 = (value)=>createHash('sha256').update(value).digest('hex');
|
|
16
17
|
function rendererProfileKey(profile) {
|
|
@@ -55,16 +56,21 @@ function resolveRendererBuildIdentities(options) {
|
|
|
55
56
|
const projectRoot = node_path.resolve(options.projectRoot);
|
|
56
57
|
const appId = options.appId ?? JSON.parse(node_fs.readFileSync(node_path.join(projectRoot, 'package.json'), 'utf8')).name;
|
|
57
58
|
if ('string' != typeof appId || !appId || appId.trim() !== appId) throw new Error('Renderer application identity requires a delivery artifact appId or a package name.');
|
|
58
|
-
const
|
|
59
|
-
if (void 0 !==
|
|
59
|
+
const { deliveryUnit } = options;
|
|
60
|
+
if (void 0 !== deliveryUnit && ('string' != typeof deliveryUnit.unitId || !deliveryUnit.unitId || deliveryUnit.unitId.trim() !== deliveryUnit.unitId)) throw new Error('Renderer delivery-unit identity requires a nonempty trimmed unitId.');
|
|
60
61
|
const profileKey = rendererProfileKey(options.profile);
|
|
61
|
-
const sourceRevision = resolveUltramodernSourceRevision(projectRoot, options.sourceRevision);
|
|
62
|
-
const
|
|
62
|
+
const sourceRevision = resolveUltramodernSourceRevision(projectRoot, deliveryUnit ? deliveryUnit.sourceRevision : options.sourceRevision);
|
|
63
|
+
const promotable = 'production' === options.mode && 'workspace' !== sourceRevision;
|
|
64
|
+
let buildId;
|
|
65
|
+
if (promotable && deliveryUnit) {
|
|
66
|
+
if (deliveryUnit.sourceRevision !== sourceRevision || !RELEASE_BUILD_MARKER_PATTERN.test(deliveryUnit.buildMarker)) throw new Error(`Renderer delivery unit ${deliveryUnit.unitId} must carry the release identity of source revision ${sourceRevision}.`);
|
|
67
|
+
buildId = deliveryUnit.buildMarker;
|
|
68
|
+
} else buildId = sha256(JSON.stringify([
|
|
63
69
|
appId,
|
|
64
|
-
unitId ?? null,
|
|
70
|
+
deliveryUnit?.unitId ?? null,
|
|
65
71
|
profileKey,
|
|
66
72
|
lockfileHash(projectRoot),
|
|
67
|
-
|
|
73
|
+
promotable ? sourceRevision : processNonce
|
|
68
74
|
]));
|
|
69
75
|
const identities = Object.fromEntries(entries.map((entryName)=>[
|
|
70
76
|
entryName,
|
|
@@ -8,6 +8,16 @@ export declare const createUltramodernReleaseBuildMarker: ({ generationBuildMark
|
|
|
8
8
|
unitId: string;
|
|
9
9
|
}) => string;
|
|
10
10
|
export declare const resolveUltramodernSourceRevision: (workspaceRoot?: string, configuredSourceRevision?: string, environment?: Readonly<NodeJS.ProcessEnv>) => string;
|
|
11
|
+
/**
|
|
12
|
+
* The one release identity of a delivery unit, resolvable before its build.
|
|
13
|
+
*
|
|
14
|
+
* For a clean source revision the build marker is a 64-hex digest of the unit
|
|
15
|
+
* id, its generation marker and the revision. API bundles carry it, and a UI
|
|
16
|
+
* unit's renderer adopts it as its `buildId`, so contracts, release plans and
|
|
17
|
+
* Worker names derived from it before the build match the built
|
|
18
|
+
* `ultramodern-build.json`, `renderer-build.json`, chunk banners and envelope.
|
|
19
|
+
* A dirty or non-Git checkout yields the non-promotable `workspace` identity.
|
|
20
|
+
*/
|
|
11
21
|
export declare const resolveUltramodernReleaseIdentity: ({ generationBuildMarker, sourceRevision: configuredSourceRevision, unitId, workspaceRoot, environment, }: {
|
|
12
22
|
generationBuildMarker: string;
|
|
13
23
|
sourceRevision?: string;
|
|
@@ -10,9 +10,18 @@ export interface RendererBuildIdentityOptions {
|
|
|
10
10
|
mode: 'development' | 'production';
|
|
11
11
|
/** Delivery-unit app id; defaults to the application package name. */
|
|
12
12
|
appId?: string;
|
|
13
|
-
/**
|
|
14
|
-
|
|
15
|
-
|
|
13
|
+
/**
|
|
14
|
+
* The declared delivery unit's release identity, resolved before the build
|
|
15
|
+
* by `resolveUltramodernReleaseIdentity`. A promotable production build
|
|
16
|
+
* adopts its buildMarker as the buildId, so consumers that resolve the unit
|
|
17
|
+
* identity before compiling see the marker the built artifacts carry.
|
|
18
|
+
*/
|
|
19
|
+
deliveryUnit?: {
|
|
20
|
+
readonly unitId: string;
|
|
21
|
+
readonly buildMarker: string;
|
|
22
|
+
readonly sourceRevision: string;
|
|
23
|
+
};
|
|
24
|
+
/** Externally authenticated source revision (CI) for an undeclared app. */
|
|
16
25
|
sourceRevision?: string;
|
|
17
26
|
/** Actual final entry ownership, supplied by the selected renderer composition. */
|
|
18
27
|
routerBindings: RendererRouterBindings;
|
package/package.json
CHANGED
|
@@ -11,7 +11,7 @@
|
|
|
11
11
|
"directory": "packages/solutions/app-tools-extensions"
|
|
12
12
|
},
|
|
13
13
|
"license": "MIT",
|
|
14
|
-
"version": "3.9.3-ultramodern.
|
|
14
|
+
"version": "3.9.3-ultramodern.6",
|
|
15
15
|
"files": [
|
|
16
16
|
"dist",
|
|
17
17
|
"src"
|
|
@@ -177,16 +177,16 @@
|
|
|
177
177
|
"dependencies": {
|
|
178
178
|
"@babel/parser": "^8.0.6",
|
|
179
179
|
"@babel/traverse": "^8.0.6",
|
|
180
|
-
"@modern-js/backend-federation-contracts": "npm:@bleedingdev/modern-js-backend-federation-contracts@3.9.3-ultramodern.
|
|
181
|
-
"@modern-js/builder": "npm:@bleedingdev/modern-js-builder@3.9.3-ultramodern.
|
|
182
|
-
"@modern-js/plugin": "npm:@bleedingdev/modern-js-plugin@3.9.3-ultramodern.
|
|
183
|
-
"@modern-js/prod-server": "npm:@bleedingdev/modern-js-prod-server@3.9.3-ultramodern.
|
|
184
|
-
"@modern-js/runtime-utils": "npm:@bleedingdev/modern-js-runtime-utils@3.9.3-ultramodern.
|
|
185
|
-
"@modern-js/server-core": "npm:@bleedingdev/modern-js-server-core@3.9.3-ultramodern.
|
|
186
|
-
"@modern-js/server-runtime-extensions": "npm:@bleedingdev/modern-js-server-runtime-extensions@3.9.3-ultramodern.
|
|
187
|
-
"@modern-js/surface-resolution": "npm:@bleedingdev/modern-js-surface-resolution@3.9.3-ultramodern.
|
|
188
|
-
"@modern-js/types": "npm:@bleedingdev/modern-js-types@3.9.3-ultramodern.
|
|
189
|
-
"@modern-js/utils": "npm:@bleedingdev/modern-js-utils@3.9.3-ultramodern.
|
|
180
|
+
"@modern-js/backend-federation-contracts": "npm:@bleedingdev/modern-js-backend-federation-contracts@3.9.3-ultramodern.6",
|
|
181
|
+
"@modern-js/builder": "npm:@bleedingdev/modern-js-builder@3.9.3-ultramodern.6",
|
|
182
|
+
"@modern-js/plugin": "npm:@bleedingdev/modern-js-plugin@3.9.3-ultramodern.6",
|
|
183
|
+
"@modern-js/prod-server": "npm:@bleedingdev/modern-js-prod-server@3.9.3-ultramodern.6",
|
|
184
|
+
"@modern-js/runtime-utils": "npm:@bleedingdev/modern-js-runtime-utils@3.9.3-ultramodern.6",
|
|
185
|
+
"@modern-js/server-core": "npm:@bleedingdev/modern-js-server-core@3.9.3-ultramodern.6",
|
|
186
|
+
"@modern-js/server-runtime-extensions": "npm:@bleedingdev/modern-js-server-runtime-extensions@3.9.3-ultramodern.6",
|
|
187
|
+
"@modern-js/surface-resolution": "npm:@bleedingdev/modern-js-surface-resolution@3.9.3-ultramodern.6",
|
|
188
|
+
"@modern-js/types": "npm:@bleedingdev/modern-js-types@3.9.3-ultramodern.6",
|
|
189
|
+
"@modern-js/utils": "npm:@bleedingdev/modern-js-utils@3.9.3-ultramodern.6",
|
|
190
190
|
"@swc/helpers": "^0.5.23",
|
|
191
191
|
"@vercel/nft": "^1.11.0",
|
|
192
192
|
"compression-webpack-plugin": "^12.0.0",
|
|
@@ -196,7 +196,7 @@
|
|
|
196
196
|
},
|
|
197
197
|
"peerDependencies": {
|
|
198
198
|
"@loadable/component": "5.16.7",
|
|
199
|
-
"@modern-js/runtime-renderer-extensions": "3.9.3-ultramodern.
|
|
199
|
+
"@modern-js/runtime-renderer-extensions": "3.9.3-ultramodern.6",
|
|
200
200
|
"@rsbuild/core": "2.2.11",
|
|
201
201
|
"react": "^19.2.8"
|
|
202
202
|
},
|
|
@@ -213,10 +213,10 @@
|
|
|
213
213
|
},
|
|
214
214
|
"devDependencies": {
|
|
215
215
|
"@loadable/component": "5.16.7",
|
|
216
|
-
"@modern-js/bff-effect": "npm:@bleedingdev/modern-js-bff-effect@3.9.3-ultramodern.
|
|
217
|
-
"@modern-js/plugin-bff-extensions": "npm:@bleedingdev/modern-js-plugin-bff-extensions@3.9.3-ultramodern.
|
|
218
|
-
"@modern-js/plugin-data-loader": "npm:@bleedingdev/modern-js-plugin-data-loader@3.9.3-ultramodern.
|
|
219
|
-
"@modern-js/runtime-renderer-extensions": "npm:@bleedingdev/modern-js-runtime-renderer-extensions@3.9.3-ultramodern.
|
|
216
|
+
"@modern-js/bff-effect": "npm:@bleedingdev/modern-js-bff-effect@3.9.3-ultramodern.6",
|
|
217
|
+
"@modern-js/plugin-bff-extensions": "npm:@bleedingdev/modern-js-plugin-bff-extensions@3.9.3-ultramodern.6",
|
|
218
|
+
"@modern-js/plugin-data-loader": "npm:@bleedingdev/modern-js-plugin-data-loader@3.9.3-ultramodern.6",
|
|
219
|
+
"@modern-js/runtime-renderer-extensions": "npm:@bleedingdev/modern-js-runtime-renderer-extensions@3.9.3-ultramodern.6",
|
|
220
220
|
"@module-federation/modern-js-v3": "2.9.2",
|
|
221
221
|
"@module-federation/runtime-tools": "2.9.2",
|
|
222
222
|
"@rsbuild/core": "2.2.11",
|
package/src/release-identity.ts
CHANGED
|
@@ -51,8 +51,7 @@ export const createUltramodernReleaseBuildMarker = ({
|
|
|
51
51
|
.update(
|
|
52
52
|
`${BUILD_MARKER_NAMESPACE}:${unitId}:${generationBuildMarker}:${sourceRevision}`,
|
|
53
53
|
)
|
|
54
|
-
.digest('hex')
|
|
55
|
-
.slice(0, 16);
|
|
54
|
+
.digest('hex');
|
|
56
55
|
|
|
57
56
|
export const resolveUltramodernSourceRevision = (
|
|
58
57
|
workspaceRoot = process.cwd(),
|
|
@@ -119,6 +118,16 @@ export const resolveUltramodernSourceRevision = (
|
|
|
119
118
|
return revision;
|
|
120
119
|
};
|
|
121
120
|
|
|
121
|
+
/**
|
|
122
|
+
* The one release identity of a delivery unit, resolvable before its build.
|
|
123
|
+
*
|
|
124
|
+
* For a clean source revision the build marker is a 64-hex digest of the unit
|
|
125
|
+
* id, its generation marker and the revision. API bundles carry it, and a UI
|
|
126
|
+
* unit's renderer adopts it as its `buildId`, so contracts, release plans and
|
|
127
|
+
* Worker names derived from it before the build match the built
|
|
128
|
+
* `ultramodern-build.json`, `renderer-build.json`, chunk banners and envelope.
|
|
129
|
+
* A dirty or non-Git checkout yields the non-promotable `workspace` identity.
|
|
130
|
+
*/
|
|
122
131
|
export const resolveUltramodernReleaseIdentity = ({
|
|
123
132
|
generationBuildMarker,
|
|
124
133
|
sourceRevision: configuredSourceRevision,
|
|
@@ -25,9 +25,18 @@ export interface RendererBuildIdentityOptions {
|
|
|
25
25
|
mode: 'development' | 'production';
|
|
26
26
|
/** Delivery-unit app id; defaults to the application package name. */
|
|
27
27
|
appId?: string;
|
|
28
|
-
/**
|
|
29
|
-
|
|
30
|
-
|
|
28
|
+
/**
|
|
29
|
+
* The declared delivery unit's release identity, resolved before the build
|
|
30
|
+
* by `resolveUltramodernReleaseIdentity`. A promotable production build
|
|
31
|
+
* adopts its buildMarker as the buildId, so consumers that resolve the unit
|
|
32
|
+
* identity before compiling see the marker the built artifacts carry.
|
|
33
|
+
*/
|
|
34
|
+
deliveryUnit?: {
|
|
35
|
+
readonly unitId: string;
|
|
36
|
+
readonly buildMarker: string;
|
|
37
|
+
readonly sourceRevision: string;
|
|
38
|
+
};
|
|
39
|
+
/** Externally authenticated source revision (CI) for an undeclared app. */
|
|
31
40
|
sourceRevision?: string;
|
|
32
41
|
/** Actual final entry ownership, supplied by the selected renderer composition. */
|
|
33
42
|
routerBindings: RendererRouterBindings;
|
|
@@ -51,6 +60,8 @@ const LOCKFILES = [
|
|
|
51
60
|
'bun.lockb',
|
|
52
61
|
];
|
|
53
62
|
|
|
63
|
+
const RELEASE_BUILD_MARKER_PATTERN = /^[a-f0-9]{64}$/u;
|
|
64
|
+
|
|
54
65
|
/** Stable per process: one dev session or dirty build keeps one buildId. */
|
|
55
66
|
const processNonce = randomUUID();
|
|
56
67
|
|
|
@@ -134,10 +145,12 @@ export function resolveRendererBuildIdentities(
|
|
|
134
145
|
throw new Error(
|
|
135
146
|
'Renderer application identity requires a delivery artifact appId or a package name.',
|
|
136
147
|
);
|
|
137
|
-
const
|
|
148
|
+
const { deliveryUnit } = options;
|
|
138
149
|
if (
|
|
139
|
-
|
|
140
|
-
(typeof unitId !== 'string' ||
|
|
150
|
+
deliveryUnit !== undefined &&
|
|
151
|
+
(typeof deliveryUnit.unitId !== 'string' ||
|
|
152
|
+
!deliveryUnit.unitId ||
|
|
153
|
+
deliveryUnit.unitId.trim() !== deliveryUnit.unitId)
|
|
141
154
|
)
|
|
142
155
|
throw new Error(
|
|
143
156
|
'Renderer delivery-unit identity requires a nonempty trimmed unitId.',
|
|
@@ -145,21 +158,34 @@ export function resolveRendererBuildIdentities(
|
|
|
145
158
|
const profileKey = rendererProfileKey(options.profile);
|
|
146
159
|
const sourceRevision = resolveUltramodernSourceRevision(
|
|
147
160
|
projectRoot,
|
|
148
|
-
options.sourceRevision,
|
|
149
|
-
);
|
|
150
|
-
// The buildId is the delivery unit's buildMarker, so it must name the unit:
|
|
151
|
-
// every app of one workspace shares the revision, lockfile and profile.
|
|
152
|
-
const buildId = sha256(
|
|
153
|
-
JSON.stringify([
|
|
154
|
-
appId,
|
|
155
|
-
unitId ?? null,
|
|
156
|
-
profileKey,
|
|
157
|
-
lockfileHash(projectRoot),
|
|
158
|
-
options.mode === 'development' || sourceRevision === 'workspace'
|
|
159
|
-
? processNonce
|
|
160
|
-
: sourceRevision,
|
|
161
|
-
]),
|
|
161
|
+
deliveryUnit ? deliveryUnit.sourceRevision : options.sourceRevision,
|
|
162
162
|
);
|
|
163
|
+
const promotable =
|
|
164
|
+
options.mode === 'production' && sourceRevision !== 'workspace';
|
|
165
|
+
let buildId: string;
|
|
166
|
+
if (promotable && deliveryUnit) {
|
|
167
|
+
// One identity per delivery unit, known before compilation.
|
|
168
|
+
if (
|
|
169
|
+
deliveryUnit.sourceRevision !== sourceRevision ||
|
|
170
|
+
!RELEASE_BUILD_MARKER_PATTERN.test(deliveryUnit.buildMarker)
|
|
171
|
+
)
|
|
172
|
+
throw new Error(
|
|
173
|
+
`Renderer delivery unit ${deliveryUnit.unitId} must carry the release identity of source revision ${sourceRevision}.`,
|
|
174
|
+
);
|
|
175
|
+
buildId = deliveryUnit.buildMarker;
|
|
176
|
+
} else {
|
|
177
|
+
// Undeclared apps and non-promotable builds (development, dirty trees)
|
|
178
|
+
// keep a per-app id; non-promotable ids are unique per process.
|
|
179
|
+
buildId = sha256(
|
|
180
|
+
JSON.stringify([
|
|
181
|
+
appId,
|
|
182
|
+
deliveryUnit?.unitId ?? null,
|
|
183
|
+
profileKey,
|
|
184
|
+
lockfileHash(projectRoot),
|
|
185
|
+
promotable ? sourceRevision : processNonce,
|
|
186
|
+
]),
|
|
187
|
+
);
|
|
188
|
+
}
|
|
163
189
|
const identities = Object.fromEntries(
|
|
164
190
|
entries.map(entryName => [
|
|
165
191
|
entryName,
|