@mfeflow/core 0.4.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/dist/adopt/detect.d.ts +11 -0
- package/dist/adopt/disk.d.ts +20 -0
- package/dist/adopt/evaluate.d.ts +70 -0
- package/dist/adopt/federation.d.ts +20 -0
- package/dist/adopt/index.d.ts +4 -0
- package/dist/adopt/plan.d.ts +39 -0
- package/dist/adopt/types.d.ts +73 -0
- package/dist/adopt/workspace.d.ts +16 -0
- package/dist/app-file.d.ts +20 -0
- package/dist/apply.d.ts +2 -0
- package/dist/errors.d.ts +96 -7
- package/dist/features/index.d.ts +2 -1
- package/dist/features/load.d.ts +8 -0
- package/dist/features/remote.d.ts +19 -3
- package/dist/features/trust.d.ts +44 -0
- package/dist/fs.d.ts +5 -0
- package/dist/index.d.ts +5 -2
- package/dist/index.js +2389 -281
- package/dist/plan.d.ts +21 -0
- package/dist/transforms/add-env-key.d.ts +2 -0
- package/dist/transforms/ast.d.ts +1 -0
- package/dist/upgrade.d.ts +109 -0
- package/package.json +2 -2
package/dist/plan.d.ts
CHANGED
|
@@ -17,12 +17,16 @@ export interface PlanFeature {
|
|
|
17
17
|
name: string;
|
|
18
18
|
version: string;
|
|
19
19
|
options?: Record<string, unknown>;
|
|
20
|
+
/** `sha256-<hex>` of the feature.json a registry served; recorded in mfeflow.json. */
|
|
21
|
+
integrity?: string;
|
|
20
22
|
}
|
|
21
23
|
export interface DependencyAdd {
|
|
22
24
|
file: string;
|
|
23
25
|
name: string;
|
|
24
26
|
range: string;
|
|
25
27
|
dev: boolean;
|
|
28
|
+
/** Added by a third-party feature, so `summarize` lists it in its own block. */
|
|
29
|
+
thirdParty?: boolean;
|
|
26
30
|
}
|
|
27
31
|
/** Added to package.json and shown. The engine never runs it. */
|
|
28
32
|
export interface ScriptAdd {
|
|
@@ -91,6 +95,8 @@ export declare class PlanBuilder {
|
|
|
91
95
|
private open;
|
|
92
96
|
exists(file: string): Promise<boolean>;
|
|
93
97
|
content(file: string): Promise<string | undefined>;
|
|
98
|
+
/** Whether `file` was on disk before this plan changed anything. */
|
|
99
|
+
existed(file: string): Promise<boolean>;
|
|
94
100
|
/** Remembers `mfeflow.json` as it is now; `applyPlan` refuses to continue if it changes before the write. */
|
|
95
101
|
captureProject(): Promise<void>;
|
|
96
102
|
addFeature(feature: PlanFeature): void;
|
|
@@ -99,8 +105,23 @@ export declare class PlanBuilder {
|
|
|
99
105
|
create(file: string, content: string, track?: boolean): Promise<void>;
|
|
100
106
|
/** Rewrites an existing file. */
|
|
101
107
|
patch(file: string, edit: (source: string) => string): Promise<void>;
|
|
108
|
+
/** Overwrites a file that exists, shown as a modification. First-party only: a third-party feature never replaces content. */
|
|
109
|
+
replace(file: string, content: string): Promise<void>;
|
|
102
110
|
delete(file: string): Promise<void>;
|
|
103
111
|
addDependency(file: string, name: string, range: string, dev?: boolean): Promise<void>;
|
|
112
|
+
/**
|
|
113
|
+
* Moves an existing dependency to `range`. A dependency on `catalog:` changes
|
|
114
|
+
* its entry in pnpm-workspace.yaml instead. A `workspace:` link, or any
|
|
115
|
+
* specifier that is not a registry range (`npm:`, `link:`, `file:`, a
|
|
116
|
+
* repository or a URL), is the project's own choice and is left alone with a
|
|
117
|
+
* warning. The new range must be a semver range or a dist-tag (E202). A
|
|
118
|
+
* missing dependency is an E208. A third-party feature can only ask for the
|
|
119
|
+
* range that is already there.
|
|
120
|
+
*/
|
|
121
|
+
setRange(file: string, name: string, range: string): Promise<void>;
|
|
122
|
+
/** The first range for `name` that is not already `wanted`, else the first one; a name can be listed in several sections. */
|
|
123
|
+
private declaredRange;
|
|
124
|
+
private setCatalogEntry;
|
|
104
125
|
/** Adds a script. An identical one already there is a no-op; a different command under the same name is a conflict. */
|
|
105
126
|
addScript(file: string, name: string, command: string): Promise<void>;
|
|
106
127
|
addEnvKey(file: string, key: string): void;
|
|
@@ -11,6 +11,8 @@ export interface SchemaKey {
|
|
|
11
11
|
name: string;
|
|
12
12
|
/** The key may be missing: an arktype `'key?'`, or a Zod or Valibot schema whose outermost call is optional, nullish, default, catch, fallback or exactOptional. */
|
|
13
13
|
optional: boolean;
|
|
14
|
+
/** The validator as written in the file, for example `z.string().min(1)`. */
|
|
15
|
+
schema: string;
|
|
14
16
|
}
|
|
15
17
|
/**
|
|
16
18
|
* The keys of the `server` schema (`env.ts`) or of the runtime-config schema object,
|
package/dist/transforms/ast.d.ts
CHANGED
|
@@ -9,6 +9,7 @@ export interface Edit {
|
|
|
9
9
|
/** Applies edits from the end backwards so earlier offsets stay valid. */
|
|
10
10
|
export declare function applyEdits(source: string, edits: Edit[]): string;
|
|
11
11
|
export declare function parseSource(source: string, file: string): File;
|
|
12
|
+
export declare const SKIP_KEYS: Set<string>;
|
|
12
13
|
/** Every node under `root` (including it) for which `match` returns true, in source order. */
|
|
13
14
|
export declare function findAll(root: Node, match: (node: Node) => boolean): Node[];
|
|
14
15
|
export type FunctionNode = FunctionDeclaration | FunctionExpression | ArrowFunctionExpression;
|
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
import type { LoadedFeature } from './features/load.js';
|
|
2
|
+
import { PlanBuilder, type Plan, type ReadFile } from './plan.js';
|
|
3
|
+
import type { MfeflowProject } from './project.js';
|
|
4
|
+
/**
|
|
5
|
+
* What a first-party migration module exports (as `default` or `migrate`). It records its
|
|
6
|
+
* changes on the builder and returns nothing, so a dry run, `--json` and rollback work for it.
|
|
7
|
+
*/
|
|
8
|
+
export type Migration = (builder: PlanBuilder, project: MfeflowProject) => void | Promise<void>;
|
|
9
|
+
export interface UpgradeInput {
|
|
10
|
+
/** The version the project is moving to; every `@mfeflow/*` range becomes `^<toVersion>`. */
|
|
11
|
+
toVersion: string;
|
|
12
|
+
/** Reads a project file by relative path; undefined when it does not exist. */
|
|
13
|
+
read: ReadFile;
|
|
14
|
+
/**
|
|
15
|
+
* The features to replay, in the order `init` applies them (`core` first). Each is replayed with
|
|
16
|
+
* the options `mfeflow.json` recorded for it.
|
|
17
|
+
*/
|
|
18
|
+
features: readonly LoadedFeature[];
|
|
19
|
+
/** First-party parts replayed after the features, such as the per-remote registry and route files. */
|
|
20
|
+
glue?: readonly LoadedFeature[];
|
|
21
|
+
/** Recorded features the caller could not load. Their files are left alone and nothing is reported as removed. */
|
|
22
|
+
skipped?: readonly {
|
|
23
|
+
name: string;
|
|
24
|
+
reason: string;
|
|
25
|
+
}[];
|
|
26
|
+
/** Whether a project file is itself a symlink. Such a file is never replaced. */
|
|
27
|
+
isSymlink?: (file: string) => Promise<boolean>;
|
|
28
|
+
/** Loads a migration module. Defaults to a dynamic `import()`. */
|
|
29
|
+
importModule?: (file: string) => Promise<unknown>;
|
|
30
|
+
/**
|
|
31
|
+
* What the person decided about files that differ. An accepted file is written with the new
|
|
32
|
+
* version; a kept one is left, and the plan's project remembers it. `all` leaves out symlinks.
|
|
33
|
+
*/
|
|
34
|
+
decisions?: UpgradeDecisions;
|
|
35
|
+
}
|
|
36
|
+
export interface UpgradeDecisions {
|
|
37
|
+
accept?: ReadonlySet<string> | 'all';
|
|
38
|
+
keep?: ReadonlySet<string> | 'all';
|
|
39
|
+
}
|
|
40
|
+
export type DivergeReason =
|
|
41
|
+
/** Tracked, and the file no longer matches the hash recorded when it was written. */
|
|
42
|
+
'edited'
|
|
43
|
+
/** The CLI never wrote this file, but a file is there and differs. */
|
|
44
|
+
| 'untracked'
|
|
45
|
+
/** The CLI edits this file after generating it (`add env-key`), so a match with the recorded hash proves nothing. */
|
|
46
|
+
| 'edited-by-cli'
|
|
47
|
+
/** A feature that could not be replayed may have patched this file, so a matching hash proves nothing. */
|
|
48
|
+
| 'skipped-feature'
|
|
49
|
+
/** The path is a symlink; it is not replaced with a regular file. */
|
|
50
|
+
| 'symlink';
|
|
51
|
+
/** A file the new version wants to change that the upgrade will not write. */
|
|
52
|
+
export interface DivergedUpgrade {
|
|
53
|
+
path: string;
|
|
54
|
+
reason: DivergeReason;
|
|
55
|
+
/** What is on disk. */
|
|
56
|
+
yours: string;
|
|
57
|
+
/** What the new version generates. */
|
|
58
|
+
incoming: string;
|
|
59
|
+
/** Unified diff from `yours` to `incoming`. */
|
|
60
|
+
diff: string;
|
|
61
|
+
/** `accept` is written with the new version in `plan`; `keep` is left and remembered. Absent: undecided, left as it is. */
|
|
62
|
+
decision?: 'accept' | 'keep';
|
|
63
|
+
/** For files the CLI adds keys to: keys in your file that the new version lacks, which accepting drops. */
|
|
64
|
+
lostKeys?: string[];
|
|
65
|
+
/** The part of `lostKeys` that is in the new file with another value; the rest are not in it at all. */
|
|
66
|
+
changedValues?: string[];
|
|
67
|
+
}
|
|
68
|
+
export interface UpgradePlan {
|
|
69
|
+
/** The version the project was made with, and where that came from. */
|
|
70
|
+
from: string;
|
|
71
|
+
fromSource: 'mfeflow.json' | 'package.json';
|
|
72
|
+
to: string;
|
|
73
|
+
/** Replaced, created and structurally edited files. Apply it with `applyPlan`, passing `project`. */
|
|
74
|
+
plan: Plan;
|
|
75
|
+
/** The project to hand to `applyPlan`: `cli` is `to`; hashes and feature versions are filled in on apply. */
|
|
76
|
+
project: MfeflowProject;
|
|
77
|
+
/** Files the new version wants to change that you changed too, each with a diff. Only those without a `decision` are left undecided. */
|
|
78
|
+
diverged: DivergedUpgrade[];
|
|
79
|
+
/** Feature migrations that ran, in order. */
|
|
80
|
+
migrations: {
|
|
81
|
+
feature: string;
|
|
82
|
+
from: string;
|
|
83
|
+
to: string;
|
|
84
|
+
}[];
|
|
85
|
+
/** Files the old version generated and the new one no longer does. Reported, never deleted. */
|
|
86
|
+
removed: string[];
|
|
87
|
+
/** Files the old version generated that you deleted. They are not brought back. */
|
|
88
|
+
missing: string[];
|
|
89
|
+
}
|
|
90
|
+
/**
|
|
91
|
+
* The version of the CLI that made the project: `cli` in `mfeflow.json`, else the lowest version
|
|
92
|
+
* the shell's `@mfeflow/runtime` range allows (0.1 projects have no `cli`). A `workspace:`,
|
|
93
|
+
* `link:` or non-version range cannot be read, and that is an error rather than a guess.
|
|
94
|
+
*/
|
|
95
|
+
export declare function detectBaseline(project: MfeflowProject, read: ReadFile): Promise<{
|
|
96
|
+
version: string;
|
|
97
|
+
source: 'mfeflow.json' | 'package.json';
|
|
98
|
+
}>;
|
|
99
|
+
/**
|
|
100
|
+
* Works out what moving a project to `toVersion` changes, without touching the disk.
|
|
101
|
+
*
|
|
102
|
+
* It replays the skeleton and every recorded feature, with its recorded options, into memory and
|
|
103
|
+
* compares the result with the project. A tracked file you have not edited is replaced; one you
|
|
104
|
+
* have edited is returned in `diverged` with a diff and left alone; a new file is created; a file
|
|
105
|
+
* the new version no longer makes is listed in `removed` and never deleted. `package.json`,
|
|
106
|
+
* `pnpm-workspace.yaml` and `turbo.json` only get structured edits. Feature migrations whose
|
|
107
|
+
* version the upgrade crosses then run, in order, on the same plan.
|
|
108
|
+
*/
|
|
109
|
+
export declare function planUpgrade(project: MfeflowProject, input: UpgradeInput): Promise<UpgradePlan>;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@mfeflow/core",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.6.0",
|
|
4
4
|
"description": "The engine behind the mfeflow CLI: project model, change plans with diffs, atomic apply with rollback, and feature resolution.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"micro-frontend",
|
|
@@ -45,7 +45,7 @@
|
|
|
45
45
|
"dependencies": {
|
|
46
46
|
"@babel/parser": "8.0.10",
|
|
47
47
|
"@babel/types": "8.0.10",
|
|
48
|
-
"@mfeflow/contracts": "0.
|
|
48
|
+
"@mfeflow/contracts": "0.6.0",
|
|
49
49
|
"diff": "9.0.0",
|
|
50
50
|
"eta": "4.6.0",
|
|
51
51
|
"semver": "7.8.5",
|