@sous-io/sous 0.2.37 → 1.0.1
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 +14 -256
- package/dist/bin.js +11 -0
- package/dist/sous.js +1093 -0
- package/docs/markdown/README.md +5 -4
- package/docs/markdown/_sidebar.md +21 -1
- package/docs/markdown/commands.md +294 -431
- package/docs/markdown/config-discovery.md +25 -14
- package/docs/markdown/config-inspection.md +53 -31
- package/docs/markdown/config-layers.md +168 -66
- package/docs/markdown/config-variables.md +44 -11
- package/docs/markdown/configuration.md +104 -17
- package/docs/markdown/design-principles.md +4 -1
- package/docs/markdown/repositories-authoring.md +30 -0
- package/docs/markdown/repositories-consuming.md +72 -14
- package/docs/markdown/repositories-file-formats.md +31 -13
- package/docs/markdown/repositories-providers.md +48 -57
- package/docs/markdown/repositories-quickstart.md +3 -2
- package/docs/markdown/repositories-troubleshooting.md +27 -1
- package/docs/markdown/repositories-variables.md +6 -1
- package/docs/markdown/repositories.md +18 -8
- package/package.json +48 -107
- package/recipes/core/sous-skills/skills/about-liquid-templates/SKILL.tpl.md +4 -6
- package/recipes/core/sous-skills/skills/about-liquid-templates/references/liquid-filters.tpl.md +2 -0
- package/recipes/core/sous-skills/skills/about-sous/SKILL.tpl.md +10 -9
- package/recipes/core/sous-skills/skills/about-sous-configuration/SKILL.tpl.md +35 -14
- package/recipes/core/sous-skills/skills/about-sous-recipes/SKILL.tpl.md +51 -20
- package/recipes/core/sous-skills/sous.recipe.yaml +1 -1
- package/sous.config.schema.json +351 -132
- package/bin/run.js +0 -51
- package/src/base-command.ts +0 -457
- package/src/commands/build.ts +0 -181
- package/src/commands/clear.ts +0 -79
- package/src/commands/compile.ts +0 -155
- package/src/commands/config/get.ts +0 -110
- package/src/commands/config/show.ts +0 -32
- package/src/commands/config/validate.ts +0 -53
- package/src/commands/help.ts +0 -46
- package/src/commands/init.ts +0 -289
- package/src/commands/launch.ts +0 -139
- package/src/commands/lock/rebuild.ts +0 -239
- package/src/commands/lock/show.ts +0 -115
- package/src/commands/namespace/list.ts +0 -138
- package/src/commands/namespace/show.ts +0 -130
- package/src/commands/prune.ts +0 -43
- package/src/commands/recipe/list.ts +0 -112
- package/src/commands/recipe/show.ts +0 -439
- package/src/commands/repo/add.ts +0 -145
- package/src/commands/repo/contribute.ts +0 -604
- package/src/commands/repo/gc.ts +0 -173
- package/src/commands/repo/init.ts +0 -136
- package/src/commands/repo/link.ts +0 -899
- package/src/commands/repo/list.ts +0 -236
- package/src/commands/repo/release.ts +0 -685
- package/src/commands/repo/remove.ts +0 -194
- package/src/commands/repo/search.ts +0 -243
- package/src/commands/repo/submit.ts +0 -341
- package/src/commands/repo/unlink.ts +0 -461
- package/src/commands/subscription/add.ts +0 -286
- package/src/commands/subscription/list.ts +0 -208
- package/src/commands/subscription/remove.ts +0 -182
- package/src/commands/subscription/update.ts +0 -216
- package/src/commands/update.ts +0 -178
- package/src/commands/vars/ask.ts +0 -417
- package/src/commands/vars/index.ts +0 -79
- package/src/commands/vars/list.ts +0 -67
- package/src/commands/vars/show.ts +0 -77
- package/src/config-command.ts +0 -30
- package/src/lib/build-preparation.ts +0 -128
- package/src/lib/build-service.ts +0 -580
- package/src/lib/config-discovery.ts +0 -378
- package/src/lib/config-inspect.ts +0 -145
- package/src/lib/config-kernel.mjs +0 -379
- package/src/lib/config-schema.ts +0 -401
- package/src/lib/env-file.ts +0 -328
- package/src/lib/env-local.ts +0 -212
- package/src/lib/errors.ts +0 -32
- package/src/lib/glob-pattern.ts +0 -24
- package/src/lib/include-resolver.ts +0 -523
- package/src/lib/interactive.ts +0 -165
- package/src/lib/markdown-compiler.ts +0 -947
- package/src/lib/package-info.ts +0 -25
- package/src/lib/pid-service.ts +0 -99
- package/src/lib/project-install.d.mts +0 -44
- package/src/lib/project-install.mjs +0 -234
- package/src/lib/project-scaffold/index.ts +0 -332
- package/src/lib/project-scaffold/templates.ts +0 -240
- package/src/lib/repos/catalog-display.ts +0 -215
- package/src/lib/repos/catalog-inputs.ts +0 -288
- package/src/lib/repos/catalog.ts +0 -842
- package/src/lib/repos/contribute.ts +0 -452
- package/src/lib/repos/core-recipe.ts +0 -105
- package/src/lib/repos/declarations.ts +0 -187
- package/src/lib/repos/defaults.ts +0 -175
- package/src/lib/repos/formats/common.ts +0 -440
- package/src/lib/repos/formats/index-file.ts +0 -253
- package/src/lib/repos/formats/links-map.ts +0 -98
- package/src/lib/repos/formats/lockfile.ts +0 -169
- package/src/lib/repos/formats/patterns.ts +0 -57
- package/src/lib/repos/formats/recipe-manifest.ts +0 -205
- package/src/lib/repos/formats/repo-manifest.ts +0 -97
- package/src/lib/repos/formats/store-entry.ts +0 -84
- package/src/lib/repos/formats/variable-definition.ts +0 -268
- package/src/lib/repos/freshness.ts +0 -264
- package/src/lib/repos/git-clone.ts +0 -850
- package/src/lib/repos/identity.ts +0 -89
- package/src/lib/repos/index.ts +0 -57
- package/src/lib/repos/links.ts +0 -356
- package/src/lib/repos/load-manifest.ts +0 -237
- package/src/lib/repos/lock-service.ts +0 -454
- package/src/lib/repos/locked-namespace-resolver.ts +0 -232
- package/src/lib/repos/locked-recipe-lookup.ts +0 -123
- package/src/lib/repos/locked-recipes.ts +0 -254
- package/src/lib/repos/managed-layer.ts +0 -422
- package/src/lib/repos/memories-hash-name.ts +0 -33
- package/src/lib/repos/namespace-resolver.ts +0 -527
- package/src/lib/repos/providers/base.ts +0 -268
- package/src/lib/repos/providers/git.ts +0 -245
- package/src/lib/repos/providers/github.ts +0 -589
- package/src/lib/repos/providers/gitlab.ts +0 -332
- package/src/lib/repos/providers/http.ts +0 -128
- package/src/lib/repos/providers/index-cache.ts +0 -421
- package/src/lib/repos/providers/index.ts +0 -106
- package/src/lib/repos/providers/local.ts +0 -410
- package/src/lib/repos/providers/provider.ts +0 -615
- package/src/lib/repos/recipe-config-layers.ts +0 -316
- package/src/lib/repos/recipe-key-matcher.ts +0 -62
- package/src/lib/repos/recipe-memories.ts +0 -178
- package/src/lib/repos/recipe-targets.ts +0 -236
- package/src/lib/repos/ref-search.ts +0 -46
- package/src/lib/repos/release/bump.ts +0 -161
- package/src/lib/repos/release/changelog.ts +0 -461
- package/src/lib/repos/release/git-state.ts +0 -460
- package/src/lib/repos/release/index-builder.ts +0 -1108
- package/src/lib/repos/release/index.ts +0 -19
- package/src/lib/repos/release/plan.ts +0 -521
- package/src/lib/repos/release/settle.ts +0 -154
- package/src/lib/repos/release/submissions.ts +0 -214
- package/src/lib/repos/release/submit-checkout.ts +0 -290
- package/src/lib/repos/release/submit-questions.ts +0 -153
- package/src/lib/repos/release/submit-service.ts +0 -898
- package/src/lib/repos/release/tags.ts +0 -239
- package/src/lib/repos/release/validate.ts +0 -463
- package/src/lib/repos/resolver.ts +0 -1028
- package/src/lib/repos/scaffold/index.ts +0 -245
- package/src/lib/repos/scaffold/templates.ts +0 -517
- package/src/lib/repos/seed.ts +0 -473
- package/src/lib/repos/store/contract.ts +0 -64
- package/src/lib/repos/store/hash.ts +0 -191
- package/src/lib/repos/store/recipe-store.ts +0 -599
- package/src/lib/repos/store/settings.ts +0 -58
- package/src/lib/repos/subscription-service.ts +0 -3859
- package/src/lib/repos/trust.ts +0 -447
- package/src/lib/repos/update-plan.ts +0 -235
- package/src/lib/self-update/index.ts +0 -14
- package/src/lib/self-update/installs.ts +0 -413
- package/src/lib/self-update/managers.ts +0 -126
- package/src/lib/self-update/plan.ts +0 -315
- package/src/lib/self-update/registry.ts +0 -99
- package/src/lib/self-update/run.ts +0 -506
- package/src/lib/self-update/versions.ts +0 -243
- package/src/lib/settings.ts +0 -1107
- package/src/lib/sous-home.ts +0 -104
- package/src/lib/state.ts +0 -167
- package/src/lib/vars/answers.ts +0 -192
- package/src/lib/vars/ask.ts +0 -1152
- package/src/lib/vars/definition-source.ts +0 -261
- package/src/lib/vars/display.ts +0 -231
- package/src/lib/vars/index.ts +0 -20
- package/src/lib/vars/ladder.ts +0 -282
- package/src/lib/vars/mappings.ts +0 -260
- package/src/lib/vars/names.ts +0 -94
- package/src/lib/vars/preanswers.ts +0 -395
- package/src/lib/vars/question-plan.ts +0 -241
- package/src/lib/vars/report.ts +0 -228
- package/src/lib/vars/safe-regex.ts +0 -235
- package/src/lib/vars/secrets.ts +0 -131
- package/src/lib/vars/validate.ts +0 -312
- package/src/lib/version-report.ts +0 -90
- package/src/lib/watch-loop.ts +0 -148
- package/src/lib/watch-service.ts +0 -116
- package/src/services/ref-resolver/container.ts +0 -107
- package/src/services/ref-resolver/dependency.ts +0 -60
- package/src/services/ref-resolver/format.ts +0 -197
- package/src/services/ref-resolver/glob.ts +0 -115
- package/src/services/ref-resolver/hash-names.ts +0 -155
- package/src/services/ref-resolver/index.ts +0 -55
- package/src/services/ref-resolver/injectable.ts +0 -36
- package/src/services/ref-resolver/location.ts +0 -62
- package/src/services/ref-resolver/lookups/cached-index-lookup.ts +0 -53
- package/src/services/ref-resolver/lookups/catalog-lookup.ts +0 -23
- package/src/services/ref-resolver/lookups/catalog-matcher.ts +0 -261
- package/src/services/ref-resolver/lookups/chained-lookup.ts +0 -27
- package/src/services/ref-resolver/lookups/env-var-lookup.ts +0 -65
- package/src/services/ref-resolver/lookups/fetched-index-lookup.ts +0 -150
- package/src/services/ref-resolver/lookups/recorded-dependency-lookup.ts +0 -62
- package/src/services/ref-resolver/lookups/ref-lookup.ts +0 -54
- package/src/services/ref-resolver/lookups/variable-lookup.ts +0 -123
- package/src/services/ref-resolver/named-refs.ts +0 -144
- package/src/services/ref-resolver/parser/env-var-splitter.ts +0 -27
- package/src/services/ref-resolver/parser/location-splitter.ts +0 -239
- package/src/services/ref-resolver/parser/name-path-splitter.ts +0 -200
- package/src/services/ref-resolver/parser/partial-ref.ts +0 -84
- package/src/services/ref-resolver/parser/query-splitter.ts +0 -61
- package/src/services/ref-resolver/parser/range-splitter.ts +0 -52
- package/src/services/ref-resolver/parser/ref-parser.ts +0 -115
- package/src/services/ref-resolver/parser/repo-qualifier-splitter.ts +0 -51
- package/src/services/ref-resolver/parts.ts +0 -115
- package/src/services/ref-resolver/pruners/command-line-pruner.ts +0 -47
- package/src/services/ref-resolver/pruners/include-pruner.ts +0 -66
- package/src/services/ref-resolver/pruners/manifest-pruner.ts +0 -130
- package/src/services/ref-resolver/pruners/ref-pruner.ts +0 -135
- package/src/services/ref-resolver/pruners/rule-helpers.ts +0 -44
- package/src/services/ref-resolver/pruners/stored-key-pruner.ts +0 -136
- package/src/services/ref-resolver/ref-helpers.ts +0 -62
- package/src/services/ref-resolver/ref-picker-service.ts +0 -204
- package/src/services/ref-resolver/ref-report.ts +0 -84
- package/src/services/ref-resolver/ref-resolve-arguments.ts +0 -47
- package/src/services/ref-resolver/ref-resolve-result.ts +0 -36
- package/src/services/ref-resolver/ref-resolver-service.ts +0 -323
- package/src/services/ref-resolver/source.ts +0 -48
- package/src/services/ref-resolver/tokens.ts +0 -25
- package/src/services/ref-resolver/types.ts +0 -155
- package/src/templating/filters/bullet-list.ts +0 -9
- package/src/templating/filters/index.ts +0 -8
- package/src/templating/init-liquid-engine.ts +0 -139
- package/src/templating/lib/glob-files.ts +0 -74
- package/src/templating/lib/import-export.ts +0 -32
- package/src/templating/lib/secret-scope.ts +0 -41
- package/src/templating/lib/tag-args.ts +0 -19
- package/src/templating/tags/exportScalarVarsJs.ts +0 -46
- package/src/templating/tags/getFiles.ts +0 -89
- package/src/templating/tags/index.ts +0 -14
- package/src/templating/tags/listFiles.ts +0 -54
- package/src/templating/tags/showVars.ts +0 -28
- package/src/utils/choice-prompt.ts +0 -143
- package/src/utils/command-errors.ts +0 -186
- package/src/utils/command-help.ts +0 -45
- package/src/utils/confirm-prompt.ts +0 -110
- package/src/utils/flags.ts +0 -177
- package/src/utils/formatting.ts +0 -849
- package/src/utils/prompts.ts +0 -53
- package/src/utils/sous-directory.ts +0 -245
- package/src/utils/table.ts +0 -603
- package/src/utils/value-prompt.ts +0 -119
|
@@ -1,107 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* The Inversify container of the ref services.
|
|
3
|
-
*
|
|
4
|
-
* Every part is bound once and shared: the parser, every splitter, every
|
|
5
|
-
* pruner, the resolver and the picker. Splitters, pruners and providers are
|
|
6
|
-
* bound many times under one token each (`REF_TOKENS`), and the parser and the
|
|
7
|
-
* resolver receive them as lists, so a plugin adds a splitter, a pruner or a
|
|
8
|
-
* provider by binding one more under the same token on a container it builds
|
|
9
|
-
* with `createRefContainer()`:
|
|
10
|
-
*
|
|
11
|
-
* const container = createRefContainer();
|
|
12
|
-
* container.bind(REF_TOKENS.Splitter).to(MyNewFormSplitter);
|
|
13
|
-
* const resolver = container.get<RefResolverService>(REF_TOKENS.Resolver);
|
|
14
|
-
*
|
|
15
|
-
* The `#` names are bound the same way: one more `HashName` under
|
|
16
|
-
* `REF_TOKENS.HashName` registers a view or a built-in, and a name bound twice
|
|
17
|
-
* is an error when the registry is first read.
|
|
18
|
-
*
|
|
19
|
-
* Callers that have no container of their own use `sharedRefResolver`,
|
|
20
|
-
* `sharedHashNames` and `sharedRefPicker`, which come from one container built the first time they
|
|
21
|
-
* are read.
|
|
22
|
-
*/
|
|
23
|
-
|
|
24
|
-
import { Container } from "inversify";
|
|
25
|
-
import { builtInProviders } from "../../lib/repos/providers/index.js";
|
|
26
|
-
import { EnvVarSplitter } from "./parser/env-var-splitter.js";
|
|
27
|
-
import { LocationSplitter } from "./parser/location-splitter.js";
|
|
28
|
-
import { NamePathSplitter } from "./parser/name-path-splitter.js";
|
|
29
|
-
import { QuerySplitter } from "./parser/query-splitter.js";
|
|
30
|
-
import { RangeSplitter } from "./parser/range-splitter.js";
|
|
31
|
-
import { RefParser } from "./parser/ref-parser.js";
|
|
32
|
-
import { RepoQualifierSplitter } from "./parser/repo-qualifier-splitter.js";
|
|
33
|
-
import { CommandLinePruner } from "./pruners/command-line-pruner.js";
|
|
34
|
-
import { IncludePruner } from "./pruners/include-pruner.js";
|
|
35
|
-
import { ManifestPruner } from "./pruners/manifest-pruner.js";
|
|
36
|
-
import { ConfigPruner, LockfilePruner } from "./pruners/stored-key-pruner.js";
|
|
37
|
-
import { MemoriesHashName } from "../../lib/repos/memories-hash-name.js";
|
|
38
|
-
import { HashNameRegistry, ProjectHashName } from "./hash-names.js";
|
|
39
|
-
import { RefPickerService } from "./ref-picker-service.js";
|
|
40
|
-
import { RefResolverService } from "./ref-resolver-service.js";
|
|
41
|
-
import { REF_TOKENS } from "./tokens.js";
|
|
42
|
-
|
|
43
|
-
/**
|
|
44
|
-
* Builds a container holding every ref service. Each call returns a fresh
|
|
45
|
-
* container, so a plugin or a test may bind more splitters or pruners without
|
|
46
|
-
* touching anyone else's.
|
|
47
|
-
*/
|
|
48
|
-
export function createRefContainer(): Container {
|
|
49
|
-
const container = new Container({ defaultScope: "Singleton" });
|
|
50
|
-
|
|
51
|
-
for (const provider of builtInProviders()) {
|
|
52
|
-
container.bind(REF_TOKENS.Provider).toConstantValue(provider);
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
for (const splitter of [
|
|
56
|
-
QuerySplitter,
|
|
57
|
-
RangeSplitter,
|
|
58
|
-
LocationSplitter,
|
|
59
|
-
RepoQualifierSplitter,
|
|
60
|
-
NamePathSplitter,
|
|
61
|
-
EnvVarSplitter,
|
|
62
|
-
]) {
|
|
63
|
-
container.bind(REF_TOKENS.Splitter).to(splitter);
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
for (const pruner of [
|
|
67
|
-
CommandLinePruner,
|
|
68
|
-
ConfigPruner,
|
|
69
|
-
ManifestPruner,
|
|
70
|
-
LockfilePruner,
|
|
71
|
-
IncludePruner,
|
|
72
|
-
]) {
|
|
73
|
-
container.bind(REF_TOKENS.Pruner).to(pruner);
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
container.bind(REF_TOKENS.HashName).to(ProjectHashName);
|
|
77
|
-
container.bind(REF_TOKENS.HashName).to(MemoriesHashName);
|
|
78
|
-
container.bind(REF_TOKENS.HashNames).to(HashNameRegistry);
|
|
79
|
-
container.bind(REF_TOKENS.Parser).to(RefParser);
|
|
80
|
-
container.bind(REF_TOKENS.Resolver).to(RefResolverService);
|
|
81
|
-
container.bind(REF_TOKENS.Picker).to(RefPickerService);
|
|
82
|
-
return container;
|
|
83
|
-
}
|
|
84
|
-
|
|
85
|
-
/** The container the shared instances come from, built on first use. */
|
|
86
|
-
let sharedContainer: Container | undefined;
|
|
87
|
-
|
|
88
|
-
/** The one container callers with no container of their own share. */
|
|
89
|
-
export function getSharedRefContainer(): Container {
|
|
90
|
-
sharedContainer ??= createRefContainer();
|
|
91
|
-
return sharedContainer;
|
|
92
|
-
}
|
|
93
|
-
|
|
94
|
-
/** The shared resolver, for callers that have no container. */
|
|
95
|
-
export function sharedRefResolver(): RefResolverService {
|
|
96
|
-
return getSharedRefContainer().get<RefResolverService>(REF_TOKENS.Resolver);
|
|
97
|
-
}
|
|
98
|
-
|
|
99
|
-
/** The shared registry of `#` names, for callers that have no container. */
|
|
100
|
-
export function sharedHashNames(): HashNameRegistry {
|
|
101
|
-
return getSharedRefContainer().get<HashNameRegistry>(REF_TOKENS.HashNames);
|
|
102
|
-
}
|
|
103
|
-
|
|
104
|
-
/** The shared picker, for callers that have no container. */
|
|
105
|
-
export function sharedRefPicker(): RefPickerService {
|
|
106
|
-
return getSharedRefContainer().get<RefPickerService>(REF_TOKENS.Picker);
|
|
107
|
-
}
|
|
@@ -1,60 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Settling a manifest dependency that reads more than one way, from what is
|
|
3
|
-
* already at hand.
|
|
4
|
-
*
|
|
5
|
-
* A manifest entry usually says exactly what it means. A GitLab URL with nested
|
|
6
|
-
* groups does not say where the project path ends, and a browser URL names a
|
|
7
|
-
* folder, so the parser returns every reading. A release settles such an entry
|
|
8
|
-
* and records the repository it settled on beside each key it resolved
|
|
9
|
-
* (`RecordedDependencies`); a consumer reads that record and never probes.
|
|
10
|
-
*/
|
|
11
|
-
|
|
12
|
-
import { sharedRefResolver } from "./container.js";
|
|
13
|
-
import {
|
|
14
|
-
isConfirmedByRecord,
|
|
15
|
-
type RecordedDependencies,
|
|
16
|
-
} from "./lookups/recorded-dependency-lookup.js";
|
|
17
|
-
import { RefSource } from "./source.js";
|
|
18
|
-
import type { SousRef } from "./types.js";
|
|
19
|
-
|
|
20
|
-
/** What `settleDependency` may consult, beyond the dependency itself. */
|
|
21
|
-
export type SettleDependencyOptions = {
|
|
22
|
-
/** What the declaring version's index entry records about its dependencies. */
|
|
23
|
-
recorded?: RecordedDependencies;
|
|
24
|
-
/**
|
|
25
|
-
* Whether a reading is already known to be right from what is on this
|
|
26
|
-
* machine: its repository is trusted and its cached index publishes what it
|
|
27
|
-
* names. Used only when the index recorded nothing, and it never fetches.
|
|
28
|
-
*/
|
|
29
|
-
known?: (reading: SousRef) => boolean;
|
|
30
|
-
};
|
|
31
|
-
|
|
32
|
-
/**
|
|
33
|
-
* The one reading a manifest dependency settles on, or undefined when it reads
|
|
34
|
-
* more than one way and nothing at hand says which: the declaring recipe's
|
|
35
|
-
* index recorded no answer, and what this machine already knows does not pick
|
|
36
|
-
* exactly one.
|
|
37
|
-
*
|
|
38
|
-
* settleDependency("workflow/alpha");
|
|
39
|
-
* // -> the recipe workflow/alpha
|
|
40
|
-
*
|
|
41
|
-
* @param written - The dependency as the manifest wrote it.
|
|
42
|
-
* @param options - The index's record, and what is known locally.
|
|
43
|
-
* @throws A ConfigError when a manifest may not write the entry that way.
|
|
44
|
-
*/
|
|
45
|
-
export function settleDependency(
|
|
46
|
-
written: string,
|
|
47
|
-
options: SettleDependencyOptions = {}
|
|
48
|
-
): SousRef | undefined {
|
|
49
|
-
const { refs } = sharedRefResolver().parse(written, RefSource.Manifest);
|
|
50
|
-
if (refs.length === 1) return refs[0];
|
|
51
|
-
|
|
52
|
-
const confirmed = refs.filter((ref) => isConfirmedByRecord(ref, options.recorded));
|
|
53
|
-
if (confirmed.length === 1) return confirmed[0];
|
|
54
|
-
|
|
55
|
-
if (options.known !== undefined) {
|
|
56
|
-
const known = refs.filter(options.known);
|
|
57
|
-
if (known.length === 1) return known[0];
|
|
58
|
-
}
|
|
59
|
-
return undefined;
|
|
60
|
-
}
|
|
@@ -1,197 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Printing a ref: its key (what everything is stored and compared under) and
|
|
3
|
-
* its canonical written form (how sous prints it).
|
|
4
|
-
*/
|
|
5
|
-
|
|
6
|
-
import {
|
|
7
|
-
builtInProviders,
|
|
8
|
-
providerById,
|
|
9
|
-
type RepoProvider,
|
|
10
|
-
} from "../../lib/repos/providers/index.js";
|
|
11
|
-
import { repoOf } from "./parts.js";
|
|
12
|
-
import { KIND_LABELS, type RepoRef, type SousRef } from "./types.js";
|
|
13
|
-
|
|
14
|
-
/**
|
|
15
|
-
* The part of a key that names the repository: its short name, or its
|
|
16
|
-
* identity when it was named by location.
|
|
17
|
-
*/
|
|
18
|
-
function repoPart(repo: RepoRef | undefined): string | undefined {
|
|
19
|
-
if (repo === undefined) return undefined;
|
|
20
|
-
return repo.name ?? repo.location?.identity;
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
/**
|
|
24
|
-
* The path part of a key, without any repository.
|
|
25
|
-
*
|
|
26
|
-
* @param ref - Any ref.
|
|
27
|
-
*/
|
|
28
|
-
function pathPart(ref: SousRef): string {
|
|
29
|
-
switch (ref.kind) {
|
|
30
|
-
case "repo":
|
|
31
|
-
return ref.browsed === undefined ? "" : `tree/${ref.browsed}`;
|
|
32
|
-
case "namespace":
|
|
33
|
-
return ref.name;
|
|
34
|
-
case "recipe":
|
|
35
|
-
return ref.namespace === undefined ? ref.name : `${ref.namespace.name}/${ref.name}`;
|
|
36
|
-
case "recipeFile":
|
|
37
|
-
return `${pathPart(ref.recipe)}/${ref.path}`;
|
|
38
|
-
case "variable": {
|
|
39
|
-
const recipe = ref.recipe === undefined ? "" : `${pathPart(ref.recipe)}.`;
|
|
40
|
-
return `${recipe}${ref.name}`;
|
|
41
|
-
}
|
|
42
|
-
case "envVar":
|
|
43
|
-
return ref.name;
|
|
44
|
-
}
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
/**
|
|
48
|
-
* The canonical key of a ref, with its version range and query values left
|
|
49
|
-
* off, so the same thing is never keyed twice under two spellings. A
|
|
50
|
-
* repository qualifier is part of the key, because the same recipe name in two
|
|
51
|
-
* repositories is two things.
|
|
52
|
-
*
|
|
53
|
-
* refKey(namespace("workflow")); // -> "workflow"
|
|
54
|
-
* refKey(recipe("task-files", "workflow", "sous-recipes")); // -> "sous-recipes:workflow/task-files"
|
|
55
|
-
* refKey(variable("apiUrl", recipe)); // -> "workflow/task-files.apiUrl"
|
|
56
|
-
*
|
|
57
|
-
* @param ref - Any ref.
|
|
58
|
-
*/
|
|
59
|
-
export function refKey(ref: SousRef): string {
|
|
60
|
-
const repo = ref.kind === "envVar" ? undefined : repoPart(repoOf(ref));
|
|
61
|
-
const rest = pathPart(ref);
|
|
62
|
-
if (ref.kind === "repo") return repo === undefined ? rest : rest === "" ? repo : `${repo}:${rest}`;
|
|
63
|
-
return repo === undefined ? rest : `${repo}:${rest}`;
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
/**
|
|
67
|
-
* The key of a ref together with its kind, which is what tells a namespace
|
|
68
|
-
* `workflow` from a repository `workflow` apart.
|
|
69
|
-
*
|
|
70
|
-
* @param ref - Any ref.
|
|
71
|
-
*/
|
|
72
|
-
export function refIdentity(ref: SousRef): string {
|
|
73
|
-
return `${ref.kind} ${refKey(ref)}`;
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
/**
|
|
77
|
-
* Writes the repository qualifier in front of what is named inside it: `name:`
|
|
78
|
-
* for a repository this project knows by short name (whatever else it knows of
|
|
79
|
-
* it), and the provider's canonical locator for one known only by location.
|
|
80
|
-
*/
|
|
81
|
-
function qualified(
|
|
82
|
-
repo: RepoRef | undefined,
|
|
83
|
-
rest: string,
|
|
84
|
-
providers: RepoProvider[]
|
|
85
|
-
): string {
|
|
86
|
-
if (repo === undefined) return rest;
|
|
87
|
-
if (repo.name !== undefined) return rest === "" ? repo.name : `${repo.name}:${rest}`;
|
|
88
|
-
if (repo.location !== undefined) {
|
|
89
|
-
const { host, repoPath } = repo.location;
|
|
90
|
-
const provider = providerById(repo.location.provider, providers);
|
|
91
|
-
if (provider !== undefined && provider.id !== "local") {
|
|
92
|
-
return provider.formatLocator(host, repoPath, rest);
|
|
93
|
-
}
|
|
94
|
-
return rest === "" ? repo.location.url : `${repo.location.url}/${rest}`;
|
|
95
|
-
}
|
|
96
|
-
return rest;
|
|
97
|
-
}
|
|
98
|
-
|
|
99
|
-
/**
|
|
100
|
-
* The canonical written form of a ref, which is how sous prints it: the short
|
|
101
|
-
* form for a short ref and each provider's own locator for a located one, then
|
|
102
|
-
* the version range, then the query values.
|
|
103
|
-
*
|
|
104
|
-
* formatRef(parse("https://github.com/o/r/w/a@^1")[0]); // -> "github://o/r/w/a@^1"
|
|
105
|
-
*
|
|
106
|
-
* @param ref - Any ref.
|
|
107
|
-
* @param providers - The providers that format locators. Defaults to the built-ins.
|
|
108
|
-
*/
|
|
109
|
-
export function formatRef(ref: SousRef, providers: RepoProvider[] = builtInProviders()): string {
|
|
110
|
-
const body = qualified(ref.kind === "envVar" ? undefined : repoOf(ref), pathPart(ref), providers);
|
|
111
|
-
const written =
|
|
112
|
-
ref.kind === "recipe" || ref.kind === "recipeFile" || ref.kind === "repo"
|
|
113
|
-
? ref.range
|
|
114
|
-
: undefined;
|
|
115
|
-
const range = written === undefined ? "" : `@${written}`;
|
|
116
|
-
const pairs = Object.entries(ref.vars ?? {}).map(
|
|
117
|
-
([name, value]) => `${encodeURIComponent(name)}=${encodeURIComponent(value)}`
|
|
118
|
-
);
|
|
119
|
-
return `${body}${range}${pairs.length === 0 ? "" : `?${pairs.join("&")}`}`;
|
|
120
|
-
}
|
|
121
|
-
|
|
122
|
-
/**
|
|
123
|
-
* What kind of thing a ref names, in a sentence.
|
|
124
|
-
*
|
|
125
|
-
* @param ref - Any ref.
|
|
126
|
-
*/
|
|
127
|
-
export function refKindLabel(ref: SousRef): string {
|
|
128
|
-
return KIND_LABELS[ref.kind];
|
|
129
|
-
}
|
|
130
|
-
|
|
131
|
-
/**
|
|
132
|
-
* How a ref is written to a person, so they can type it back: its key when a
|
|
133
|
-
* repository's short name qualifies it, and its canonical locator when only a
|
|
134
|
-
* location does (a ref that has not been matched to a repository this project
|
|
135
|
-
* knows by name).
|
|
136
|
-
*
|
|
137
|
-
* refSpelling(recipe "task-files" in "sous-recipes") // -> "sous-recipes:workflow/task-files"
|
|
138
|
-
* refSpelling(a recipe at a located repository) // -> its canonical locator
|
|
139
|
-
*
|
|
140
|
-
* @param ref - Any ref.
|
|
141
|
-
*/
|
|
142
|
-
export function refSpelling(ref: SousRef): string {
|
|
143
|
-
const repo = ref.kind === "envVar" ? undefined : repoOf(ref);
|
|
144
|
-
if (repo !== undefined && repo.name === undefined && repo.location !== undefined) {
|
|
145
|
-
return formatRef(ref);
|
|
146
|
-
}
|
|
147
|
-
return refKey(ref);
|
|
148
|
-
}
|
|
149
|
-
|
|
150
|
-
/** The repository a person is told a ref lives in: its short name, or where it lives. */
|
|
151
|
-
function repoLabel(repo: RepoRef | undefined): string {
|
|
152
|
-
return repo?.name ?? repo?.location?.url ?? "unknown";
|
|
153
|
-
}
|
|
154
|
-
|
|
155
|
-
/**
|
|
156
|
-
* Describes one ref in the words a person choosing between several needs: the
|
|
157
|
-
* fully qualified name, and what it actually means.
|
|
158
|
-
*
|
|
159
|
-
* @param ref - A known ref, as a lookup returns it.
|
|
160
|
-
*/
|
|
161
|
-
export function describeRef(ref: SousRef): string {
|
|
162
|
-
const summary = ref.description === undefined ? "" : `: ${ref.description}`;
|
|
163
|
-
const key = refSpelling(ref);
|
|
164
|
-
|
|
165
|
-
switch (ref.kind) {
|
|
166
|
-
case "repo": {
|
|
167
|
-
const where = ref.location?.url;
|
|
168
|
-
return `${key} (the repository '${ref.name ?? key}'${where === undefined ? "" : `, at ${where}`})`;
|
|
169
|
-
}
|
|
170
|
-
case "namespace":
|
|
171
|
-
return (
|
|
172
|
-
`${key} (the whole namespace '${ref.name}' in the ` +
|
|
173
|
-
`repository '${repoLabel(ref.repo)}')`
|
|
174
|
-
);
|
|
175
|
-
case "recipe":
|
|
176
|
-
return (
|
|
177
|
-
`${key} (the recipe '${ref.name}' in the namespace ` +
|
|
178
|
-
`'${ref.namespace?.name ?? "unknown"}' of the repository ` +
|
|
179
|
-
`'${repoLabel(repoOf(ref))}'${summary})`
|
|
180
|
-
);
|
|
181
|
-
case "recipeFile":
|
|
182
|
-
return `${key} (the file '${ref.path}' of the recipe '${pathPart(ref.recipe)}'${summary})`;
|
|
183
|
-
case "variable":
|
|
184
|
-
return (
|
|
185
|
-
`${key} (the variable '${ref.name}' of the recipe ` +
|
|
186
|
-
`'${ref.recipe === undefined ? "unknown" : pathPart(ref.recipe)}'${summary})`
|
|
187
|
-
);
|
|
188
|
-
case "envVar": {
|
|
189
|
-
const first = ref.variables?.[0];
|
|
190
|
-
const answers =
|
|
191
|
-
first === undefined
|
|
192
|
-
? ""
|
|
193
|
-
: `answering '${first.name}' of the recipe '${first.recipe === undefined ? "unknown" : pathPart(first.recipe)}'`;
|
|
194
|
-
return `${ref.name} (the environment variable${answers === "" ? "" : ` ${answers}`}${summary})`;
|
|
195
|
-
}
|
|
196
|
-
}
|
|
197
|
-
}
|
|
@@ -1,115 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Names, glob patterns and how a written name is compared with a known one.
|
|
3
|
-
*
|
|
4
|
-
* Every name or path part of a ref may be a glob pattern (`*`, `**`, `?`,
|
|
5
|
-
* `[..]`, `{a,b}`), matched with minimatch. Plain names are compared as
|
|
6
|
-
* strings. Either way the exact spelling is tried first and ignoring case is
|
|
7
|
-
* the fallback, so the caller can tell which one matched.
|
|
8
|
-
*/
|
|
9
|
-
|
|
10
|
-
import { minimatch } from "minimatch";
|
|
11
|
-
|
|
12
|
-
/** A name as the parser accepts it: kebab-case, in any case. */
|
|
13
|
-
export const NAME_ANY_CASE = /^[a-z][a-z0-9-]*$/i;
|
|
14
|
-
|
|
15
|
-
/** A name as it is stored: lowercase kebab-case. */
|
|
16
|
-
export const NAME_STORED = /^[a-z][a-z0-9-]*$/;
|
|
17
|
-
|
|
18
|
-
/** A variable name, as a recipe's author writes it: camelCase. */
|
|
19
|
-
export const VARIABLE_NAME = /^[a-z][a-zA-Z0-9]*$/;
|
|
20
|
-
|
|
21
|
-
/** An environment variable name: whatever a shell accepts. */
|
|
22
|
-
export const ENV_VAR_NAME = /^[A-Za-z_][A-Za-z0-9_]*$/;
|
|
23
|
-
|
|
24
|
-
/** The characters a glob pattern is made of. */
|
|
25
|
-
const GLOB_CHARS = /[*?[\]{}]/;
|
|
26
|
-
|
|
27
|
-
/** The characters a glob pattern standing for a name may use. */
|
|
28
|
-
const GLOB_NAME = /^[A-Za-z0-9_\-.*?[\]{},!^]+$/;
|
|
29
|
-
|
|
30
|
-
/** True when a string holds glob syntax. */
|
|
31
|
-
export function hasGlob(text: string): boolean {
|
|
32
|
-
return GLOB_CHARS.test(text);
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
/** True when a string is a glob pattern that could stand for a name. */
|
|
36
|
-
export function isGlobName(text: string): boolean {
|
|
37
|
-
return hasGlob(text) && GLOB_NAME.test(text);
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
/**
|
|
41
|
-
* Splits text at `/`, except inside braces, so `{a/b,c}` stays whole.
|
|
42
|
-
*
|
|
43
|
-
* splitSegments("a/{b/c,d}/e"); // -> ["a", "{b/c,d}", "e"]
|
|
44
|
-
*
|
|
45
|
-
* @param text - The text to split.
|
|
46
|
-
*/
|
|
47
|
-
export function splitSegments(text: string): string[] {
|
|
48
|
-
const segments: string[] = [];
|
|
49
|
-
let depth = 0;
|
|
50
|
-
let current = "";
|
|
51
|
-
for (const character of text) {
|
|
52
|
-
if (character === "{") depth += 1;
|
|
53
|
-
if (character === "}" && depth > 0) depth -= 1;
|
|
54
|
-
if (character === "/" && depth === 0) {
|
|
55
|
-
segments.push(current);
|
|
56
|
-
current = "";
|
|
57
|
-
continue;
|
|
58
|
-
}
|
|
59
|
-
current += character;
|
|
60
|
-
}
|
|
61
|
-
segments.push(current);
|
|
62
|
-
return segments;
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
/** How a written name matched a known one. */
|
|
66
|
-
export type NameMatch = "exact" | "folded" | undefined;
|
|
67
|
-
|
|
68
|
-
/**
|
|
69
|
-
* Whether a written name (or glob pattern) matches a known one: exactly, only
|
|
70
|
-
* ignoring case, or not at all.
|
|
71
|
-
*
|
|
72
|
-
* matchName("Workflow", "workflow"); // -> "folded"
|
|
73
|
-
* matchName("work*", "workflow"); // -> "exact"
|
|
74
|
-
*
|
|
75
|
-
* @param written - The name or pattern as written.
|
|
76
|
-
* @param known - The name as it is spelled where it is published.
|
|
77
|
-
*/
|
|
78
|
-
export function matchName(written: string, known: string): NameMatch {
|
|
79
|
-
if (hasGlob(written)) {
|
|
80
|
-
if (minimatch(known, written, { dot: true })) return "exact";
|
|
81
|
-
return minimatch(known, written, { dot: true, nocase: true }) ? "folded" : undefined;
|
|
82
|
-
}
|
|
83
|
-
if (written === known) return "exact";
|
|
84
|
-
return written.toLowerCase() === known.toLowerCase() ? "folded" : undefined;
|
|
85
|
-
}
|
|
86
|
-
|
|
87
|
-
/**
|
|
88
|
-
* The names that match a written one: those spelled exactly as written, or,
|
|
89
|
-
* when there is none, those that differ only in case.
|
|
90
|
-
*
|
|
91
|
-
* matchNames("Workflow", ["workflow", "tooling"]); // -> ["workflow"]
|
|
92
|
-
* matchNames("workflow", ["workflow", "Workflow"]); // -> ["workflow"]
|
|
93
|
-
*
|
|
94
|
-
* @param written - The name as written.
|
|
95
|
-
* @param names - The names it could mean.
|
|
96
|
-
*/
|
|
97
|
-
export function matchNames(written: string, names: Iterable<string>): string[] {
|
|
98
|
-
const all = [...names];
|
|
99
|
-
const exact = all.filter((name) => matchName(written, name) === "exact");
|
|
100
|
-
if (exact.length > 0) return exact;
|
|
101
|
-
return all.filter((name) => matchName(written, name) === "folded");
|
|
102
|
-
}
|
|
103
|
-
|
|
104
|
-
/**
|
|
105
|
-
* Orders two strings by their UTF-8 bytes, so the order is the same on every
|
|
106
|
-
* machine whatever its locale.
|
|
107
|
-
*
|
|
108
|
-
* ["b", "B", "a"].sort(compareBytewise); // -> ["B", "a", "b"]
|
|
109
|
-
*
|
|
110
|
-
* @param left - The first string.
|
|
111
|
-
* @param right - The second string.
|
|
112
|
-
*/
|
|
113
|
-
export function compareBytewise(left: string, right: string): number {
|
|
114
|
-
return Buffer.compare(Buffer.from(left), Buffer.from(right));
|
|
115
|
-
}
|
|
@@ -1,155 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* The `#` names: the built-in names an include line, a `{% render %}` path or
|
|
3
|
-
* an `entryGlob` may start with, such as `#project`.
|
|
4
|
-
*
|
|
5
|
-
* `~` keeps meaning the home directory and recipe namespaces; `#` is for names
|
|
6
|
-
* sous or a plugin provides. Each name is registered once, with the directories
|
|
7
|
-
* it stands for, and a registration that repeats a name is an error naming both
|
|
8
|
-
* registrants. A later layer registers a view the same way.
|
|
9
|
-
*
|
|
10
|
-
* A plugin adds a name by binding one more `HashName` under
|
|
11
|
-
* `REF_TOKENS.HashName` on a container it builds with `createRefContainer()`.
|
|
12
|
-
*/
|
|
13
|
-
|
|
14
|
-
import { ConfigError } from "../../lib/errors.js";
|
|
15
|
-
import { compareBytewise } from "./glob.js";
|
|
16
|
-
import { makeInjectable } from "./injectable.js";
|
|
17
|
-
import { REF_TOKENS } from "./tokens.js";
|
|
18
|
-
|
|
19
|
-
/** One file a view lists: where it sits in the view, and the real file behind it. */
|
|
20
|
-
export interface ViewFile {
|
|
21
|
-
/** The path inside the view, without the `#name/` prefix, with `/` separators. */
|
|
22
|
-
readonly path: string;
|
|
23
|
-
/** The real file's absolute path. */
|
|
24
|
-
readonly file: string;
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
/** What a view needs to know about the project to list its files. */
|
|
28
|
-
export interface HashViewContext {
|
|
29
|
-
/** The project's `.sous/` directory. */
|
|
30
|
-
sousDir: string;
|
|
31
|
-
/** The environment to read; decides where the recipe store is. */
|
|
32
|
-
env?: NodeJS.ProcessEnv;
|
|
33
|
-
/** The merged project config, read for the `recipes` key. */
|
|
34
|
-
settings: {
|
|
35
|
-
recipes?: { memories?: { first?: string[] | undefined; exclude?: string[] | undefined } };
|
|
36
|
-
};
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
/** One `#` name and what it stands for. */
|
|
40
|
-
export interface HashName {
|
|
41
|
-
/** The name without its `#`: lowercase kebab-case, such as `project`. */
|
|
42
|
-
readonly name: string;
|
|
43
|
-
/** Who registers it, for the error a duplicate raises (`sous`, or a plugin's name). */
|
|
44
|
-
readonly registeredBy: string;
|
|
45
|
-
/** What the name is, in one sentence. */
|
|
46
|
-
readonly description: string;
|
|
47
|
-
/**
|
|
48
|
-
* The directories the name stands for, in the order they are tried. A path
|
|
49
|
-
* after the name is looked up under each in turn, the first that exists
|
|
50
|
-
* wins. Empty when the name has nothing to stand for in this project.
|
|
51
|
-
*
|
|
52
|
-
* @param scope - The settings scope the project's paths come from.
|
|
53
|
-
*/
|
|
54
|
-
bases(scope: Record<string, string>): string[];
|
|
55
|
-
/**
|
|
56
|
-
* A view lists virtual files instead of standing for directories: an include
|
|
57
|
-
* of `#name/<glob>` selects among the listed paths and includes the real
|
|
58
|
-
* files behind them, in the listed order. A view has no bases.
|
|
59
|
-
*
|
|
60
|
-
* @param context - The project the files are listed for.
|
|
61
|
-
*/
|
|
62
|
-
view?(context: HashViewContext): ViewFile[];
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
/** The characters a registered name may hold. */
|
|
66
|
-
const VALID_NAME = /^[a-z][a-z0-9-]*$/;
|
|
67
|
-
|
|
68
|
-
/** The built-in `#project`: the consuming project's root. */
|
|
69
|
-
export class ProjectHashName implements HashName {
|
|
70
|
-
readonly name = "project";
|
|
71
|
-
readonly registeredBy = "sous";
|
|
72
|
-
readonly description = "the root directory of the project being built.";
|
|
73
|
-
|
|
74
|
-
bases(scope: Record<string, string>): string[] {
|
|
75
|
-
return scope.projectRoot ? [scope.projectRoot] : [];
|
|
76
|
-
}
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
makeInjectable(ProjectHashName);
|
|
80
|
-
|
|
81
|
-
/** Every registered `#` name. */
|
|
82
|
-
export class HashNameRegistry {
|
|
83
|
-
private readonly entries = new Map<string, HashName>();
|
|
84
|
-
|
|
85
|
-
/**
|
|
86
|
-
* @param names - The names to register, each once.
|
|
87
|
-
* @throws A ConfigError when a name is invalid or registered twice.
|
|
88
|
-
*/
|
|
89
|
-
constructor(names: HashName[] = []) {
|
|
90
|
-
for (const entry of names) this.register(entry);
|
|
91
|
-
}
|
|
92
|
-
|
|
93
|
-
/**
|
|
94
|
-
* Adds a name.
|
|
95
|
-
*
|
|
96
|
-
* @param entry - The name to add.
|
|
97
|
-
* @throws A ConfigError naming both registrants when the name is already taken.
|
|
98
|
-
*/
|
|
99
|
-
register(entry: HashName): void {
|
|
100
|
-
if (!VALID_NAME.test(entry.name)) {
|
|
101
|
-
throw new ConfigError(
|
|
102
|
-
`The name '#${entry.name}' registered by '${entry.registeredBy}' is invalid: a name is ` +
|
|
103
|
-
"lowercase kebab-case, a letter then letters, digits or hyphens."
|
|
104
|
-
);
|
|
105
|
-
}
|
|
106
|
-
const existing = this.entries.get(entry.name);
|
|
107
|
-
if (existing !== undefined) {
|
|
108
|
-
throw new ConfigError(
|
|
109
|
-
`The name '#${entry.name}' is registered twice: by '${existing.registeredBy}' and by ` +
|
|
110
|
-
`'${entry.registeredBy}'.`
|
|
111
|
-
);
|
|
112
|
-
}
|
|
113
|
-
this.entries.set(entry.name, entry);
|
|
114
|
-
}
|
|
115
|
-
|
|
116
|
-
/** The registered name, or undefined. */
|
|
117
|
-
get(name: string): HashName | undefined {
|
|
118
|
-
return this.entries.get(name);
|
|
119
|
-
}
|
|
120
|
-
|
|
121
|
-
/** Every registered name, sorted. */
|
|
122
|
-
list(): HashName[] {
|
|
123
|
-
return [...this.entries.values()].sort((left, right) => compareBytewise(left.name, right.name));
|
|
124
|
-
}
|
|
125
|
-
|
|
126
|
-
/**
|
|
127
|
-
* Every view's listed files, keyed by the name with its `#`.
|
|
128
|
-
*
|
|
129
|
-
* @param context - The project the files are listed for.
|
|
130
|
-
*/
|
|
131
|
-
viewMap(context: HashViewContext): Record<string, ViewFile[]> {
|
|
132
|
-
const map: Record<string, ViewFile[]> = {};
|
|
133
|
-
for (const entry of this.list()) {
|
|
134
|
-
if (entry.view !== undefined) map[`#${entry.name}`] = entry.view(context);
|
|
135
|
-
}
|
|
136
|
-
return map;
|
|
137
|
-
}
|
|
138
|
-
|
|
139
|
-
/**
|
|
140
|
-
* The alias map the registered names make for a project: `#name` to its
|
|
141
|
-
* directories, leaving out a name with none.
|
|
142
|
-
*
|
|
143
|
-
* @param scope - The settings scope the project's paths come from.
|
|
144
|
-
*/
|
|
145
|
-
aliasMap(scope: Record<string, string>): Record<string, string[]> {
|
|
146
|
-
const map: Record<string, string[]> = {};
|
|
147
|
-
for (const entry of this.list()) {
|
|
148
|
-
const bases = entry.bases(scope);
|
|
149
|
-
if (bases.length > 0) map[`#${entry.name}`] = bases;
|
|
150
|
-
}
|
|
151
|
-
return map;
|
|
152
|
-
}
|
|
153
|
-
}
|
|
154
|
-
|
|
155
|
-
makeInjectable(HashNameRegistry, [{ multi: REF_TOKENS.HashName }]);
|
|
@@ -1,55 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* The ref resolver service: how every sous command and template turns a
|
|
3
|
-
* written ref into the thing it names.
|
|
4
|
-
*
|
|
5
|
-
* Import from here. `types.ts` says what a ref is, the parser reads every way a
|
|
6
|
-
* text can be one, a pruner per place says which readings count there, a
|
|
7
|
-
* lookup says which exist, `RefResolverService` runs the three in order, and
|
|
8
|
-
* `RefPickerService` settles which meaning a run proceeds with.
|
|
9
|
-
*
|
|
10
|
-
* `EnvVarLookup` is not exported here. It reads the variable ladder, which
|
|
11
|
-
* reaches config discovery, and config discovery reaches this module through
|
|
12
|
-
* the recipe formats, so exporting it from the barrel would make an import
|
|
13
|
-
* cycle that fails at load time. Import it from `lookups/env-var-lookup.js`.
|
|
14
|
-
*/
|
|
15
|
-
|
|
16
|
-
export * from "./source.js";
|
|
17
|
-
export * from "./types.js";
|
|
18
|
-
export * from "./parts.js";
|
|
19
|
-
export * from "./glob.js";
|
|
20
|
-
export * from "./location.js";
|
|
21
|
-
export * from "./format.js";
|
|
22
|
-
export * from "./tokens.js";
|
|
23
|
-
export * from "./hash-names.js";
|
|
24
|
-
export * from "./injectable.js";
|
|
25
|
-
export * from "./parser/partial-ref.js";
|
|
26
|
-
export * from "./parser/ref-parser.js";
|
|
27
|
-
export * from "./parser/query-splitter.js";
|
|
28
|
-
export * from "./parser/range-splitter.js";
|
|
29
|
-
export * from "./parser/location-splitter.js";
|
|
30
|
-
export * from "./parser/repo-qualifier-splitter.js";
|
|
31
|
-
export * from "./parser/name-path-splitter.js";
|
|
32
|
-
export * from "./parser/env-var-splitter.js";
|
|
33
|
-
export * from "./pruners/ref-pruner.js";
|
|
34
|
-
export * from "./pruners/rule-helpers.js";
|
|
35
|
-
export * from "./pruners/command-line-pruner.js";
|
|
36
|
-
export * from "./pruners/stored-key-pruner.js";
|
|
37
|
-
export * from "./pruners/manifest-pruner.js";
|
|
38
|
-
export * from "./pruners/include-pruner.js";
|
|
39
|
-
export * from "./lookups/ref-lookup.js";
|
|
40
|
-
export * from "./lookups/chained-lookup.js";
|
|
41
|
-
export * from "./lookups/catalog-matcher.js";
|
|
42
|
-
export * from "./lookups/catalog-lookup.js";
|
|
43
|
-
export * from "./lookups/cached-index-lookup.js";
|
|
44
|
-
export * from "./lookups/recorded-dependency-lookup.js";
|
|
45
|
-
export * from "./lookups/fetched-index-lookup.js";
|
|
46
|
-
export * from "./lookups/variable-lookup.js";
|
|
47
|
-
export * from "./ref-resolve-arguments.js";
|
|
48
|
-
export * from "./ref-resolve-result.js";
|
|
49
|
-
export * from "./ref-resolver-service.js";
|
|
50
|
-
export * from "./ref-picker-service.js";
|
|
51
|
-
export * from "./ref-report.js";
|
|
52
|
-
export * from "./named-refs.js";
|
|
53
|
-
export * from "./dependency.js";
|
|
54
|
-
export * from "./ref-helpers.js";
|
|
55
|
-
export * from "./container.js";
|