rman 1.3.0 → 2.0.0-beta.2
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 +63 -19
- package/cli.d.ts +5 -0
- package/cli.js +214 -88
- package/commands/build.command.d.ts +177 -3
- package/commands/build.command.js +20 -10
- package/commands/changed.command.d.ts +80 -3
- package/commands/changed.command.js +19 -12
- package/commands/changelog.command.d.ts +192 -3
- package/commands/changelog.command.js +87 -43
- package/commands/config.command.d.ts +44 -3
- package/commands/config.command.js +30 -19
- package/commands/diff.command.d.ts +37 -3
- package/commands/diff.command.js +25 -16
- package/commands/exec.command.d.ts +193 -3
- package/commands/exec.command.js +60 -58
- package/commands/github-release.command.d.ts +154 -3
- package/commands/github-release.command.js +67 -37
- package/commands/import.command.d.ts +36 -3
- package/commands/import.command.js +28 -20
- package/commands/info.command.d.ts +35 -7
- package/commands/info.command.js +36 -30
- package/commands/list.command.d.ts +163 -3
- package/commands/list.command.js +109 -71
- package/commands/publish.command.d.ts +231 -0
- package/commands/publish.command.js +304 -0
- package/commands/run.command.d.ts +186 -6
- package/commands/run.command.js +26 -72
- package/commands/test.command.d.ts +173 -3
- package/commands/test.command.js +16 -10
- package/commands/version.command.d.ts +317 -3
- package/commands/version.command.js +149 -69
- package/commands.d.ts +32 -0
- package/commands.js +28 -0
- package/constants.js +1 -1
- package/core/application.d.ts +116 -0
- package/core/application.js +143 -0
- package/core/command-builder.d.ts +14 -0
- package/core/command-builder.js +78 -0
- package/core/config.d.ts +140 -19
- package/core/config.js +258 -74
- package/core/core-services.d.ts +14 -0
- package/core/core-services.js +30 -0
- package/core/core-targets.d.ts +14 -0
- package/core/core-targets.js +16 -0
- package/core/custom-command.d.ts +42 -6
- package/core/custom-command.js +44 -17
- package/core/extends-config.d.ts +13 -5
- package/core/extends-config.js +52 -12
- package/core/load-config-module.d.ts +28 -0
- package/core/load-config-module.js +42 -0
- package/core/manifest.d.ts +47 -25
- package/core/manifest.js +51 -69
- package/core/merge-config.d.ts +33 -34
- package/core/merge-config.js +137 -92
- package/core/package.d.ts +145 -17
- package/core/package.js +128 -36
- package/core/plugin-loader.d.ts +65 -0
- package/core/plugin-loader.js +234 -0
- package/core/plugin.d.ts +135 -90
- package/core/plugin.js +70 -173
- package/core/publish-target.d.ts +124 -0
- package/core/publish-target.js +30 -0
- package/core/registry.d.ts +30 -0
- package/core/registry.js +47 -0
- package/core/repository.d.ts +72 -9
- package/core/repository.js +293 -44
- package/core/resolve-target.d.ts +1 -1
- package/core/resolve-target.js +1 -1
- package/core/service.d.ts +49 -0
- package/core/service.js +40 -0
- package/core/version-scheme.d.ts +23 -1
- package/core/version-scheme.js +29 -1
- package/core/workspace.d.ts +84 -33
- package/core/workspace.js +63 -22
- package/index.d.ts +111 -14
- package/index.js +85 -9
- package/interfaces/rman-config.interface.d.ts +725 -202
- package/interfaces/rman-config.interface.js +61 -1
- package/package.json +2 -1
- package/plugins/builtins.d.ts +44 -0
- package/plugins/builtins.js +33 -0
- package/plugins/detect.d.ts +78 -0
- package/plugins/detect.js +70 -0
- package/plugins/node/augmentation/rman.augmentation.d.ts +84 -0
- package/plugins/node/augmentation/rman.augmentation.js +1 -0
- package/plugins/node/augmentation/system-info.augmentation.d.ts +26 -0
- package/plugins/node/augmentation/system-info.augmentation.js +79 -0
- package/plugins/node/commands/ci.command.d.ts +131 -0
- package/plugins/node/commands/ci.command.js +59 -0
- package/plugins/node/commands/clean.command.d.ts +183 -0
- package/plugins/node/commands/clean.command.js +73 -0
- package/plugins/node/index.d.ts +29 -0
- package/plugins/node/index.js +40 -0
- package/plugins/node/node-config.interface.d.ts +77 -0
- package/plugins/node/node-config.interface.js +7 -0
- package/plugins/node/node-manifest.provider.d.ts +68 -0
- package/plugins/node/node-manifest.provider.js +125 -0
- package/plugins/node/node.platform.d.ts +53 -0
- package/plugins/node/node.platform.js +134 -0
- package/plugins/node/npm-publish-target.d.ts +73 -0
- package/plugins/node/npm-publish-target.js +96 -0
- package/plugins/node/services/ci.service.d.ts +47 -0
- package/plugins/node/services/ci.service.js +213 -0
- package/plugins/node/services/clean.service.d.ts +53 -0
- package/plugins/node/services/clean.service.js +237 -0
- package/plugins/node/services/publish.service.d.ts +114 -0
- package/plugins/node/services/publish.service.js +371 -0
- package/plugins/node/services/version-plan.service.d.ts +44 -0
- package/plugins/node/services/version-plan.service.js +58 -0
- package/plugins/node/utils/npm-view.d.ts +48 -0
- package/plugins/node/utils/npm-view.js +71 -0
- package/plugins/node/utils/workspace-range.d.ts +26 -0
- package/plugins/node/utils/workspace-range.js +28 -0
- package/services/change-hash.service.d.ts +2 -2
- package/services/change-hash.service.js +2 -2
- package/services/changelog.service.d.ts +62 -51
- package/services/changelog.service.js +14 -11
- package/services/docker-publish.service.d.ts +50 -29
- package/services/docker-publish.service.js +43 -20
- package/services/exec.service.d.ts +23 -12
- package/services/exec.service.js +14 -9
- package/services/github-release.service.d.ts +44 -33
- package/services/github-release.service.js +13 -10
- package/services/import.service.d.ts +25 -14
- package/services/import.service.js +9 -5
- package/services/list.service.d.ts +62 -10
- package/services/list.service.js +62 -15
- package/services/run.service.d.ts +22 -13
- package/services/run.service.js +262 -223
- package/services/version-plan.service.d.ts +27 -4
- package/services/version-plan.service.js +42 -15
- package/services/version.service.d.ts +31 -11
- package/services/version.service.js +29 -13
- package/targets/docker.target.d.ts +53 -0
- package/targets/docker.target.js +40 -0
- package/utils/bin-path.d.ts +6 -7
- package/utils/bin-path.js +7 -18
- package/utils/branch-guard.d.ts +29 -0
- package/utils/branch-guard.js +31 -0
- package/utils/exec.d.ts +10 -0
- package/utils/exec.js +1 -1
- package/utils/logger.d.ts +1 -1
- package/utils/logger.js +1 -1
- package/utils/package-filter.d.ts +127 -7
- package/utils/package-filter.js +197 -16
- package/utils/printable-config.d.ts +1 -1
- package/utils/printable-config.js +1 -1
- package/utils/run-bin.d.ts +10 -0
- package/utils/run-bin.js +1 -1
- package/utils/run-options.d.ts +97 -0
- package/utils/run-options.js +81 -0
- package/utils/version-stamp.d.ts +1 -1
- package/utils/version-stamp.js +1 -1
package/core/merge-config.d.ts
CHANGED
|
@@ -1,8 +1,19 @@
|
|
|
1
|
-
/**
|
|
2
|
-
|
|
3
|
-
export declare const APPEND_PREFIX = "+";
|
|
1
|
+
/** Where a repository keeps command modules of its own, as a glob or a list of them. */
|
|
2
|
+
export declare const COMMANDS_KEY = "commands";
|
|
4
3
|
/**
|
|
5
|
-
* Keys that **append
|
|
4
|
+
* Keys that **append rather than replace**, which is the only append rman has.
|
|
5
|
+
*
|
|
6
|
+
* **There used to be a `+key` prefix on every key, and it is gone.** It said "add to what this
|
|
7
|
+
* resolved to below", which is exactly what `value` says - and `value` says it better: it composes
|
|
8
|
+
* (three layers each deriving from the one under them), it can reorder or filter rather than only
|
|
9
|
+
* append, and it does not need the merge to keep an append *outstanding* until the layer it belongs
|
|
10
|
+
* to turns up. The prefix also carried a bug `value` does not: appending onto a value that was a
|
|
11
|
+
* sole `${{ }}` expression returning an array nested it, because the merge promoted the expression
|
|
12
|
+
* *string* to a list and interpolation only later turned that element into the array (measured,
|
|
13
|
+
* `[['a','b'],'c']` where a literal list gave `['a','b','c']`).
|
|
14
|
+
*
|
|
15
|
+
* What is left is this list, where appending is not a choice the author makes per layer but what
|
|
16
|
+
* the key *means*.
|
|
6
17
|
*
|
|
7
18
|
* `plugins` is the whole list because it is the one key where replacing is never what anyone meant:
|
|
8
19
|
* every other setting has a value a closer layer can sensibly overrule, while a plugin *adds
|
|
@@ -10,6 +21,12 @@ export declare const APPEND_PREFIX = "+";
|
|
|
10
21
|
* brought. Replacing was the silent failure - `extends`-ing a toolchain config and then adding a
|
|
11
22
|
* plugin of your own dropped the toolchain's, and what you noticed was `Unknown argument: publish`.
|
|
12
23
|
*
|
|
24
|
+
* `commands` and `publishTargets` are the same kind of statement - what this repository has, in
|
|
25
|
+
* instances or in globs naming them - so they append for the same reason: a repository adding one
|
|
26
|
+
* of its own never means "and stop loading the ones my shared config brought". All three are what
|
|
27
|
+
* a config *contributes*, and a contribution list is exactly the case where replacing is never
|
|
28
|
+
* what anyone meant.
|
|
29
|
+
*
|
|
13
30
|
* Do not extend this list casually: a key that always appends can never be *un*-said by a closer
|
|
14
31
|
* layer, which is only acceptable where the value is a set of contributions rather than a decision.
|
|
15
32
|
*/
|
|
@@ -24,7 +41,7 @@ export declare const ALWAYS_APPEND: readonly string[];
|
|
|
24
41
|
* carry one.
|
|
25
42
|
*
|
|
26
43
|
* A symbol is invisible to `Object.entries`, `JSON.stringify` and js-yaml, so the chain travels
|
|
27
|
-
* through `mergeConfig
|
|
44
|
+
* through `mergeConfig` and `rman config` without either of them having to know it
|
|
28
45
|
* is there.
|
|
29
46
|
*
|
|
30
47
|
* Each entry is a link, not a single slot: three layers each deriving from the one below need
|
|
@@ -51,47 +68,29 @@ export interface PreviousValue {
|
|
|
51
68
|
}
|
|
52
69
|
/** Only these two can ask for `value`, so only these two are worth remembering a previous for. */
|
|
53
70
|
export declare function carriesPreviousValue(value: unknown): boolean;
|
|
54
|
-
/** `"+before"` -> `"before"`, or `undefined` for a key that isn't an append. */
|
|
55
|
-
export declare function appendTarget(key: string): string | undefined;
|
|
56
71
|
/**
|
|
57
72
|
* Merges `source` onto `target` in place, the way every layer of rman config is combined - a
|
|
58
73
|
* directory's own file forms, the directory chain, `"[selector]"` blocks, and an `extends` base.
|
|
59
74
|
* One implementation for all of them, so they cannot disagree about what an append means.
|
|
60
75
|
*
|
|
61
|
-
* Plain keys replace
|
|
62
|
-
* adds
|
|
76
|
+
* Plain keys replace and nested objects merge recursively, as a deep merge always has. The two
|
|
77
|
+
* things it adds are the contribution keys, which append instead (`ALWAYS_APPEND`), and the record
|
|
78
|
+
* of what each key held underneath, so a closer layer can derive from it as `value`.
|
|
63
79
|
*
|
|
64
80
|
* ```yaml
|
|
65
|
-
* # the root says
|
|
66
|
-
* # a package
|
|
67
|
-
* # it resolves to
|
|
81
|
+
* # the root says before: "rm ./build"
|
|
82
|
+
* # a package says before: "${{ [...value, 'rm ./cache'] }}"
|
|
83
|
+
* # it resolves to before: ["rm ./build", "rm ./cache"]
|
|
68
84
|
* ```
|
|
69
85
|
*
|
|
70
|
-
*
|
|
71
|
-
*
|
|
72
|
-
*
|
|
73
|
-
*
|
|
74
|
-
* A scalar is promoted to a list on the way, so neither side has to be written as an array. With
|
|
75
|
-
* nothing inherited, `+key` simply produces a one-element list.
|
|
86
|
+
* That is the half a shared config cannot live without: a base declaring `before: ["rm ./build"]`
|
|
87
|
+
* otherwise forces every repository wanting one more step to restate the whole list - which is a
|
|
88
|
+
* copy of the base, silently frozen at the version it was copied from.
|
|
76
89
|
*
|
|
77
|
-
*
|
|
78
|
-
*
|
|
79
|
-
* scalar has nothing to append to, so `+key` behaves exactly as `key` would. Nothing is silently
|
|
80
|
-
* dropped - the value still lands.
|
|
81
|
-
*
|
|
82
|
-
* `key` and `+key` in the same object are both honored, in that order: the replacement happens
|
|
83
|
-
* first, then the append lands on top of it.
|
|
90
|
+
* **A `+key` prefix used to mean this and is refused now**, naming the key and what to write
|
|
91
|
+
* instead - see the check at the top of the loop.
|
|
84
92
|
*/
|
|
85
93
|
export declare function mergeConfig(target: Record<string, any>, source: Record<string, any>,
|
|
86
94
|
/** The file `source` was read from, recorded per key - see `ORIGINS`. A caller merging a value it
|
|
87
95
|
* built rather than read (a selector block already carrying its own origins) passes nothing. */
|
|
88
96
|
origin?: string): Record<string, any>;
|
|
89
|
-
/**
|
|
90
|
-
* Turns any `+key` still outstanding into its plain key, as a list - the "nothing was inherited"
|
|
91
|
-
* case, where an append simply is the whole value.
|
|
92
|
-
*
|
|
93
|
-
* Called once on a fully resolved config, and only there: until then an outstanding append may
|
|
94
|
-
* still find the layer it belongs to, and a config handed to a command must carry no `+key` at all
|
|
95
|
-
* or every reader would have to know about them.
|
|
96
|
-
*/
|
|
97
|
-
export declare function finalizeConfig<T>(config: T): T;
|
package/core/merge-config.js
CHANGED
|
@@ -1,8 +1,23 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
export const
|
|
1
|
+
import path from 'node:path';
|
|
2
|
+
/** Where a repository keeps command modules of its own, as a glob or a list of them. */
|
|
3
|
+
export const COMMANDS_KEY = 'commands';
|
|
4
|
+
/** The keys whose string entries are globs, and so have to be anchored to the file that wrote
|
|
5
|
+
* them - see `anchorContributions`. The same three that always append. */
|
|
6
|
+
const GLOB_KEYS = ['plugins', COMMANDS_KEY, 'publishTargets'];
|
|
4
7
|
/**
|
|
5
|
-
* Keys that **append
|
|
8
|
+
* Keys that **append rather than replace**, which is the only append rman has.
|
|
9
|
+
*
|
|
10
|
+
* **There used to be a `+key` prefix on every key, and it is gone.** It said "add to what this
|
|
11
|
+
* resolved to below", which is exactly what `value` says - and `value` says it better: it composes
|
|
12
|
+
* (three layers each deriving from the one under them), it can reorder or filter rather than only
|
|
13
|
+
* append, and it does not need the merge to keep an append *outstanding* until the layer it belongs
|
|
14
|
+
* to turns up. The prefix also carried a bug `value` does not: appending onto a value that was a
|
|
15
|
+
* sole `${{ }}` expression returning an array nested it, because the merge promoted the expression
|
|
16
|
+
* *string* to a list and interpolation only later turned that element into the array (measured,
|
|
17
|
+
* `[['a','b'],'c']` where a literal list gave `['a','b','c']`).
|
|
18
|
+
*
|
|
19
|
+
* What is left is this list, where appending is not a choice the author makes per layer but what
|
|
20
|
+
* the key *means*.
|
|
6
21
|
*
|
|
7
22
|
* `plugins` is the whole list because it is the one key where replacing is never what anyone meant:
|
|
8
23
|
* every other setting has a value a closer layer can sensibly overrule, while a plugin *adds
|
|
@@ -10,10 +25,16 @@ export const APPEND_PREFIX = '+';
|
|
|
10
25
|
* brought. Replacing was the silent failure - `extends`-ing a toolchain config and then adding a
|
|
11
26
|
* plugin of your own dropped the toolchain's, and what you noticed was `Unknown argument: publish`.
|
|
12
27
|
*
|
|
28
|
+
* `commands` and `publishTargets` are the same kind of statement - what this repository has, in
|
|
29
|
+
* instances or in globs naming them - so they append for the same reason: a repository adding one
|
|
30
|
+
* of its own never means "and stop loading the ones my shared config brought". All three are what
|
|
31
|
+
* a config *contributes*, and a contribution list is exactly the case where replacing is never
|
|
32
|
+
* what anyone meant.
|
|
33
|
+
*
|
|
13
34
|
* Do not extend this list casually: a key that always appends can never be *un*-said by a closer
|
|
14
35
|
* layer, which is only acceptable where the value is a set of contributions rather than a decision.
|
|
15
36
|
*/
|
|
16
|
-
export const ALWAYS_APPEND = ['plugins'];
|
|
37
|
+
export const ALWAYS_APPEND = ['plugins', COMMANDS_KEY, 'publishTargets'];
|
|
17
38
|
/**
|
|
18
39
|
* Where a key keeps what it is replacing, so the replacement can be handed it back as `value`.
|
|
19
40
|
*
|
|
@@ -24,7 +45,7 @@ export const ALWAYS_APPEND = ['plugins'];
|
|
|
24
45
|
* carry one.
|
|
25
46
|
*
|
|
26
47
|
* A symbol is invisible to `Object.entries`, `JSON.stringify` and js-yaml, so the chain travels
|
|
27
|
-
* through `mergeConfig
|
|
48
|
+
* through `mergeConfig` and `rman config` without either of them having to know it
|
|
28
49
|
* is there.
|
|
29
50
|
*
|
|
30
51
|
* Each entry is a link, not a single slot: three layers each deriving from the one below need
|
|
@@ -48,112 +69,61 @@ export const ORIGINS = Symbol('rman.origins');
|
|
|
48
69
|
export function carriesPreviousValue(value) {
|
|
49
70
|
return typeof value === 'function' || (typeof value === 'string' && value.includes('${{'));
|
|
50
71
|
}
|
|
51
|
-
/** `"+before"` -> `"before"`, or `undefined` for a key that isn't an append. */
|
|
52
|
-
export function appendTarget(key) {
|
|
53
|
-
return key.length > APPEND_PREFIX.length && key.startsWith(APPEND_PREFIX)
|
|
54
|
-
? key.slice(APPEND_PREFIX.length)
|
|
55
|
-
: undefined;
|
|
56
|
-
}
|
|
57
72
|
/**
|
|
58
73
|
* Merges `source` onto `target` in place, the way every layer of rman config is combined - a
|
|
59
74
|
* directory's own file forms, the directory chain, `"[selector]"` blocks, and an `extends` base.
|
|
60
75
|
* One implementation for all of them, so they cannot disagree about what an append means.
|
|
61
76
|
*
|
|
62
|
-
* Plain keys replace
|
|
63
|
-
* adds
|
|
77
|
+
* Plain keys replace and nested objects merge recursively, as a deep merge always has. The two
|
|
78
|
+
* things it adds are the contribution keys, which append instead (`ALWAYS_APPEND`), and the record
|
|
79
|
+
* of what each key held underneath, so a closer layer can derive from it as `value`.
|
|
64
80
|
*
|
|
65
81
|
* ```yaml
|
|
66
|
-
* # the root says
|
|
67
|
-
* # a package
|
|
68
|
-
* # it resolves to
|
|
82
|
+
* # the root says before: "rm ./build"
|
|
83
|
+
* # a package says before: "${{ [...value, 'rm ./cache'] }}"
|
|
84
|
+
* # it resolves to before: ["rm ./build", "rm ./cache"]
|
|
69
85
|
* ```
|
|
70
86
|
*
|
|
71
|
-
*
|
|
72
|
-
*
|
|
73
|
-
*
|
|
74
|
-
*
|
|
75
|
-
* A scalar is promoted to a list on the way, so neither side has to be written as an array. With
|
|
76
|
-
* nothing inherited, `+key` simply produces a one-element list.
|
|
87
|
+
* That is the half a shared config cannot live without: a base declaring `before: ["rm ./build"]`
|
|
88
|
+
* otherwise forces every repository wanting one more step to restate the whole list - which is a
|
|
89
|
+
* copy of the base, silently frozen at the version it was copied from.
|
|
77
90
|
*
|
|
78
|
-
*
|
|
79
|
-
*
|
|
80
|
-
* scalar has nothing to append to, so `+key` behaves exactly as `key` would. Nothing is silently
|
|
81
|
-
* dropped - the value still lands.
|
|
82
|
-
*
|
|
83
|
-
* `key` and `+key` in the same object are both honored, in that order: the replacement happens
|
|
84
|
-
* first, then the append lands on top of it.
|
|
91
|
+
* **A `+key` prefix used to mean this and is refused now**, naming the key and what to write
|
|
92
|
+
* instead - see the check at the top of the loop.
|
|
85
93
|
*/
|
|
86
94
|
export function mergeConfig(target, source,
|
|
87
95
|
/** The file `source` was read from, recorded per key - see `ORIGINS`. A caller merging a value it
|
|
88
96
|
* built rather than read (a selector block already carrying its own origins) passes nothing. */
|
|
89
97
|
origin) {
|
|
90
|
-
// Plain keys first, so a `+key` alongside its own `key` appends to that replacement rather than
|
|
91
|
-
// to whatever the previous layer had.
|
|
92
98
|
for (const [key, value] of Object.entries(source)) {
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
99
|
+
/**
|
|
100
|
+
* **A retired `+key` is refused, not ignored.** rman validates no config keys at all - there is
|
|
101
|
+
* no schema behind `.rmanrc`/`.rmanrc.yml` any more - so an unknown key is silent, and a
|
|
102
|
+
* repository upgrading from 1.x with `+before:` in its config would simply lose that step with
|
|
103
|
+
* nothing said. Measured before this check: `+include: ['extra']` resolved to the inherited
|
|
104
|
+
* list unchanged, exactly as if the line were not there.
|
|
105
|
+
*
|
|
106
|
+
* Here rather than in a validator, because this is the one function every layer passes through,
|
|
107
|
+
* and it is the only place that still knows which file the key came from.
|
|
108
|
+
*/
|
|
109
|
+
if (key.length > 1 && key.startsWith('+')) {
|
|
110
|
+
const plain = key.slice(1);
|
|
111
|
+
throw new Error(`"${key}" is no longer a config key${origin ? ` (${origin})` : ''}. The \`+key\` prefix is ` +
|
|
112
|
+
`gone: write "${plain}" as a value that derives from what it inherited - ` +
|
|
113
|
+
`\`${plain}: ({ value }) => [...value, 'x']\`, or \`"\${{ [...value, 'x'] }}"\` in YAML. ` +
|
|
114
|
+
`\`value\` is the layers below this one, and spreads as empty when there are none.`);
|
|
115
|
+
}
|
|
116
|
+
/** `plugins`/`commands`/`publishTargets`: additive at every layer, so the closer one adds
|
|
117
|
+
* rather than takes over. A glob among them is anchored to its own file on the way in - see
|
|
118
|
+
* `anchorContributions`. */
|
|
96
119
|
if (ALWAYS_APPEND.includes(key)) {
|
|
97
|
-
appendList(target, key, value);
|
|
120
|
+
appendList(target, key, GLOB_KEYS.includes(key) ? anchorContributions(value, origin) : value);
|
|
98
121
|
continue;
|
|
99
122
|
}
|
|
100
123
|
assignMerged(target, key, value, source, origin);
|
|
101
124
|
}
|
|
102
|
-
for (const [key, value] of Object.entries(source)) {
|
|
103
|
-
const plain = appendTarget(key);
|
|
104
|
-
if (!plain)
|
|
105
|
-
continue;
|
|
106
|
-
// An object merges either way, so the prefix asks for nothing extra - resolve it now and let
|
|
107
|
-
// the two spellings coincide.
|
|
108
|
-
if (isPlainObject(value) || isPlainObject(target[plain])) {
|
|
109
|
-
assignMerged(target, plain, value, source, origin);
|
|
110
|
-
continue;
|
|
111
|
-
}
|
|
112
|
-
if (plain in target) {
|
|
113
|
-
appendList(target, plain, value);
|
|
114
|
-
continue;
|
|
115
|
-
}
|
|
116
|
-
/** Nothing to append to *yet*. Kept as an append rather than collapsed into the plain key,
|
|
117
|
-
* because the layer that provides it may still be coming: a directory's own file forms are
|
|
118
|
-
* merged into an empty object long before the selector blocks and parent directories they
|
|
119
|
-
* append to are. Collapsing here lost both of those - measured. `finalizeConfig` turns
|
|
120
|
-
* whatever is still outstanding at the end into a plain list. */
|
|
121
|
-
target[key] = [...toList(target[key] ?? []), ...toList(value)];
|
|
122
|
-
}
|
|
123
125
|
return target;
|
|
124
126
|
}
|
|
125
|
-
/**
|
|
126
|
-
* Turns any `+key` still outstanding into its plain key, as a list - the "nothing was inherited"
|
|
127
|
-
* case, where an append simply is the whole value.
|
|
128
|
-
*
|
|
129
|
-
* Called once on a fully resolved config, and only there: until then an outstanding append may
|
|
130
|
-
* still find the layer it belongs to, and a config handed to a command must carry no `+key` at all
|
|
131
|
-
* or every reader would have to know about them.
|
|
132
|
-
*/
|
|
133
|
-
export function finalizeConfig(config) {
|
|
134
|
-
if (Array.isArray(config))
|
|
135
|
-
return config.map(finalizeConfig);
|
|
136
|
-
if (!isPlainObject(config))
|
|
137
|
-
return config;
|
|
138
|
-
const result = {};
|
|
139
|
-
for (const [key, value] of Object.entries(config)) {
|
|
140
|
-
const plain = appendTarget(key);
|
|
141
|
-
if (!plain) {
|
|
142
|
-
result[key] = finalizeConfig(value);
|
|
143
|
-
continue;
|
|
144
|
-
}
|
|
145
|
-
const pending = finalizeConfig(value);
|
|
146
|
-
result[plain] = plain in result ? [...toList(result[plain]), ...toList(pending)] : toList(pending);
|
|
147
|
-
}
|
|
148
|
-
/** Carried across by hand: this rebuilds the object from `Object.entries`, which does not see a
|
|
149
|
-
* symbol - and dropping it here would lose every `value` chain the merge just recorded. */
|
|
150
|
-
for (const carried of [PREVIOUS_VALUES, ORIGINS]) {
|
|
151
|
-
const value = config[carried];
|
|
152
|
-
if (value)
|
|
153
|
-
Object.defineProperty(result, carried, { value });
|
|
154
|
-
}
|
|
155
|
-
return result;
|
|
156
|
-
}
|
|
157
127
|
function assignMerged(target, key, value, source, origin) {
|
|
158
128
|
/** A source that already carries origins wins over the caller's: an `extends` base keeps the file
|
|
159
129
|
* its own keys were written in, rather than being attributed to the file that named it. */
|
|
@@ -185,18 +155,48 @@ function assignMerged(target, key, value, source, origin) {
|
|
|
185
155
|
* layers - by the time `interpolateConfig` sees the config they have collapsed into one object,
|
|
186
156
|
* and whatever a closer layer said has already taken the place of what it was derived from.
|
|
187
157
|
*/
|
|
188
|
-
|
|
158
|
+
/**
|
|
159
|
+
* **A chain already on `source` is carried over**, the way its `ORIGINS` are just above - and for
|
|
160
|
+
* the same reason: `source` may itself be several layers already merged, and only the merge knows
|
|
161
|
+
* their order.
|
|
162
|
+
*
|
|
163
|
+
* Without this, a chain recorded *inside* a source was silently dropped whenever the key was
|
|
164
|
+
* absent from the target, because the link below was only ever recorded for a key being
|
|
165
|
+
* *replaced*. The shape that hit it is the ordinary one for a shared config: a base and its
|
|
166
|
+
* consumer both writing `"[*]"`. Those two blocks merge into one before `matchingSelectors` sees
|
|
167
|
+
* them - recording the chain on the merged block - and that block is then merged into a `result`
|
|
168
|
+
* which has no such key, so the chain went nowhere.
|
|
169
|
+
*
|
|
170
|
+
* Measured, on a base declaring `clean.include: ['build']` and a consumer's `"[*]"` deriving from
|
|
171
|
+
* it: `${{ [...value, 'dist'] }}` answered `['dist']`, losing `build` outright. It answers
|
|
172
|
+
* `['build', 'dist']` now. Two *different* selectors (`"[*]"` then `"[pkg-a]"`) always worked,
|
|
173
|
+
* and so did an unmarked key, which is why this went unnoticed - those merge into a target that
|
|
174
|
+
* already holds the key.
|
|
175
|
+
*/
|
|
176
|
+
const sourceChain = source[PREVIOUS_VALUES]?.[key];
|
|
177
|
+
if (carriesPreviousValue(value) && (key in target || sourceChain)) {
|
|
189
178
|
const carrier = target;
|
|
190
179
|
const chain = (carrier[PREVIOUS_VALUES] ??= {});
|
|
191
|
-
|
|
180
|
+
/** The layer the target itself stands for, bottom-most of the three: what it holds now, over
|
|
181
|
+
* whatever *that* was derived from. Absent when the target never had the key. */
|
|
182
|
+
const below = key in target ? { value: target[key], previous: chain[key] } : chain[key];
|
|
183
|
+
/** Bottom-up: the target's layer, then `source`'s own intermediate ones, then `value` on top -
|
|
184
|
+
* so `source`'s chain keeps its internal order and gets the target's spliced beneath it. */
|
|
185
|
+
chain[key] = sourceChain ? graftChain(sourceChain, below) : below;
|
|
192
186
|
}
|
|
193
187
|
target[key] = Array.isArray(value) ? [...value] : value;
|
|
194
188
|
}
|
|
189
|
+
/** `node`'s chain, copied with `tail` spliced in beneath its deepest link - so two layer-stacks
|
|
190
|
+
* join into one without either being mutated (a chain is shared by every package that resolved
|
|
191
|
+
* through it, so grafting in place would rewrite what the others see). */
|
|
192
|
+
function graftChain(node, tail) {
|
|
193
|
+
return { value: node.value, previous: node.previous ? graftChain(node.previous, tail) : tail };
|
|
194
|
+
}
|
|
195
195
|
/**
|
|
196
196
|
* Appends `value` to `target[key]`, de-duplicating **only** an `ALWAYS_APPEND` key.
|
|
197
197
|
*
|
|
198
198
|
* That asymmetry is the point. `plugins` appends without being asked, so a repository and the config
|
|
199
|
-
* it extends both naming `'
|
|
199
|
+
* it extends both naming `'node'` is the ordinary case rather than a mistake, and the list is
|
|
200
200
|
* also what `rman config` prints. An explicit `+before`, by contrast, was *written* - repeating a
|
|
201
201
|
* step that is already there is a strange thing to ask for, but it is what was asked for, and
|
|
202
202
|
* silently collapsing it would make one layer's list depend on another's contents.
|
|
@@ -212,6 +212,51 @@ function appendList(target, key, value) {
|
|
|
212
212
|
function toList(value) {
|
|
213
213
|
return Array.isArray(value) ? value : [value];
|
|
214
214
|
}
|
|
215
|
+
/**
|
|
216
|
+
* Anchors every glob in `plugins`/`commands`/`publishTargets` to the directory of the file that
|
|
217
|
+
* declared it, on the way in. A non-string entry - an instance written straight into the config -
|
|
218
|
+
* passes through untouched.
|
|
219
|
+
*
|
|
220
|
+
* **Done here, at the merge, because this is the last moment the answer is known.** `commands`
|
|
221
|
+
* always appends, so one resolved list ends up holding entries from the repository's own
|
|
222
|
+
* `.rmanrc`, from each `extends` base, and from every directory above - and `ORIGINS` records one
|
|
223
|
+
* file per *key*, not per element, so after the merge there is nothing left to attribute them by.
|
|
224
|
+
* Rewriting each glob as it arrives makes the merge trivially correct and costs one `path.resolve`.
|
|
225
|
+
*
|
|
226
|
+
* It is what lets a **shared config ship its own contributions**: `commands: './commands/*.js'`
|
|
227
|
+
* in a published package means that package's directory, wherever the repository inheriting it
|
|
228
|
+
* happens to sit. All three keys behave the same way; `plugins` used to resolve every entry
|
|
229
|
+
* against the repository root instead, whatever file declared it, and that asymmetry is gone.
|
|
230
|
+
*
|
|
231
|
+
* `origin` is absent when a caller merges a value it built rather than read (a selector block, the
|
|
232
|
+
* directory chain layering already-resolved configs); those globs have been anchored already, and
|
|
233
|
+
* an absolute path is left alone by `path.resolve` anyway.
|
|
234
|
+
*/
|
|
235
|
+
function anchorContributions(value, origin) {
|
|
236
|
+
if (!origin)
|
|
237
|
+
return value;
|
|
238
|
+
const dir = path.dirname(origin);
|
|
239
|
+
const anchor = (entry) => typeof entry === 'string' && !looksLikePackageName(entry) ? path.resolve(dir, entry) : entry;
|
|
240
|
+
return Array.isArray(value) ? value.map(anchor) : anchor(value);
|
|
241
|
+
}
|
|
242
|
+
/**
|
|
243
|
+
* Whether an entry is shaped like a **package name** rather than a glob - `rman-node`,
|
|
244
|
+
* `@panates/rman-node`, but not `*.js`, `./x.js` or `commands/*.mjs`.
|
|
245
|
+
*
|
|
246
|
+
* Such an entry is left unanchored, because it is not a relative path and turning it into one
|
|
247
|
+
* destroys the only evidence of what the author meant. A package name is never valid in these keys
|
|
248
|
+
* (a package's config arrives through `extends`), so the whole value of keeping it intact is the
|
|
249
|
+
* error message: anchored, `plugins: ['rman-node']` failed with `glob ".../rman-node" matched no
|
|
250
|
+
* file`, which sends the reader to check their paths. `loadPlugins` can now say what they actually
|
|
251
|
+
* wrote and what to write instead - which two doc pages already promised it did.
|
|
252
|
+
*
|
|
253
|
+
* Shape, not a resolver call: decidable without touching the disk, and a wrong guess only chooses
|
|
254
|
+
* which of two error messages a failing entry gets. An extension is excluded so a bare `plugin.js`
|
|
255
|
+
* beside the config is still anchored as the relative path it is.
|
|
256
|
+
*/
|
|
257
|
+
function looksLikePackageName(entry) {
|
|
258
|
+
return /^(?:@[a-z0-9-~][\w.-]*\/)?[a-z0-9-~][\w.-]*$/i.test(entry) && !/\.[cm]?js$/i.test(entry);
|
|
259
|
+
}
|
|
215
260
|
/** A config object, as opposed to an array or anything with its own prototype - only the former
|
|
216
261
|
* merges key by key. */
|
|
217
262
|
function isPlainObject(value) {
|
package/core/package.d.ts
CHANGED
|
@@ -1,15 +1,17 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type { RmanApplication } from './application.js';
|
|
2
|
+
import type { ResolvedConfig } from './config.js';
|
|
2
3
|
import { Manifest } from './manifest.js';
|
|
4
|
+
import type { Platform } from './plugin.js';
|
|
3
5
|
import type { Repository } from './repository.js';
|
|
4
6
|
import { type VersionScheme } from './version-scheme.js';
|
|
5
7
|
export declare class Package {
|
|
6
8
|
readonly dirname: string;
|
|
7
9
|
/**
|
|
8
|
-
* This package's identity, read through whichever `
|
|
10
|
+
* This package's identity, read through whichever `Plugin`'s manifest members recognizes its directory.
|
|
9
11
|
*
|
|
10
12
|
* There is no `json` here any more, and that is the point: `package.json` is npm's answer to
|
|
11
13
|
* "where is a package's name and version written", not rman's. `manifest.raw` is still the whole
|
|
12
|
-
* document for a command that knows its own ecosystem - `
|
|
14
|
+
* document for a command that knows its own ecosystem - the `node` built-in reads `scripts` and
|
|
13
15
|
* `publishConfig` off it - but the core only ever touches `name`, `version` and `private`.
|
|
14
16
|
*/
|
|
15
17
|
manifest: Manifest;
|
|
@@ -23,9 +25,16 @@ export declare class Package {
|
|
|
23
25
|
* whatever the ecosystem, and comparing by identity removes a lookup from every consumer.
|
|
24
26
|
*/
|
|
25
27
|
dependencies: Package[];
|
|
26
|
-
/**
|
|
27
|
-
*
|
|
28
|
-
|
|
28
|
+
/**
|
|
29
|
+
* Effective rman config for this package, cascaded from the repository root, with every
|
|
30
|
+
* `${{ ... }}` expression already evaluated.
|
|
31
|
+
*
|
|
32
|
+
* **`ResolvedConfig`, not `RmanConfig`, and that is the whole two-view split in one line.**
|
|
33
|
+
* `RmanConfig` is what an *author* writes, where a value may be a function; this is what a
|
|
34
|
+
* *reader* gets, where it has already been called. Derived from the one the author writes, so
|
|
35
|
+
* there is no second type to keep in step - see `Resolved`.
|
|
36
|
+
*/
|
|
37
|
+
config: ResolvedConfig;
|
|
29
38
|
/**
|
|
30
39
|
* The repository this package belongs to - so anything holding a package can reach the whole
|
|
31
40
|
* picture (its siblings, the root's config, git) without being handed it separately.
|
|
@@ -33,14 +42,54 @@ export declare class Package {
|
|
|
33
42
|
* Assigned by `Repository.create` rather than taken as a constructor argument, and it has to be:
|
|
34
43
|
* `Repository extends Package`, so a repository constructing itself runs this constructor before
|
|
35
44
|
* it exists to be passed in. A repository's own is itself.
|
|
45
|
+
*
|
|
46
|
+
* **Non-enumerable, and `declare` for the same reason `parent` is** - this is the *other* half of
|
|
47
|
+
* why a package could not be serialized, and the older half. A `Repository` holds every package,
|
|
48
|
+
* so one enumerable back-reference makes `JSON.stringify(anyPackage)` a cycle whatever the tree
|
|
49
|
+
* edges do: measured before `parent` was touched at all, and the error even named it
|
|
50
|
+
* (`property 'repository' closes the circle`). Making only `parent` non-enumerable would have
|
|
51
|
+
* delivered a tree that still cannot be dumped, which is the whole reason the asymmetry exists.
|
|
52
|
+
*
|
|
53
|
+
* It is the same rule `Repository.app`, `_repoScope` and `_git` already follow: a back-reference
|
|
54
|
+
* to something that holds everything has no business in a walk of one package.
|
|
36
55
|
*/
|
|
37
56
|
repository: Repository;
|
|
38
57
|
/**
|
|
39
58
|
* The package whose directory contains this one - the repository root for an ordinary member, and
|
|
40
59
|
* a genuine enclosing package for one nested inside another (which `Repository.currentPackage`
|
|
41
60
|
* already has to reason about). `undefined` for the root itself, which nothing contains.
|
|
61
|
+
*
|
|
62
|
+
* **Non-enumerable, and `children` is not** - the two halves of one edge, and only one of them
|
|
63
|
+
* can be the one a walk follows. A tree is walked downwards, so `children` has to be visible and
|
|
64
|
+
* `parent` must not be, or a `toEqual` diff climbs back to the root and down again. Assigned
|
|
65
|
+
* through `defineProperty` by `Repository._linkPackages`, the same way `Repository.app` and
|
|
66
|
+
* `ORIGINS` travel.
|
|
67
|
+
*
|
|
68
|
+
* **`declare`, and that is load-bearing.** A plain `readonly parent?: Package` is a *class field*
|
|
69
|
+
* under this target, so TypeScript emits `parent;` and every package gets an **enumerable**
|
|
70
|
+
* `undefined` that the later `defineProperty` only replaces on the packages that have a parent.
|
|
71
|
+
* Measured: `Object.keys(rootPackage)` listed `parent` while `Object.keys(pkg-a)` did not, which
|
|
72
|
+
* is the exact opposite of what either name suggests. `declare` emits nothing, so the property
|
|
73
|
+
* exists only where it is defined.
|
|
74
|
+
*
|
|
75
|
+
* **It does not make a `Package` JSON-serializable, and nothing here claims it does** - see
|
|
76
|
+
* `repository`, which is enumerable and points back at an object holding every package.
|
|
77
|
+
*/
|
|
78
|
+
readonly parent?: Package;
|
|
79
|
+
/**
|
|
80
|
+
* The packages whose directories sit directly inside this one - **the tree edge**, in the order
|
|
81
|
+
* the platform that claimed this directory gave them.
|
|
82
|
+
*
|
|
83
|
+
* This is the shape discovery actually has, and it used to be flattened away: a provider was
|
|
84
|
+
* asked once at the repository root and returned one list, so a package nested inside another was
|
|
85
|
+
* only reconstructible by comparing path prefixes (which `_linkPackages` and `currentPackage`
|
|
86
|
+
* both did, separately). `Workspace.walk` descends, so the containment is known as it is found -
|
|
87
|
+
* and `Repository.packages` is now this tree flattened rather than the other way round.
|
|
88
|
+
*
|
|
89
|
+
* Empty for a leaf, and for every package in an ordinary flat monorepo - where the root's
|
|
90
|
+
* `children` is the whole member list.
|
|
42
91
|
*/
|
|
43
|
-
|
|
92
|
+
readonly children: Package[];
|
|
44
93
|
/**
|
|
45
94
|
* How this package's versions are numbered - `pkg.versionScheme.next(pkg.version, 'minor')`.
|
|
46
95
|
*
|
|
@@ -57,27 +106,106 @@ export declare class Package {
|
|
|
57
106
|
* changed (a commit's path list). Empty when no provider recognized this directory. */
|
|
58
107
|
manifestFileName: string;
|
|
59
108
|
/**
|
|
60
|
-
* **
|
|
61
|
-
*
|
|
109
|
+
* **What addresses this package**: what a `.rmanrc "[glob]"` block and `--scope`/`--ignore` match
|
|
110
|
+
* against, and what must be unique within the repository.
|
|
111
|
+
*
|
|
112
|
+
* Three sources, first one that answers:
|
|
113
|
+
*
|
|
114
|
+
* 1. the package's own `.rmanrc "name"` - the repository assigning one;
|
|
115
|
+
* 2. its platform's `manifestProvider.selector`;
|
|
116
|
+
* 3. the manifest's own `name`, which is the default that answer falls back to.
|
|
117
|
+
*
|
|
118
|
+
* **Not `name`, and the split is the point.** `name` is what the package calls itself, read from
|
|
119
|
+
* its manifest, and it is an *ecosystem's* promise that such a thing exists and identifies the
|
|
120
|
+
* package - npm's promise, not rman's. Selectors matched `pkg.name` until this existed, so a
|
|
121
|
+
* repository whose technology has no name concept had packages it could not address at all, and
|
|
122
|
+
* one whose names are not unique (or are import paths) could only address them badly. They
|
|
123
|
+
* coincide for every Node repository, which is why nothing had to change for one.
|
|
124
|
+
*
|
|
125
|
+
* **The root's is nearly unused, deliberately.** A glob never matches the root and `"[/]"` needs
|
|
126
|
+
* no name - the root is addressed structurally, which is the whole reason it is `/`. It still has
|
|
127
|
+
* one so that nothing has to special-case it.
|
|
128
|
+
*
|
|
129
|
+
* Assigned by `Repository.create`, which is what has the config; a bare `new Package(dir, app)`
|
|
130
|
+
* gets the manifest's name, which is sources 2 and 3 with no config to consult.
|
|
131
|
+
*/
|
|
132
|
+
selector: string;
|
|
133
|
+
/**
|
|
134
|
+
* **The technology this package belongs to** - the platform whose manifest provider claimed the
|
|
135
|
+
* directory, or `basePlatform` when none did.
|
|
136
|
+
*
|
|
137
|
+
* Per *package*, not per repository: the question is asked per directory, so a polyglot monorepo
|
|
138
|
+
* can hold a `node` package beside a `cargo` one and a command sweeping `getPackages()` can tell
|
|
139
|
+
* them apart. It is also what carries the rest of the technology's answers - where its binaries
|
|
140
|
+
* live, where its scripts come from, how its releases are planned - so anything that used to walk
|
|
141
|
+
* four separate registries asking "is this yours?" now asks the package it already has.
|
|
142
|
+
*/
|
|
143
|
+
platform: Platform;
|
|
144
|
+
/**
|
|
145
|
+
* **Which ecosystem this package belongs to** - `'node'` for one the `node` built-in read. Empty when
|
|
146
|
+
* no stack claimed the directory.
|
|
62
147
|
*
|
|
63
148
|
* The escape hatch for code that legitimately knows one technology: `if (pkg.provider === 'node')`
|
|
64
|
-
* before reaching into `manifest.raw` for something only npm has.
|
|
65
|
-
* repository, because `Manifest.read` asks per directory - a polyglot monorepo can hold a `node`
|
|
66
|
-
* package beside a `cargo` one, and a command sweeping over `getPackages()` has to be able to
|
|
67
|
-
* tell.
|
|
149
|
+
* before reaching into `manifest.raw` for something only npm has.
|
|
68
150
|
*
|
|
69
151
|
* Not a union type on purpose: the set of ecosystems is whatever the repository's `plugins`
|
|
70
152
|
* contribute, so narrowing it here would mean the core listing plugins it cannot know about.
|
|
71
153
|
*/
|
|
72
|
-
provider: string;
|
|
73
|
-
|
|
154
|
+
get provider(): string;
|
|
155
|
+
/**
|
|
156
|
+
* **Takes the application but does not keep it.** A package needs it once, to find out which
|
|
157
|
+
* technology claims its directory; afterwards it holds only data, so nothing that has a package
|
|
158
|
+
* can reach a service through it. Data down, behaviour up - the work belongs to services, and a
|
|
159
|
+
* piece of code holding only a package is not doing any.
|
|
160
|
+
*
|
|
161
|
+
* It also keeps the package out of every spread and serialization the application would
|
|
162
|
+
* otherwise be dragged into: `{...pkg}` and `pkg.manifest.raw` are both real, and an `app` field
|
|
163
|
+
* here would carry the whole world into them.
|
|
164
|
+
*/
|
|
165
|
+
constructor(dirname: string, app: RmanApplication,
|
|
166
|
+
/**
|
|
167
|
+
* The technology that claimed this directory, when the caller already knows - which
|
|
168
|
+
* `Repository.create` does, because the walk that found the directory is what established it.
|
|
169
|
+
*
|
|
170
|
+
* Optional so a bare `new Package(dir, app)` still works: that is what the fixtures build, and
|
|
171
|
+
* it is also the honest fallback for anyone constructing a package outside a walk. It costs one
|
|
172
|
+
* search of the registry (`app.platformFor`), which is what *every* construction used to do.
|
|
173
|
+
*/
|
|
174
|
+
platform?: Platform);
|
|
175
|
+
/** What this package's **platform** says addresses it, before any config is consulted - the
|
|
176
|
+
* manifest's own name when the platform has no opinion, and the directory when it has no name
|
|
177
|
+
* either (which is unique among siblings and is all there is to go on). */
|
|
178
|
+
platformSelector(): string;
|
|
74
179
|
get basename(): string;
|
|
75
180
|
get name(): string;
|
|
76
181
|
get version(): string;
|
|
77
182
|
get isPrivate(): boolean;
|
|
78
|
-
/**
|
|
79
|
-
*
|
|
183
|
+
/**
|
|
184
|
+
* Whether this is the repository's **own root package** - what `--scope /` and `.rmanrc`'s
|
|
185
|
+
* `"[/]"` both select.
|
|
186
|
+
*
|
|
187
|
+
* **By directory, and deliberately not by name or by identity.** The documented rule is that the
|
|
188
|
+
* root package is the one whose directory *is* the repository root, because a name can be
|
|
189
|
+
* anything - and identity (`this === repository.rootPackage`) is not equivalent either:
|
|
190
|
+
* `Repository extends Package` while holding a separate `rootPackage` instance for the same
|
|
191
|
+
* directory, so a comparison by reference answers `false` for one of the two objects that are
|
|
192
|
+
* both, truthfully, the root.
|
|
193
|
+
*
|
|
194
|
+
* `false` before `Repository.create` has assigned `repository` - a bare `new Package(dir, app)`
|
|
195
|
+
* (which the test fixtures build) belongs to no repository yet, so there is no root for it to be.
|
|
196
|
+
*/
|
|
197
|
+
get isRoot(): boolean;
|
|
198
|
+
/**
|
|
199
|
+
* Re-reads from disk - for a command that has just written the manifest itself and wants the
|
|
200
|
+
* package to agree with the file again.
|
|
201
|
+
*
|
|
202
|
+
* Through **its own** technology's provider, like the constructor: the package already knows
|
|
203
|
+
* which platform claimed it, and a second opinion on a re-read was never wanted.
|
|
204
|
+
*/
|
|
80
205
|
reloadManifest(): Manifest;
|
|
81
206
|
/** Writes the current manifest back through its provider. */
|
|
82
207
|
writeManifest(): void;
|
|
208
|
+
/** The three fields a manifest read sets, in one place - so construction and `reloadManifest`
|
|
209
|
+
* cannot disagree about what "reading the manifest" means. */
|
|
210
|
+
private _readManifest;
|
|
83
211
|
}
|