mfeflow 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.
Files changed (68) hide show
  1. package/README.md +8 -3
  2. package/assets/features/registry-server/feature.json +128 -0
  3. package/assets/features/registry-server/files/deploy-server.yml +69 -0
  4. package/assets/features/registry-server/files/registry-server.md.eta +52 -0
  5. package/assets/features/registry-server/files/registry-sources.ts +12 -0
  6. package/assets/features/registry-static/feature.json +61 -0
  7. package/assets/features/registry-static/files/deploy.yml +61 -0
  8. package/assets/features/registry-static/files/registry.md.eta +49 -0
  9. package/assets/features/release/feature.json +43 -0
  10. package/assets/features/release/files/changeset-readme.md +7 -0
  11. package/assets/features/release/files/config.json +10 -0
  12. package/assets/features/release/files/releasing.md +21 -0
  13. package/assets/templates/monorepo/feature.json +7 -6
  14. package/assets/templates/monorepo/files/remote/{mfe.json.eta → mfeflow.app.json.eta} +1 -0
  15. package/assets/templates/monorepo/files/root/README.md.eta +1 -1
  16. package/assets/templates/monorepo/files/shell/{mfe.json.eta → mfeflow.app.json.eta} +1 -0
  17. package/assets/templates/monorepo/files/shell/rsbuild.config.ts.eta +42 -6
  18. package/assets/templates/monorepo/migrations/0.4.0-app-file.mjs +58 -0
  19. package/assets/templates/polyrepo/feature.json +305 -0
  20. package/assets/templates/polyrepo/files/AGENTS.md.eta +15 -0
  21. package/assets/templates/polyrepo/files/changeset/README.md +5 -0
  22. package/assets/templates/polyrepo/files/changeset/config.json +9 -0
  23. package/assets/templates/polyrepo/files/packages/contracts/package.json.eta +23 -0
  24. package/assets/templates/polyrepo/files/packages/contracts/src/index.ts +11 -0
  25. package/assets/templates/polyrepo/files/packages/contracts/tsconfig.json.eta +5 -0
  26. package/assets/templates/polyrepo/files/packages/tokens/package.json.eta +23 -0
  27. package/assets/templates/polyrepo/files/packages/tokens/src/index.ts +13 -0
  28. package/assets/templates/polyrepo/files/packages/tokens/tsconfig.json.eta +5 -0
  29. package/assets/templates/polyrepo/files/platform/README.md.eta +43 -0
  30. package/assets/templates/polyrepo/files/platform/default.json.eta +27 -0
  31. package/assets/templates/polyrepo/files/remote/README.md.eta +23 -0
  32. package/assets/templates/polyrepo/files/renovate.json.eta +4 -0
  33. package/assets/templates/polyrepo/files/shell/README.md.eta +32 -0
  34. package/assets/templates/polyrepo/files/tsconfig.base.json.eta +13 -0
  35. package/assets/templates/polyrepo/files/workflows/platform-ci.yml +29 -0
  36. package/assets/templates/polyrepo/files/workflows/release.yml +40 -0
  37. package/assets/templates/polyrepo/files/workflows/reusable-ci.yml.eta +50 -0
  38. package/assets/templates/polyrepo/files/workflows/team-ci.yml.eta +12 -0
  39. package/dist/against.d.ts +16 -0
  40. package/dist/catalog.d.ts +4 -0
  41. package/dist/checks/compat.d.ts +12 -0
  42. package/dist/checks/index.d.ts +0 -1
  43. package/dist/commands/add.d.ts +0 -2
  44. package/dist/commands/adopt.d.ts +54 -0
  45. package/dist/commands/deploy.d.ts +35 -0
  46. package/dist/commands/doctor.d.ts +5 -0
  47. package/dist/commands/init.d.ts +9 -1
  48. package/dist/commands/server-mode.d.ts +210 -0
  49. package/dist/commands/status.d.ts +5 -0
  50. package/dist/commands/team-repo.d.ts +9 -0
  51. package/dist/commands/upgrade.d.ts +66 -0
  52. package/dist/devremotes.d.ts +15 -0
  53. package/dist/exit.d.ts +1 -0
  54. package/dist/glue.d.ts +6 -0
  55. package/dist/index.d.ts +1 -1
  56. package/dist/index.js +4546 -1880
  57. package/dist/inspect.d.ts +14 -2
  58. package/dist/output.d.ts +138 -3
  59. package/dist/pipeline.d.ts +5 -2
  60. package/dist/polyrepo.d.ts +69 -0
  61. package/dist/publish.d.ts +10 -1
  62. package/dist/runtime.d.ts +2 -0
  63. package/dist/server-client.d.ts +61 -0
  64. package/dist/system.d.ts +2 -0
  65. package/dist/testing.d.ts +17 -1
  66. package/dist/upgrade.d.ts +25 -0
  67. package/dist/write.d.ts +8 -0
  68. package/package.json +5 -5
@@ -0,0 +1,32 @@
1
+ # <%= it.scope.slice(1) %>-shell
2
+
3
+ The shell of a polyrepo made with [mfeflow](https://github.com/mfeflow/mfeflow): routes, layout and
4
+ the registry that tells it which build of each remote to load. The remotes are in their own repos.
5
+
6
+ ```
7
+ apps/shell the host
8
+ apps/shell/public/config/runtime-config.* per environment; dev lists where the remotes run
9
+ registry/envs which build of each remote staging and prod serve
10
+ ```
11
+
12
+ ## Run it
13
+
14
+ ```sh
15
+ pnpm install
16
+ pnpm dev
17
+ ```
18
+
19
+ `pnpm dev` starts the shell on http://localhost:4300. It finds each remote in `devRemotes` in
20
+ `apps/shell/public/config/runtime-config.dev.json`. Start a remote with `pnpm dev` in its own repo.
21
+
22
+ `pnpm mfeflow dev` runs the shell the same way and reloads the list when that file changes.
23
+ Point one remote somewhere else for a run with `pnpm mfeflow dev --remote cart=http://localhost:3001`.
24
+
25
+ ## Add a team repo
26
+
27
+ ```sh
28
+ pnpm mfeflow add team-repo checkout
29
+ ```
30
+
31
+ This creates `../checkout` as a new git repo and registers it here. Run `git init` and the GitHub
32
+ steps yourself.
@@ -0,0 +1,13 @@
1
+ {
2
+ "compilerOptions": {
3
+ "target": "ES2022",
4
+ "module": "ESNext",
5
+ "moduleResolution": "Bundler",
6
+ "strict": true,
7
+ "noUncheckedIndexedAccess": true,
8
+ "verbatimModuleSyntax": true,
9
+ "declaration": true,
10
+ "skipLibCheck": true,
11
+ "types": []
12
+ }
13
+ }
@@ -0,0 +1,29 @@
1
+ name: ci
2
+
3
+ on:
4
+ pull_request:
5
+
6
+ permissions: {}
7
+
8
+ concurrency:
9
+ group: ci-${{ github.ref }}
10
+ cancel-in-progress: true
11
+
12
+ jobs:
13
+ check:
14
+ runs-on: ubuntu-latest
15
+ timeout-minutes: 15
16
+ permissions:
17
+ contents: read
18
+ steps:
19
+ - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
20
+ with:
21
+ persist-credentials: false
22
+ - uses: pnpm/action-setup@ea17c68df8912ef543352723c149a84f56e3d413 # v6.1.0
23
+ - uses: actions/setup-node@949feb2413d6458794dcd2491c4babbbce0c15c1 # v7.1.0
24
+ with:
25
+ node-version: lts/*
26
+ cache: pnpm
27
+ - run: pnpm install
28
+ - run: pnpm build
29
+ - run: pnpm mfeflow validate
@@ -0,0 +1,40 @@
1
+ name: release
2
+
3
+ # Publishes the packages in packages/ when a "chore: version packages" pull request is merged.
4
+ # Set the NPM_TOKEN secret for npm, or change the registry in .npmrc for GitHub Packages.
5
+ # Dormant until the repository variable RELEASE_ENABLED is 'true'.
6
+ on:
7
+ push:
8
+ branches: [main]
9
+
10
+ permissions: {}
11
+
12
+ concurrency:
13
+ group: release
14
+ cancel-in-progress: false
15
+
16
+ jobs:
17
+ release:
18
+ if: vars.RELEASE_ENABLED == 'true'
19
+ runs-on: ubuntu-latest
20
+ permissions:
21
+ contents: write
22
+ pull-requests: write
23
+ steps:
24
+ - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
25
+ with:
26
+ persist-credentials: false
27
+ - uses: pnpm/action-setup@ea17c68df8912ef543352723c149a84f56e3d413 # v6.1.0
28
+ - uses: actions/setup-node@949feb2413d6458794dcd2491c4babbbce0c15c1 # v7.1.0
29
+ with:
30
+ node-version: lts/*
31
+ registry-url: https://registry.npmjs.org
32
+ - run: pnpm install
33
+ - uses: changesets/action@ae32849d5ba541f9ae29e40e22a623bc13562f51 # v2.1.2
34
+ with:
35
+ publish: pnpm release
36
+ pr-title: 'chore: version packages'
37
+ commit-message: 'chore: version packages'
38
+ env:
39
+ GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
40
+ NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
@@ -0,0 +1,50 @@
1
+ name: reusable-ci
2
+
3
+ # Every team repo calls this file from its own workflow:
4
+ #
5
+ # jobs:
6
+ # ci:
7
+ # uses: <%= it.options.org || it.scope.slice(1) %>/platform/.github/workflows/reusable-ci.yml@main
8
+ #
9
+ # A private platform repo has to allow it under Settings > Actions > General > Access.
10
+ on:
11
+ workflow_call:
12
+ inputs:
13
+ node-version:
14
+ description: Node version to run the checks on
15
+ type: string
16
+ default: lts/*
17
+ run-budget:
18
+ description: Also run mfeflow budget after the build
19
+ type: boolean
20
+ default: false
21
+
22
+ permissions: {}
23
+
24
+ jobs:
25
+ check:
26
+ runs-on: ubuntu-latest
27
+ timeout-minutes: 20
28
+ permissions:
29
+ contents: read
30
+ steps:
31
+ - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
32
+ with:
33
+ persist-credentials: false
34
+ - uses: pnpm/action-setup@ea17c68df8912ef543352723c149a84f56e3d413 # v6.1.0
35
+ - uses: actions/setup-node@949feb2413d6458794dcd2491c4babbbce0c15c1 # v7.1.0
36
+ with:
37
+ node-version: ${{ inputs.node-version }}
38
+ cache: pnpm
39
+ - run: pnpm install
40
+ - run: pnpm run --if-present typecheck
41
+ - run: pnpm run --if-present lint
42
+ - run: pnpm run --if-present test
43
+ - run: pnpm build
44
+ - name: mfeflow validate
45
+ run: pnpm mfeflow validate
46
+ - name: mfeflow doctor
47
+ run: pnpm mfeflow doctor
48
+ - name: mfeflow budget
49
+ if: ${{ inputs.run-budget }}
50
+ run: pnpm mfeflow budget
@@ -0,0 +1,12 @@
1
+ name: ci
2
+
3
+ on:
4
+ pull_request:
5
+
6
+ permissions: {}
7
+
8
+ jobs:
9
+ ci:
10
+ permissions:
11
+ contents: read
12
+ uses: <%= it.options.org || it.scope.slice(1) %>/platform/.github/workflows/reusable-ci.yml@main
@@ -0,0 +1,16 @@
1
+ import { type FetchLike } from '@mfeflow/core';
2
+ /** The shell a remote is checked against, as its deployed `mf-manifest.json`. */
3
+ export interface ShellSource {
4
+ /** What the user passed, for the report. */
5
+ from: string;
6
+ manifest: unknown;
7
+ }
8
+ /**
9
+ * The shell's `mf-manifest.json` from `source`: the manifest itself, or a registry index, whose
10
+ * `shell/mf-manifest.json` is read from beside it. `source` is a file or an https URL (http on
11
+ * localhost). Fails with E307 on anything else.
12
+ */
13
+ export declare function loadShell(source: string, options: {
14
+ cwd: string;
15
+ fetch: FetchLike;
16
+ }): Promise<ShellSource>;
package/dist/catalog.d.ts CHANGED
@@ -13,6 +13,8 @@ export declare function isFirstParty(name: string): boolean;
13
13
  /** The first-party features a user may pick, in catalogue order. */
14
14
  export declare const OPTIONAL_FEATURES: readonly string[];
15
15
  export declare const DEFAULT_FEATURES: readonly string[];
16
+ /** `polyrepo` is applied by `init --topology polyrepo`; it is not offered by `add` or listed by `features`. */
17
+ export declare const POLYREPO_FEATURE = "polyrepo";
16
18
  export interface FeatureSource {
17
19
  roots: AssetRoots;
18
20
  registries?: Record<string, string> | undefined;
@@ -26,3 +28,5 @@ export interface FeatureSource {
26
28
  }
27
29
  /** A first-party feature by name, or `@namespace/name` from a configured registry. */
28
30
  export declare function loadAny(name: string, source: FeatureSource): Promise<LoadedFeature>;
31
+ /** First-party features in the order `init` applies them, then the rest as typed: a feature may edit another's files. */
32
+ export declare function inCatalogueOrder(names: readonly string[]): string[];
@@ -1,2 +1,14 @@
1
1
  import { type Check } from '../findings.js';
2
+ /** Where the shell's versions come from when it is not in this repo. */
3
+ export interface AgainstShell {
4
+ from: string;
5
+ manifest: unknown;
6
+ }
7
+ export declare const ABSENT_SHELL_WARNING = "shell is not in this repo, pass --against <url|file>";
8
+ /**
9
+ * Each remote's shared ranges against the shell. The shell comes from `against` (a deployed
10
+ * manifest) when given, else from the shells in this repo; with neither, the check warns
11
+ * instead of passing.
12
+ */
13
+ export declare function compatCheck(against?: AgainstShell, under?: 'check-compat' | 'doctor'): Check;
2
14
  export declare const compat: Check;
@@ -1,6 +1,5 @@
1
1
  import type { Check } from '../findings.js';
2
2
  /** What `mfeflow validate` runs: the files against their schemas and each other. */
3
3
  export declare const VALIDATE_CHECKS: readonly Check[];
4
- export declare const COMPAT_CHECKS: readonly Check[];
5
4
  /** Every check `mfeflow doctor` runs, in order. */
6
5
  export declare const DOCTOR_CHECKS: readonly Check[];
@@ -83,6 +83,4 @@ export declare const ADD_ARGS: {
83
83
  readonly description: 'Take a registry feature whose content differs from the hash recorded in mfeflow.json';
84
84
  };
85
85
  };
86
- /** First-party features in the order `init` applies them, then the rest as typed: a feature may edit another's files. */
87
- export declare function inCatalogueOrder(names: readonly string[]): string[];
88
86
  export declare function runAdd(rt: Runtime, args: Record<string, unknown>, raw: readonly string[]): Promise<AddResult>;
@@ -0,0 +1,54 @@
1
+ import { type Plan } from '@mfeflow/core';
2
+ import { type AdoptResult } from '../output.js';
3
+ import type { Runtime } from '../runtime.js';
4
+ export declare const ADOPT_ARGS: {
5
+ readonly yes: {
6
+ readonly type: 'boolean';
7
+ readonly alias: 'y';
8
+ readonly description: 'Take the defaults and never prompt';
9
+ };
10
+ readonly preset: {
11
+ readonly type: 'string';
12
+ readonly description: 'Replay options from a JSON file or an https URL';
13
+ readonly valueHint: 'file|url';
14
+ };
15
+ readonly json: {
16
+ readonly type: 'boolean';
17
+ readonly description: 'Print one JSON document on stdout, nothing else';
18
+ };
19
+ readonly 'dry-run': {
20
+ readonly type: 'boolean';
21
+ readonly description: 'Print the summary and diff, write nothing';
22
+ };
23
+ readonly cwd: {
24
+ readonly type: 'string';
25
+ readonly description: 'Run as if started in this folder';
26
+ readonly valueHint: 'dir';
27
+ };
28
+ readonly install: {
29
+ readonly type: 'boolean';
30
+ readonly default: true;
31
+ readonly description: 'Run the package manager after writing (--no-install to skip)';
32
+ };
33
+ readonly verbose: {
34
+ readonly type: 'boolean';
35
+ readonly description: 'Show package manager output and stack traces';
36
+ };
37
+ readonly local: {
38
+ readonly type: 'string';
39
+ readonly description: 'Link @mfeflow/* from a built mfeflow checkout (env MFEFLOW_LOCAL)';
40
+ readonly valueHint: 'path';
41
+ };
42
+ readonly help: {
43
+ readonly type: 'boolean';
44
+ readonly alias: 'h';
45
+ readonly description: 'Show this help';
46
+ };
47
+ };
48
+ /** The lines to paste into the shared list of a build config, which adopt never edits. */
49
+ export declare const SHARED_SNIPPET = " '@mfeflow/runtime': { singleton: true },";
50
+ /** mfeflow.json may have appeared since the first check; the plan would then overwrite it. */
51
+ export declare function assertNoProjectFile(plan: Plan): void;
52
+ /** A last guard behind the promise that adopt never edits a build config. */
53
+ export declare function assertBuildConfigUntouched(plan: Plan, buildConfig: readonly string[]): void;
54
+ export declare function runAdopt(rt: Runtime, args: Record<string, unknown>, raw: readonly string[]): Promise<AdoptResult>;
@@ -43,6 +43,21 @@ export declare const DEPLOY_ARGS: {
43
43
  readonly alias: 'h';
44
44
  readonly description: 'Show this help';
45
45
  };
46
+ readonly 'registry-url': {
47
+ readonly type: 'string';
48
+ readonly description: 'Registry server address (env MFEFLOW_REGISTRY_URL). The token is only read from MFEFLOW_REGISTRY_TOKEN';
49
+ readonly valueHint: 'url';
50
+ };
51
+ readonly percent: {
52
+ readonly type: 'string';
53
+ readonly description: 'Start a percentage rollout at this share of visitors, 1 to 99 (registry server only)';
54
+ readonly valueHint: 'n';
55
+ };
56
+ readonly steps: {
57
+ readonly type: 'string';
58
+ readonly description: 'Later rollout steps, rising, like 50,100 (needs --percent)';
59
+ readonly valueHint: 'a,b,c';
60
+ };
46
61
  readonly host: {
47
62
  readonly type: 'string';
48
63
  readonly description: 'Where the registry lives: file:<dir> or s3://<bucket>[/prefix] (default registry.host)';
@@ -122,6 +137,21 @@ export declare const PROMOTE_ARGS: {
122
137
  readonly alias: 'h';
123
138
  readonly description: 'Show this help';
124
139
  };
140
+ readonly 'registry-url': {
141
+ readonly type: 'string';
142
+ readonly description: 'Registry server address (env MFEFLOW_REGISTRY_URL). The token is only read from MFEFLOW_REGISTRY_TOKEN';
143
+ readonly valueHint: 'url';
144
+ };
145
+ readonly percent: {
146
+ readonly type: 'string';
147
+ readonly description: 'Start a percentage rollout at this share of visitors, 1 to 99 (registry server only)';
148
+ readonly valueHint: 'n';
149
+ };
150
+ readonly steps: {
151
+ readonly type: 'string';
152
+ readonly description: 'Later rollout steps, rising, like 50,100 (needs --percent)';
153
+ readonly valueHint: 'a,b,c';
154
+ };
125
155
  readonly host: {
126
156
  readonly type: 'string';
127
157
  readonly description: 'Where the registry lives: file:<dir> or s3://<bucket>[/prefix] (default registry.host)';
@@ -191,6 +221,11 @@ export declare const ROLLBACK_ARGS: {
191
221
  readonly alias: 'h';
192
222
  readonly description: 'Show this help';
193
223
  };
224
+ readonly 'registry-url': {
225
+ readonly type: 'string';
226
+ readonly description: 'Registry server address (env MFEFLOW_REGISTRY_URL). The token is only read from MFEFLOW_REGISTRY_TOKEN';
227
+ readonly valueHint: 'url';
228
+ };
194
229
  readonly host: {
195
230
  readonly type: 'string';
196
231
  readonly description: 'Where the registry lives: file:<dir> or s3://<bucket>[/prefix] (default registry.host)';
@@ -135,6 +135,11 @@ export declare const COMPAT_ARGS: {
135
135
  readonly alias: 'h';
136
136
  readonly description: 'Show this help';
137
137
  };
138
+ readonly against: {
139
+ readonly type: 'string';
140
+ readonly description: 'Check against the shell a registry index or a deployed mf-manifest.json describes (file or https URL)';
141
+ readonly valueHint: 'url|file';
142
+ };
138
143
  };
139
144
  export declare function runDoctor(rt: Runtime, args: Record<string, unknown>, raw: readonly string[]): Promise<ReportResult>;
140
145
  export declare function runValidate(rt: Runtime, args: Record<string, unknown>, raw: readonly string[]): Promise<ReportResult>;
@@ -74,16 +74,24 @@ export declare const INIT_ARGS: {
74
74
  };
75
75
  readonly topology: {
76
76
  readonly type: 'string';
77
- readonly description: 'monorepo (the only one in this release)';
77
+ readonly description: 'monorepo (default), or polyrepo: a platform repo, a shell repo and a repo for each remote';
78
78
  readonly valueHint: 'name';
79
79
  };
80
+ readonly org: {
81
+ readonly type: 'string';
82
+ readonly description: 'polyrepo: the GitHub owner the CI and Renovate files point at (default: the scope without @)';
83
+ readonly valueHint: 'owner';
84
+ };
80
85
  readonly option: {
81
86
  readonly type: 'string';
82
87
  readonly description: 'A feature option, repeatable: --option feature.key=value';
83
88
  readonly valueHint: 'f.k=v';
84
89
  };
85
90
  };
91
+ export type Topology = 'monorepo' | 'polyrepo';
86
92
  export interface InitOptions {
93
+ topology: Topology;
94
+ org?: string;
87
95
  dir: string;
88
96
  scope: string;
89
97
  remotes: string[];
@@ -0,0 +1,210 @@
1
+ import type { ArgsDef } from 'citty';
2
+ import type { DeployResult, KillCommandResult, RolloutCommandResult, StatusResult } from '../output.js';
3
+ import type { Runtime } from '../runtime.js';
4
+ import type { ServerClient } from '../server-client.js';
5
+ export declare const SERVER_ARGS: {
6
+ readonly 'registry-url': {
7
+ readonly type: 'string';
8
+ readonly description: 'Registry server address (env MFEFLOW_REGISTRY_URL). The token is only read from MFEFLOW_REGISTRY_TOKEN';
9
+ readonly valueHint: 'url';
10
+ };
11
+ };
12
+ export declare const ROLLOUT_ARGS: {
13
+ readonly percent: {
14
+ readonly type: 'string';
15
+ readonly description: 'Start a percentage rollout at this share of visitors, 1 to 99 (registry server only)';
16
+ readonly valueHint: 'n';
17
+ };
18
+ readonly steps: {
19
+ readonly type: 'string';
20
+ readonly description: 'Later rollout steps, rising, like 50,100 (needs --percent)';
21
+ readonly valueHint: 'a,b,c';
22
+ };
23
+ };
24
+ export declare const ROLLOUT_CMD_ARGS: {
25
+ readonly yes: {
26
+ readonly type: 'boolean';
27
+ readonly alias: 'y';
28
+ readonly description: 'Take the defaults and never prompt';
29
+ };
30
+ readonly preset: {
31
+ readonly type: 'string';
32
+ readonly description: 'Replay options from a JSON file or an https URL';
33
+ readonly valueHint: 'file|url';
34
+ };
35
+ readonly json: {
36
+ readonly type: 'boolean';
37
+ readonly description: 'Print one JSON document on stdout, nothing else';
38
+ };
39
+ readonly 'dry-run': {
40
+ readonly type: 'boolean';
41
+ readonly description: 'Print the summary and diff, write nothing';
42
+ };
43
+ readonly cwd: {
44
+ readonly type: 'string';
45
+ readonly description: 'Run as if started in this folder';
46
+ readonly valueHint: 'dir';
47
+ };
48
+ readonly install: {
49
+ readonly type: 'boolean';
50
+ readonly default: true;
51
+ readonly description: 'Run the package manager after writing (--no-install to skip)';
52
+ };
53
+ readonly verbose: {
54
+ readonly type: 'boolean';
55
+ readonly description: 'Show package manager output and stack traces';
56
+ };
57
+ readonly local: {
58
+ readonly type: 'string';
59
+ readonly description: 'Link @mfeflow/* from a built mfeflow checkout (env MFEFLOW_LOCAL)';
60
+ readonly valueHint: 'path';
61
+ };
62
+ readonly help: {
63
+ readonly type: 'boolean';
64
+ readonly alias: 'h';
65
+ readonly description: 'Show this help';
66
+ };
67
+ readonly 'registry-url': {
68
+ readonly type: 'string';
69
+ readonly description: 'Registry server address (env MFEFLOW_REGISTRY_URL). The token is only read from MFEFLOW_REGISTRY_TOKEN';
70
+ readonly valueHint: 'url';
71
+ };
72
+ readonly env: {
73
+ readonly type: 'string';
74
+ readonly description: 'Environment the rollout runs in';
75
+ readonly valueHint: 'env';
76
+ };
77
+ readonly reason: {
78
+ readonly type: 'string';
79
+ readonly description: 'Why, for the audit log (abort only)';
80
+ readonly valueHint: 'text';
81
+ };
82
+ };
83
+ export declare const KILL_ARGS: {
84
+ readonly yes: {
85
+ readonly type: 'boolean';
86
+ readonly alias: 'y';
87
+ readonly description: 'Take the defaults and never prompt';
88
+ };
89
+ readonly preset: {
90
+ readonly type: 'string';
91
+ readonly description: 'Replay options from a JSON file or an https URL';
92
+ readonly valueHint: 'file|url';
93
+ };
94
+ readonly json: {
95
+ readonly type: 'boolean';
96
+ readonly description: 'Print one JSON document on stdout, nothing else';
97
+ };
98
+ readonly 'dry-run': {
99
+ readonly type: 'boolean';
100
+ readonly description: 'Print the summary and diff, write nothing';
101
+ };
102
+ readonly cwd: {
103
+ readonly type: 'string';
104
+ readonly description: 'Run as if started in this folder';
105
+ readonly valueHint: 'dir';
106
+ };
107
+ readonly install: {
108
+ readonly type: 'boolean';
109
+ readonly default: true;
110
+ readonly description: 'Run the package manager after writing (--no-install to skip)';
111
+ };
112
+ readonly verbose: {
113
+ readonly type: 'boolean';
114
+ readonly description: 'Show package manager output and stack traces';
115
+ };
116
+ readonly local: {
117
+ readonly type: 'string';
118
+ readonly description: 'Link @mfeflow/* from a built mfeflow checkout (env MFEFLOW_LOCAL)';
119
+ readonly valueHint: 'path';
120
+ };
121
+ readonly help: {
122
+ readonly type: 'boolean';
123
+ readonly alias: 'h';
124
+ readonly description: 'Show this help';
125
+ };
126
+ readonly 'registry-url': {
127
+ readonly type: 'string';
128
+ readonly description: 'Registry server address (env MFEFLOW_REGISTRY_URL). The token is only read from MFEFLOW_REGISTRY_TOKEN';
129
+ readonly valueHint: 'url';
130
+ };
131
+ readonly env: {
132
+ readonly type: 'string';
133
+ readonly description: 'Environment to remove the remote from';
134
+ readonly valueHint: 'env';
135
+ };
136
+ readonly reason: {
137
+ readonly type: 'string';
138
+ readonly description: 'Why, for the audit log';
139
+ readonly valueHint: 'text';
140
+ };
141
+ };
142
+ export declare const RESTORE_ARGS: {
143
+ readonly yes: {
144
+ readonly type: 'boolean';
145
+ readonly alias: 'y';
146
+ readonly description: 'Take the defaults and never prompt';
147
+ };
148
+ readonly preset: {
149
+ readonly type: 'string';
150
+ readonly description: 'Replay options from a JSON file or an https URL';
151
+ readonly valueHint: 'file|url';
152
+ };
153
+ readonly json: {
154
+ readonly type: 'boolean';
155
+ readonly description: 'Print one JSON document on stdout, nothing else';
156
+ };
157
+ readonly 'dry-run': {
158
+ readonly type: 'boolean';
159
+ readonly description: 'Print the summary and diff, write nothing';
160
+ };
161
+ readonly cwd: {
162
+ readonly type: 'string';
163
+ readonly description: 'Run as if started in this folder';
164
+ readonly valueHint: 'dir';
165
+ };
166
+ readonly install: {
167
+ readonly type: 'boolean';
168
+ readonly default: true;
169
+ readonly description: 'Run the package manager after writing (--no-install to skip)';
170
+ };
171
+ readonly verbose: {
172
+ readonly type: 'boolean';
173
+ readonly description: 'Show package manager output and stack traces';
174
+ };
175
+ readonly local: {
176
+ readonly type: 'string';
177
+ readonly description: 'Link @mfeflow/* from a built mfeflow checkout (env MFEFLOW_LOCAL)';
178
+ readonly valueHint: 'path';
179
+ };
180
+ readonly help: {
181
+ readonly type: 'boolean';
182
+ readonly alias: 'h';
183
+ readonly description: 'Show this help';
184
+ };
185
+ readonly 'registry-url': {
186
+ readonly type: 'string';
187
+ readonly description: 'Registry server address (env MFEFLOW_REGISTRY_URL). The token is only read from MFEFLOW_REGISTRY_TOKEN';
188
+ readonly valueHint: 'url';
189
+ };
190
+ readonly env: {
191
+ readonly type: 'string';
192
+ readonly description: 'Environment to put the remote back in';
193
+ readonly valueHint: 'env';
194
+ };
195
+ };
196
+ export interface RolloutPlan {
197
+ percent: number;
198
+ steps: number[];
199
+ }
200
+ /** `--percent` and `--steps` as the server wants them, or undefined when neither is given. */
201
+ export declare function rolloutOf(args: Record<string, unknown>): RolloutPlan | undefined;
202
+ /** A rollout was asked for in static mode, which has no way to split traffic. */
203
+ export declare function refuseRolloutFlags(args: Record<string, unknown>): void;
204
+ export declare function deployViaServer(rt: Runtime, args: Record<string, unknown>, raw: readonly string[], defs: ArgsDef, client: ServerClient): Promise<DeployResult>;
205
+ export declare function promoteViaServer(rt: Runtime, args: Record<string, unknown>, raw: readonly string[], defs: ArgsDef, client: ServerClient): Promise<DeployResult>;
206
+ export declare function rollbackViaServer(rt: Runtime, args: Record<string, unknown>, raw: readonly string[], defs: ArgsDef, client: ServerClient): Promise<DeployResult>;
207
+ export declare function statusViaServer(rt: Runtime, args: Record<string, unknown>, raw: readonly string[], defs: ArgsDef, client: ServerClient): Promise<StatusResult>;
208
+ export declare function runRolloutCommand(rt: Runtime, args: Record<string, unknown>, raw: readonly string[], client: ServerClient | undefined): Promise<RolloutCommandResult>;
209
+ export declare function runKillCommand(rt: Runtime, args: Record<string, unknown>, raw: readonly string[], restore: boolean, client: ServerClient | undefined): Promise<KillCommandResult>;
210
+ export declare function formatServerAction(result: RolloutCommandResult | KillCommandResult): string;
@@ -43,6 +43,11 @@ export declare const STATUS_ARGS: {
43
43
  readonly alias: 'h';
44
44
  readonly description: 'Show this help';
45
45
  };
46
+ readonly 'registry-url': {
47
+ readonly type: 'string';
48
+ readonly description: 'Registry server address (env MFEFLOW_REGISTRY_URL). The token is only read from MFEFLOW_REGISTRY_TOKEN';
49
+ readonly valueHint: 'url';
50
+ };
46
51
  readonly env: {
47
52
  readonly type: 'string';
48
53
  readonly description: 'Only this environment (default: every env on the host, and every folder in registry/envs but dev)';
@@ -0,0 +1,9 @@
1
+ import type { Globals } from '../args.js';
2
+ import { type AddResult } from '../output.js';
3
+ import type { Runtime } from '../runtime.js';
4
+ /**
5
+ * `mfeflow add team-repo <name>`, run in the shell repo: makes `../<name>` a new git repo with the
6
+ * remote in it, then registers the remote here (a route, staging and prod registry entries and its
7
+ * dev server in the dev config). The new repo is written first, so a failure here leaves no folder.
8
+ */
9
+ export declare function addTeamRepo(rt: Runtime, globals: Globals, args: Record<string, unknown>, given: string | undefined): Promise<AddResult>;