@mfeflow/contracts 0.5.0 → 0.6.0
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 +1 -1
- package/dist/docs.d.ts +7 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +19 -5
- package/dist/mfe-manifest.d.ts +1 -1
- package/dist/project.d.ts +6 -1
- package/dist/remote-budget.d.ts +4 -4
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
Part of [mfeflow](https://github.com/mfeflow/mfeflow), the React micro-frontend boilerplate and platform kit.
|
|
4
4
|
|
|
5
|
-
Types, validators and JSON Schemas for `
|
|
5
|
+
Types, validators and JSON Schemas for `mfeflow.app.json`, `mfeflow.json` and the remote registry. Pre-1.0: minor versions may change the API.
|
|
6
6
|
|
|
7
7
|
```sh
|
|
8
8
|
pnpm add @mfeflow/contracts
|
package/dist/docs.d.ts
CHANGED
|
@@ -2,7 +2,8 @@
|
|
|
2
2
|
export declare const DOCS_URL = "https://mfeflow.github.io/mfeflow";
|
|
3
3
|
/** Where the JSON Schemas are published, for `$schema` in editors. */
|
|
4
4
|
export declare const SCHEMA_URLS: {
|
|
5
|
-
|
|
5
|
+
/** `mfeflow.app.json`, the file in each app's folder. */
|
|
6
|
+
readonly mfe: "https://mfeflow.github.io/mfeflow/schema/mfeflow-app.json";
|
|
6
7
|
readonly project: "https://mfeflow.github.io/mfeflow/schema/mfeflow.json";
|
|
7
8
|
readonly feature: "https://mfeflow.github.io/mfeflow/schema/feature.json";
|
|
8
9
|
readonly registryEntry: "https://mfeflow.github.io/mfeflow/schema/registry-entry.json";
|
|
@@ -10,5 +11,10 @@ export declare const SCHEMA_URLS: {
|
|
|
10
11
|
readonly featureRegistryIndex: "https://mfeflow.github.io/mfeflow/schema/feature-registry-index.json";
|
|
11
12
|
};
|
|
12
13
|
export type SchemaName = keyof typeof SCHEMA_URLS;
|
|
14
|
+
/**
|
|
15
|
+
* Old schema URLs that still serve a schema, so `$schema` lines written before a rename keep
|
|
16
|
+
* resolving. Each maps to the schema now published at its `SCHEMA_URLS` address.
|
|
17
|
+
*/
|
|
18
|
+
export declare const SCHEMA_ALIASES: Readonly<Record<string, SchemaName>>;
|
|
13
19
|
/** The docs page for an error code such as `E102`. */
|
|
14
20
|
export declare function errorDocsUrl(code: string): string;
|
package/dist/index.d.ts
CHANGED
|
@@ -10,5 +10,5 @@ export { isFeatureRegistryIndex, isLoopbackHttp, isPrivateHost, isRegistryProtoc
|
|
|
10
10
|
export { FILE_HASH, PROJECT_REPOS, REGISTRY_HOST, REGISTRY_NAMESPACE, isMfeflowProject, validateMfeflowProject, type MfeflowProject, type ProjectBudget, type ProjectRegistry, } from './project.js';
|
|
11
11
|
export { COST_MODEL, judgeCost, round1, splitScripts, type CostLine, type CostModel, type CostSample, type CostVerdict, } from './cost-model.js';
|
|
12
12
|
export { FEATURE_CONDITION, FEATURE_NAME, isFeatureManifest, TRANSFORM_OPS, validateFeatureManifest, type AddBootStepOp, type AddEnvKeyOp, type AddImportOp, type AddRouteOp, type AddSharedOp, type AddWorkflowStepOp, type EnvValidator, type FeatureCondition, type FeatureDependency, type FeatureFile, type FeatureManifest, type FeatureMigration, type FeaturePrompt, type FeatureScript, type FeatureTarget, type Literal, type PromptValue, type TransformOp, type TransformOpName, type WorkflowStep, type WrapProviderOp, } from './feature.js';
|
|
13
|
-
export { DOCS_URL, SCHEMA_URLS, errorDocsUrl, type SchemaName } from './docs.js';
|
|
13
|
+
export { DOCS_URL, SCHEMA_ALIASES, SCHEMA_URLS, errorDocsUrl, type SchemaName } from './docs.js';
|
|
14
14
|
export { JSON_SCHEMAS } from './json-schema.js';
|
package/dist/index.js
CHANGED
|
@@ -349,7 +349,7 @@ function judgeRemoteInitial(bytes, budgetKb, model = COST_MODEL) {
|
|
|
349
349
|
totalKb,
|
|
350
350
|
limitKb: budgetKb,
|
|
351
351
|
pass: totalKb <= budgetKb,
|
|
352
|
-
source: '
|
|
352
|
+
source: 'mfeflow.app.json'
|
|
353
353
|
};
|
|
354
354
|
const kb = round1(bytes.entryBytes / remote_budget_KB);
|
|
355
355
|
return {
|
|
@@ -794,7 +794,7 @@ function validateMfeflowProject(value) {
|
|
|
794
794
|
});
|
|
795
795
|
if (void 0 !== port && !Number.isInteger(port)) c.add(`${at}.port`, 'must be a whole number');
|
|
796
796
|
}
|
|
797
|
-
if (0 === shells && 'remote' !== repo) c.add('apps', 'needs at least one shell');
|
|
797
|
+
if (0 === shells && 'remote' !== repo && 'platform' !== repo) c.add('apps', 'needs at least one shell');
|
|
798
798
|
}
|
|
799
799
|
const features = c.object(value, 'features', '');
|
|
800
800
|
if (features) for (const [name, feature] of Object.entries(features)){
|
|
@@ -815,6 +815,12 @@ function validateMfeflowProject(value) {
|
|
|
815
815
|
if (!isSafeRelativePath(file)) c.add(at, 'must be a relative path with forward slashes');
|
|
816
816
|
if ('string' != typeof hash || !FILE_HASH.test(hash)) c.add(at, 'must be a hash like "sha256-<64 hex characters>"');
|
|
817
817
|
}
|
|
818
|
+
const kept = c.object(value, 'kept', '', false);
|
|
819
|
+
if (kept) for (const [file, hash] of Object.entries(kept)){
|
|
820
|
+
const at = `kept.${file}`;
|
|
821
|
+
if (!isSafeRelativePath(file)) c.add(at, 'must be a relative path with forward slashes');
|
|
822
|
+
if ('string' != typeof hash || !FILE_HASH.test(hash)) c.add(at, 'must be a hash like "sha256-<64 hex characters>"');
|
|
823
|
+
}
|
|
818
824
|
const registries = c.object(value, 'registries', '', false);
|
|
819
825
|
if (registries) for (const [ns, url] of Object.entries(registries)){
|
|
820
826
|
const at = `registries.${ns}`;
|
|
@@ -1148,13 +1154,16 @@ function isFeatureManifest(value) {
|
|
|
1148
1154
|
}
|
|
1149
1155
|
const DOCS_URL = 'https://mfeflow.github.io/mfeflow';
|
|
1150
1156
|
const SCHEMA_URLS = {
|
|
1151
|
-
mfe: `${DOCS_URL}/schema/
|
|
1157
|
+
mfe: `${DOCS_URL}/schema/mfeflow-app.json`,
|
|
1152
1158
|
project: `${DOCS_URL}/schema/mfeflow.json`,
|
|
1153
1159
|
feature: `${DOCS_URL}/schema/feature.json`,
|
|
1154
1160
|
registryEntry: `${DOCS_URL}/schema/registry-entry.json`,
|
|
1155
1161
|
registryIndex: `${DOCS_URL}/schema/registry-index.json`,
|
|
1156
1162
|
featureRegistryIndex: `${DOCS_URL}/schema/feature-registry-index.json`
|
|
1157
1163
|
};
|
|
1164
|
+
const SCHEMA_ALIASES = {
|
|
1165
|
+
[`${DOCS_URL}/schema/mfe.json`]: 'mfe'
|
|
1166
|
+
};
|
|
1158
1167
|
function errorDocsUrl(code) {
|
|
1159
1168
|
return `${DOCS_URL}/errors/${code}`;
|
|
1160
1169
|
}
|
|
@@ -1394,7 +1403,7 @@ const json_schema_item = (properties, required)=>({
|
|
|
1394
1403
|
required
|
|
1395
1404
|
});
|
|
1396
1405
|
const JSON_SCHEMAS = {
|
|
1397
|
-
mfe: root('mfe', '
|
|
1406
|
+
mfe: root('mfe', 'mfeflow.app.json', {
|
|
1398
1407
|
properties: {
|
|
1399
1408
|
name: str(MFE_NAME),
|
|
1400
1409
|
owner: str(),
|
|
@@ -1510,6 +1519,11 @@ const JSON_SCHEMAS = {
|
|
|
1510
1519
|
propertyNames: relativePath,
|
|
1511
1520
|
additionalProperties: str(FILE_HASH)
|
|
1512
1521
|
},
|
|
1522
|
+
kept: {
|
|
1523
|
+
type: 'object',
|
|
1524
|
+
propertyNames: relativePath,
|
|
1525
|
+
additionalProperties: str(FILE_HASH)
|
|
1526
|
+
},
|
|
1513
1527
|
registries: {
|
|
1514
1528
|
type: 'object',
|
|
1515
1529
|
propertyNames: {
|
|
@@ -1759,4 +1773,4 @@ const JSON_SCHEMAS = {
|
|
|
1759
1773
|
})
|
|
1760
1774
|
};
|
|
1761
1775
|
export { EXPOSE, ROUTE, isRegistryIndexRemote, registryRemoteIssues } from "./entry.js";
|
|
1762
|
-
export { ANALYTICS_EVENT, COST_MODEL, DOCS_URL, EVENT_NAME, FEATURE_CONDITION, FEATURE_NAME, FILE_HASH, JSON_SCHEMAS, MAX_DESCRIPTION, MAX_INDEX_ITEMS, MFE_NAME, PROJECT_REPOS, REGISTRY_HOST, REGISTRY_ITEM_NAME, REGISTRY_NAMESPACE, ROUTE_OVERLAP, SCHEMA_URLS, TRANSFORM_OPS, assetsFromManifest, errorDocsUrl, injectIntoHead, isFeatureManifest, isFeatureRegistryIndex, isLoopbackHttp, isMfeManifest, isMfeflowProject, isPortableRelativePath, isPrivateHost, isRegistryEntry, isRegistryIndex, isRegistryProtocol, isSafeRelativePath, judgeCost, judgeRemoteInitial, primaryExpose, redactUrl, redactUrlsIn, registryIndexUrl, registryInjection, registryTemplateProblem, remoteDistFiles, round1, routesOverlap, splitScripts, validateFeatureManifest, validateFeatureRegistryIndex, validateMfeManifest, validateMfeflowProject, validateRegistryEntry, validateRegistryIndex };
|
|
1776
|
+
export { ANALYTICS_EVENT, COST_MODEL, DOCS_URL, EVENT_NAME, FEATURE_CONDITION, FEATURE_NAME, FILE_HASH, JSON_SCHEMAS, MAX_DESCRIPTION, MAX_INDEX_ITEMS, MFE_NAME, PROJECT_REPOS, REGISTRY_HOST, REGISTRY_ITEM_NAME, REGISTRY_NAMESPACE, ROUTE_OVERLAP, SCHEMA_ALIASES, SCHEMA_URLS, TRANSFORM_OPS, assetsFromManifest, errorDocsUrl, injectIntoHead, isFeatureManifest, isFeatureRegistryIndex, isLoopbackHttp, isMfeManifest, isMfeflowProject, isPortableRelativePath, isPrivateHost, isRegistryEntry, isRegistryIndex, isRegistryProtocol, isSafeRelativePath, judgeCost, judgeRemoteInitial, primaryExpose, redactUrl, redactUrlsIn, registryIndexUrl, registryInjection, registryTemplateProblem, remoteDistFiles, round1, routesOverlap, splitScripts, validateFeatureManifest, validateFeatureRegistryIndex, validateMfeManifest, validateMfeflowProject, validateRegistryEntry, validateRegistryIndex };
|
package/dist/mfe-manifest.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { EXPOSE, ROUTE } from './entry.js';
|
|
2
2
|
import { type Issue } from './validate.js';
|
|
3
3
|
export { EXPOSE, ROUTE };
|
|
4
|
-
/** `mfe.json
|
|
4
|
+
/** `mfeflow.app.json` (formerly `mfe.json`): who owns a micro-frontend and what it promises. */
|
|
5
5
|
export interface MfeManifest {
|
|
6
6
|
$schema?: string;
|
|
7
7
|
/** Module Federation name: lowercase letters, digits, `_`. */
|
package/dist/project.d.ts
CHANGED
|
@@ -5,7 +5,7 @@ export interface MfeflowProject {
|
|
|
5
5
|
version: 1;
|
|
6
6
|
/** Version of the CLI that last wrote this file. */
|
|
7
7
|
cli?: string;
|
|
8
|
-
/** Which repo this is in a multi-repo setup. Absent means a platform
|
|
8
|
+
/** Which repo this is in a multi-repo setup. Absent means a monorepo. A `platform` or `remote` repo may have no shell. */
|
|
9
9
|
repo?: 'platform' | 'shell' | 'remote';
|
|
10
10
|
topology: 'monorepo' | 'polyrepo' | 'hybrid';
|
|
11
11
|
packageManager: 'pnpm' | 'npm';
|
|
@@ -24,6 +24,11 @@ export interface MfeflowProject {
|
|
|
24
24
|
}>;
|
|
25
25
|
/** Hashes of copied files, so `upgrade` can tell when a file was edited. */
|
|
26
26
|
files?: Record<string, string>;
|
|
27
|
+
/**
|
|
28
|
+
* Files `upgrade --keep` left alone: the hash of the new version each one was kept against.
|
|
29
|
+
* While the new version is that one, the file stays quiet; when it changes, the file is raised again.
|
|
30
|
+
*/
|
|
31
|
+
kept?: Record<string, string>;
|
|
27
32
|
/** Third-party feature registries: `{ "@someone": "https://…/{name}.json" }`, https only (plain http for loopback hosts). `@mfeflow` is reserved. */
|
|
28
33
|
registries?: Record<string, string>;
|
|
29
34
|
/** Built mfeflow checkout, relative to the project root, that `@mfeflow/*` dependencies link to. Set by `--local` only. */
|
package/dist/remote-budget.d.ts
CHANGED
|
@@ -2,17 +2,17 @@ import { type CostModel } from './cost-model.js';
|
|
|
2
2
|
/** The expose a remote's route loads first: `./App`, else the first one. */
|
|
3
3
|
export declare function primaryExpose(names: readonly string[]): string | undefined;
|
|
4
4
|
export interface RemoteInitialVerdict {
|
|
5
|
-
/** Gzip KB that were judged, one decimal: the entry plus the primary expose, or the entry alone without an
|
|
5
|
+
/** Gzip KB that were judged, one decimal: the entry plus the primary expose, or the entry alone without an app file budget. */
|
|
6
6
|
kb: number;
|
|
7
7
|
/** Gzip KB of the entry plus the primary expose, whichever was judged. */
|
|
8
8
|
totalKb: number;
|
|
9
9
|
limitKb: number;
|
|
10
10
|
pass: boolean;
|
|
11
|
-
/** Where the limit came from: the remote's `
|
|
12
|
-
source: '
|
|
11
|
+
/** Where the limit came from: the remote's `mfeflow.app.json` budget or the cost model. */
|
|
12
|
+
source: 'mfeflow.app.json' | 'cost-model';
|
|
13
13
|
}
|
|
14
14
|
/**
|
|
15
|
-
* Judges the JS a remote loads first. With
|
|
15
|
+
* Judges the JS a remote loads first. With a `mfeflow.app.json` `budgets.initialJsKb` the entry plus the
|
|
16
16
|
* primary expose must fit it; without one the entry alone must fit the cost model's `remoteKb`.
|
|
17
17
|
*/
|
|
18
18
|
export declare function judgeRemoteInitial(bytes: {
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@mfeflow/contracts",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"description": "Types, validators and JSON Schemas for mfeflow:
|
|
3
|
+
"version": "0.6.0",
|
|
4
|
+
"description": "Types, validators and JSON Schemas for mfeflow: mfeflow.app.json ownership manifests, mfeflow.json project state, and the remote registry (entries and index).",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"micro-frontend",
|
|
7
7
|
"mfe",
|