@bleedingdev/modern-js-create 3.5.0-ultramodern.3 → 3.5.0-ultramodern.30
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 +21 -17
- package/dist/cjs/ultramodern-tooling/commands.cjs +772 -75
- package/dist/cjs/ultramodern-tooling/config.cjs +149 -8
- package/dist/cjs/ultramodern-workspace/add-vertical.cjs +25 -0
- package/dist/cjs/ultramodern-workspace/api.cjs +44 -0
- package/dist/cjs/ultramodern-workspace/app-files.cjs +8 -11
- package/dist/cjs/ultramodern-workspace/backend-federation.cjs +282 -0
- package/dist/cjs/ultramodern-workspace/contracts.cjs +24 -8
- package/dist/cjs/ultramodern-workspace/delivery-unit-sync.cjs +157 -0
- package/dist/cjs/ultramodern-workspace/delivery-unit.cjs +88 -0
- package/dist/cjs/ultramodern-workspace/descriptors.cjs +24 -0
- package/dist/cjs/ultramodern-workspace/module-federation.cjs +161 -50
- package/dist/cjs/ultramodern-workspace/package-json.cjs +26 -43
- package/dist/cjs/ultramodern-workspace/pnpm-workspace-policy-plan.cjs +166 -0
- package/dist/cjs/ultramodern-workspace/tooling-command-catalog.cjs +153 -0
- package/dist/cjs/ultramodern-workspace/versions.cjs +8 -3
- package/dist/cjs/ultramodern-workspace/workspace-script-plan.cjs +175 -0
- package/dist/cjs/ultramodern-workspace/workspace-scripts.cjs +104 -63
- package/dist/cjs/ultramodern-workspace/workspace-validation-contract.cjs +97 -0
- package/dist/cjs/ultramodern-workspace/write-workspace.cjs +11 -3
- package/dist/cjs/ultramodern-workspace/zerops.cjs +100 -0
- package/dist/esm/ultramodern-tooling/commands.js +775 -78
- package/dist/esm/ultramodern-tooling/config.js +144 -9
- package/dist/esm/ultramodern-workspace/add-vertical.js +26 -1
- package/dist/esm/ultramodern-workspace/api.js +43 -2
- package/dist/esm/ultramodern-workspace/app-files.js +8 -11
- package/dist/esm/ultramodern-workspace/backend-federation.js +217 -0
- package/dist/esm/ultramodern-workspace/contracts.js +24 -8
- package/dist/esm/ultramodern-workspace/delivery-unit-sync.js +108 -0
- package/dist/esm/ultramodern-workspace/delivery-unit.js +31 -0
- package/dist/esm/ultramodern-workspace/descriptors.js +13 -1
- package/dist/esm/ultramodern-workspace/module-federation.js +160 -42
- package/dist/esm/ultramodern-workspace/package-json.js +16 -40
- package/dist/esm/ultramodern-workspace/pnpm-workspace-policy-plan.js +113 -0
- package/dist/esm/ultramodern-workspace/tooling-command-catalog.js +100 -0
- package/dist/esm/ultramodern-workspace/versions.js +6 -4
- package/dist/esm/ultramodern-workspace/workspace-script-plan.js +110 -0
- package/dist/esm/ultramodern-workspace/workspace-scripts.js +88 -65
- package/dist/esm/ultramodern-workspace/workspace-validation-contract.js +59 -0
- package/dist/esm/ultramodern-workspace/write-workspace.js +14 -6
- package/dist/esm/ultramodern-workspace/zerops.js +62 -0
- package/dist/esm-node/ultramodern-tooling/commands.js +775 -78
- package/dist/esm-node/ultramodern-tooling/config.js +144 -9
- package/dist/esm-node/ultramodern-workspace/add-vertical.js +26 -1
- package/dist/esm-node/ultramodern-workspace/api.js +43 -2
- package/dist/esm-node/ultramodern-workspace/app-files.js +8 -11
- package/dist/esm-node/ultramodern-workspace/backend-federation.js +218 -0
- package/dist/esm-node/ultramodern-workspace/contracts.js +24 -8
- package/dist/esm-node/ultramodern-workspace/delivery-unit-sync.js +109 -0
- package/dist/esm-node/ultramodern-workspace/delivery-unit.js +32 -0
- package/dist/esm-node/ultramodern-workspace/descriptors.js +13 -1
- package/dist/esm-node/ultramodern-workspace/module-federation.js +160 -42
- package/dist/esm-node/ultramodern-workspace/package-json.js +16 -40
- package/dist/esm-node/ultramodern-workspace/pnpm-workspace-policy-plan.js +114 -0
- package/dist/esm-node/ultramodern-workspace/tooling-command-catalog.js +101 -0
- package/dist/esm-node/ultramodern-workspace/versions.js +6 -4
- package/dist/esm-node/ultramodern-workspace/workspace-script-plan.js +111 -0
- package/dist/esm-node/ultramodern-workspace/workspace-scripts.js +88 -65
- package/dist/esm-node/ultramodern-workspace/workspace-validation-contract.js +60 -0
- package/dist/esm-node/ultramodern-workspace/write-workspace.js +14 -6
- package/dist/esm-node/ultramodern-workspace/zerops.js +63 -0
- package/dist/types/ultramodern-tooling/config.d.ts +6 -0
- package/dist/types/ultramodern-workspace/api.d.ts +1 -0
- package/dist/types/ultramodern-workspace/backend-federation.d.ts +11 -0
- package/dist/types/ultramodern-workspace/contracts.d.ts +1 -1
- package/dist/types/ultramodern-workspace/delivery-unit-sync.d.ts +6 -0
- package/dist/types/ultramodern-workspace/delivery-unit.d.ts +27 -0
- package/dist/types/ultramodern-workspace/descriptors.d.ts +4 -0
- package/dist/types/ultramodern-workspace/module-federation.d.ts +4 -9
- package/dist/types/ultramodern-workspace/package-json.d.ts +0 -1
- package/dist/types/ultramodern-workspace/pnpm-workspace-policy-plan.d.ts +39 -0
- package/dist/types/ultramodern-workspace/tooling-command-catalog.d.ts +18 -0
- package/dist/types/ultramodern-workspace/versions.d.ts +5 -3
- package/dist/types/ultramodern-workspace/workspace-script-plan.d.ts +72 -0
- package/dist/types/ultramodern-workspace/workspace-scripts.d.ts +13 -0
- package/dist/types/ultramodern-workspace/workspace-validation-contract.d.ts +42 -0
- package/dist/types/ultramodern-workspace/zerops.d.ts +2 -0
- package/package.json +3 -3
- package/template-workspace/.gitignore.handlebars +4 -0
- package/template-workspace/README.md.handlebars +18 -15
- package/template-workspace/patches/@module-federation__bridge-react@2.6.0.patch +140 -0
- package/template-workspace/patches/@module-federation__modern-js-v3@2.6.0.patch +57 -0
- package/template-workspace/patches/drizzle-orm-ts7-strict-declarations.patch +452 -0
- package/template-workspace/patches/effect-schema-error-type-id.patch +18 -0
- package/template-workspace/pnpm-workspace.yaml.handlebars +8 -0
- package/template-workspace/scripts/bootstrap-agent-skills.mjs +11 -3
- package/templates/workspace-scripts/check-ultramodern-api-boundaries.mts +40 -2
- package/templates/workspace-scripts/generate-node-backend-federation.mjs +270 -0
- package/templates/workspace-scripts/materialize-zerops-runtime.mjs +448 -0
- package/templates/workspace-scripts/proof-cloudflare-version.mjs +237 -9
- package/templates/workspace-scripts/proof-node-backend-federation.mjs +729 -0
- package/templates/workspace-scripts/ultramodern-cloudflare-proof.mjs +188 -2
- package/templates/workspace-scripts/validate-ultramodern-workspace.mjs.handlebars +434 -18
|
@@ -20,8 +20,8 @@ function resolveModuleFederationPublicPath(publicPath, manifestUrl) {
|
|
|
20
20
|
}
|
|
21
21
|
}
|
|
22
22
|
|
|
23
|
-
async function fetchText(url) {
|
|
24
|
-
const response = await fetch(url);
|
|
23
|
+
async function fetchText(url, init) {
|
|
24
|
+
const response = await fetch(url, init);
|
|
25
25
|
return {
|
|
26
26
|
ok: response.ok,
|
|
27
27
|
status: response.status,
|
|
@@ -48,6 +48,52 @@ function parseMaybeJson(body) {
|
|
|
48
48
|
}
|
|
49
49
|
}
|
|
50
50
|
|
|
51
|
+
function jsonPathValue(value, path) {
|
|
52
|
+
const segments = String(path ?? '')
|
|
53
|
+
.split('.')
|
|
54
|
+
.filter(Boolean);
|
|
55
|
+
let current = value;
|
|
56
|
+
|
|
57
|
+
for (const segment of segments) {
|
|
58
|
+
if (current === null || current === undefined) {
|
|
59
|
+
return undefined;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
if (Array.isArray(current) && /^\d+$/u.test(segment)) {
|
|
63
|
+
current = current[Number(segment)];
|
|
64
|
+
continue;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
if (typeof current === 'object' && Object.hasOwn(current, segment)) {
|
|
68
|
+
current = current[segment];
|
|
69
|
+
continue;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
return undefined;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
return current;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
function jsonValuesEqual(left, right) {
|
|
79
|
+
return JSON.stringify(left) === JSON.stringify(right);
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
function normalizeJsonSmokeExpectations(check) {
|
|
83
|
+
if (Array.isArray(check.expectations)) {
|
|
84
|
+
return check.expectations;
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
if (check.expect && typeof check.expect === 'object') {
|
|
88
|
+
return Object.entries(check.expect).map(([path, equals]) => ({
|
|
89
|
+
path,
|
|
90
|
+
equals,
|
|
91
|
+
}));
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
return [];
|
|
95
|
+
}
|
|
96
|
+
|
|
51
97
|
function markerFromJson(value) {
|
|
52
98
|
if (!value || typeof value !== 'object') {
|
|
53
99
|
return undefined;
|
|
@@ -687,6 +733,27 @@ function validateUiMarkerEvidence(evidence, app, ssr) {
|
|
|
687
733
|
status: uiMarker === app.marker?.build ? 'pass' : 'fail',
|
|
688
734
|
});
|
|
689
735
|
assert(uiMarker === app.marker?.build, `${app.id} UI marker mismatch`);
|
|
736
|
+
|
|
737
|
+
if (app.deliveryUnit) {
|
|
738
|
+
evidence.assertions.push({
|
|
739
|
+
type: 'delivery-unit-ui-marker',
|
|
740
|
+
unitId: app.deliveryUnit.unitId,
|
|
741
|
+
expected: app.deliveryUnit.surfaces?.ui?.buildMarker ?? app.deliveryUnit.buildMarker,
|
|
742
|
+
actual: uiMarker,
|
|
743
|
+
status:
|
|
744
|
+
uiMarker === (app.deliveryUnit.surfaces?.ui?.buildMarker ?? app.deliveryUnit.buildMarker)
|
|
745
|
+
? 'pass'
|
|
746
|
+
: 'fail',
|
|
747
|
+
});
|
|
748
|
+
assert(
|
|
749
|
+
uiMarker !== undefined,
|
|
750
|
+
`${app.id} delivery unit ${app.deliveryUnit.unitId} is declared but SSR response is missing its build marker`,
|
|
751
|
+
);
|
|
752
|
+
assert(
|
|
753
|
+
uiMarker === (app.deliveryUnit.surfaces?.ui?.buildMarker ?? app.deliveryUnit.buildMarker),
|
|
754
|
+
`${app.id} delivery unit ${app.deliveryUnit.unitId} UI surface build marker mismatch`,
|
|
755
|
+
);
|
|
756
|
+
}
|
|
690
757
|
}
|
|
691
758
|
|
|
692
759
|
function validateCssRootMarkerEvidence(evidence, app, ssr) {
|
|
@@ -857,6 +924,123 @@ async function validateReadinessEvidence(evidence, app, publicUrl, routes) {
|
|
|
857
924
|
`${app.id} Effect readiness returned HTTP ${readiness.status}`,
|
|
858
925
|
);
|
|
859
926
|
assert(apiMarker === app.marker?.build, `${app.id} API marker mismatch`);
|
|
927
|
+
|
|
928
|
+
if (app.deliveryUnit) {
|
|
929
|
+
evidence.assertions.push({
|
|
930
|
+
type: 'delivery-unit-api-marker',
|
|
931
|
+
route: routes.apiReadiness,
|
|
932
|
+
unitId: app.deliveryUnit.unitId,
|
|
933
|
+
expected: app.deliveryUnit.buildMarker,
|
|
934
|
+
actual: apiMarker,
|
|
935
|
+
status: apiMarker === app.deliveryUnit.buildMarker ? 'pass' : 'fail',
|
|
936
|
+
});
|
|
937
|
+
assert(
|
|
938
|
+
apiMarker !== undefined,
|
|
939
|
+
`${app.id} delivery unit ${app.deliveryUnit.unitId} is declared but readiness response is missing its build marker`,
|
|
940
|
+
);
|
|
941
|
+
assert(
|
|
942
|
+
apiMarker === app.deliveryUnit.buildMarker,
|
|
943
|
+
`${app.id} delivery unit ${app.deliveryUnit.unitId} API surface build marker mismatch`,
|
|
944
|
+
);
|
|
945
|
+
}
|
|
946
|
+
}
|
|
947
|
+
}
|
|
948
|
+
|
|
949
|
+
async function validateServiceBindingEvidence(evidence, app, publicUrl) {
|
|
950
|
+
const serviceBindings = app.deploy?.cloudflare?.serviceBindings ?? [];
|
|
951
|
+
|
|
952
|
+
for (const binding of serviceBindings) {
|
|
953
|
+
const response = await fetchText(joinUrl(publicUrl, binding.route));
|
|
954
|
+
const responseJson = parseMaybeJson(response.body);
|
|
955
|
+
const apiMarker = markerFromJson(responseJson);
|
|
956
|
+
const passed = response.ok && apiMarker === binding.expectedMarker;
|
|
957
|
+
|
|
958
|
+
evidence.assertions.push({
|
|
959
|
+
type: 'service-binding-api-marker',
|
|
960
|
+
appId: binding.appId,
|
|
961
|
+
binding: binding.binding,
|
|
962
|
+
route: binding.route,
|
|
963
|
+
expected: binding.expectedMarker,
|
|
964
|
+
actual: apiMarker,
|
|
965
|
+
status: passed ? 'pass' : 'fail',
|
|
966
|
+
statusCode: response.status,
|
|
967
|
+
});
|
|
968
|
+
assert(
|
|
969
|
+
response.ok,
|
|
970
|
+
`${app.id} service binding ${binding.binding} returned HTTP ${response.status}`,
|
|
971
|
+
);
|
|
972
|
+
assert(
|
|
973
|
+
apiMarker === binding.expectedMarker,
|
|
974
|
+
`${app.id} service binding ${binding.binding} API marker mismatch`,
|
|
975
|
+
);
|
|
976
|
+
}
|
|
977
|
+
}
|
|
978
|
+
|
|
979
|
+
async function validateJsonSmokeEvidence(evidence, app, publicUrl) {
|
|
980
|
+
const checks = app.deploy?.cloudflare?.jsonSmokeChecks ?? [];
|
|
981
|
+
|
|
982
|
+
for (const check of checks) {
|
|
983
|
+
const route = check.route;
|
|
984
|
+
assert(
|
|
985
|
+
typeof route === 'string' && route.length > 0,
|
|
986
|
+
`${app.id} JSON smoke check is missing a route`,
|
|
987
|
+
);
|
|
988
|
+
|
|
989
|
+
const method = String(check.method ?? 'GET').toUpperCase();
|
|
990
|
+
const requestBody =
|
|
991
|
+
check.body ?? check.payload ?? check.requestBody ?? undefined;
|
|
992
|
+
const response = await fetchText(joinUrl(publicUrl, route), {
|
|
993
|
+
method,
|
|
994
|
+
headers: {
|
|
995
|
+
accept: 'application/json',
|
|
996
|
+
...(requestBody === undefined
|
|
997
|
+
? {}
|
|
998
|
+
: { 'content-type': 'application/json' }),
|
|
999
|
+
},
|
|
1000
|
+
...(requestBody === undefined
|
|
1001
|
+
? {}
|
|
1002
|
+
: { body: JSON.stringify(requestBody) }),
|
|
1003
|
+
});
|
|
1004
|
+
const responseJson = parseMaybeJson(response.body);
|
|
1005
|
+
const checkId = check.id ?? route;
|
|
1006
|
+
|
|
1007
|
+
evidence.assertions.push({
|
|
1008
|
+
type: 'json-smoke-http',
|
|
1009
|
+
id: checkId,
|
|
1010
|
+
method,
|
|
1011
|
+
route,
|
|
1012
|
+
status: response.ok && responseJson !== undefined ? 'pass' : 'fail',
|
|
1013
|
+
statusCode: response.status,
|
|
1014
|
+
});
|
|
1015
|
+
assert(
|
|
1016
|
+
response.ok,
|
|
1017
|
+
`${app.id} JSON smoke ${checkId} returned HTTP ${response.status}`,
|
|
1018
|
+
);
|
|
1019
|
+
assert(
|
|
1020
|
+
responseJson !== undefined,
|
|
1021
|
+
`${app.id} JSON smoke ${checkId} did not return JSON`,
|
|
1022
|
+
);
|
|
1023
|
+
|
|
1024
|
+
for (const expectation of normalizeJsonSmokeExpectations(check)) {
|
|
1025
|
+
const actual = jsonPathValue(responseJson, expectation.path);
|
|
1026
|
+
const passed = jsonValuesEqual(actual, expectation.equals);
|
|
1027
|
+
|
|
1028
|
+
evidence.assertions.push({
|
|
1029
|
+
type: 'json-smoke-value',
|
|
1030
|
+
id: checkId,
|
|
1031
|
+
route,
|
|
1032
|
+
path: expectation.path,
|
|
1033
|
+
expected: expectation.equals,
|
|
1034
|
+
actual,
|
|
1035
|
+
status: passed ? 'pass' : 'fail',
|
|
1036
|
+
});
|
|
1037
|
+
assert(
|
|
1038
|
+
passed,
|
|
1039
|
+
`${app.id} JSON smoke ${checkId} expected ${expectation.path} to equal ${JSON.stringify(
|
|
1040
|
+
expectation.equals,
|
|
1041
|
+
)}`,
|
|
1042
|
+
);
|
|
1043
|
+
}
|
|
860
1044
|
}
|
|
861
1045
|
}
|
|
862
1046
|
|
|
@@ -869,6 +1053,8 @@ async function validateApp(app, publicUrl) {
|
|
|
869
1053
|
await validateModuleFederationManifestEvidence(evidence, app, publicUrl, routes);
|
|
870
1054
|
await validateI18nEvidence(evidence, app, publicUrl, routes);
|
|
871
1055
|
await validateReadinessEvidence(evidence, app, publicUrl, routes);
|
|
1056
|
+
await validateServiceBindingEvidence(evidence, app, publicUrl);
|
|
1057
|
+
await validateJsonSmokeEvidence(evidence, app, publicUrl);
|
|
872
1058
|
|
|
873
1059
|
return evidence;
|
|
874
1060
|
}
|