@endora-commerce/cli 0.100.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +37 -0
- package/dist/bin/endora.d.ts +28 -0
- package/dist/bin/endora.d.ts.map +1 -0
- package/dist/bin/endora.js +926 -0
- package/dist/bin/endora.js.map +1 -0
- package/dist/check/estate.d.ts +189 -0
- package/dist/check/estate.d.ts.map +1 -0
- package/dist/check/estate.js +1037 -0
- package/dist/check/estate.js.map +1 -0
- package/dist/check/hosts.d.ts +25 -0
- package/dist/check/hosts.d.ts.map +1 -0
- package/dist/check/hosts.js +1347 -0
- package/dist/check/hosts.js.map +1 -0
- package/dist/check/index.d.ts +60 -0
- package/dist/check/index.d.ts.map +1 -0
- package/dist/check/index.js +111 -0
- package/dist/check/index.js.map +1 -0
- package/dist/check/layout.d.ts +136 -0
- package/dist/check/layout.d.ts.map +1 -0
- package/dist/check/layout.js +262 -0
- package/dist/check/layout.js.map +1 -0
- package/dist/check/ledger.d.ts +98 -0
- package/dist/check/ledger.d.ts.map +1 -0
- package/dist/check/ledger.js +173 -0
- package/dist/check/ledger.js.map +1 -0
- package/dist/check/peer-owners.d.ts +116 -0
- package/dist/check/peer-owners.d.ts.map +1 -0
- package/dist/check/peer-owners.js +225 -0
- package/dist/check/peer-owners.js.map +1 -0
- package/dist/check/report.d.ts +33 -0
- package/dist/check/report.d.ts.map +1 -0
- package/dist/check/report.js +107 -0
- package/dist/check/report.js.map +1 -0
- package/dist/check/run.d.ts +147 -0
- package/dist/check/run.d.ts.map +1 -0
- package/dist/check/run.js +111 -0
- package/dist/check/run.js.map +1 -0
- package/dist/checks.d.ts +17 -0
- package/dist/checks.d.ts.map +1 -0
- package/dist/checks.js +17 -0
- package/dist/checks.js.map +1 -0
- package/dist/dev/index.d.ts +83 -0
- package/dist/dev/index.d.ts.map +1 -0
- package/dist/dev/index.js +298 -0
- package/dist/dev/index.js.map +1 -0
- package/dist/generate/divergence.d.ts +38 -0
- package/dist/generate/divergence.d.ts.map +1 -0
- package/dist/generate/divergence.js +237 -0
- package/dist/generate/divergence.js.map +1 -0
- package/dist/generate/index.d.ts +90 -0
- package/dist/generate/index.d.ts.map +1 -0
- package/dist/generate/index.js +369 -0
- package/dist/generate/index.js.map +1 -0
- package/dist/index.d.ts +23 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +35 -0
- package/dist/index.js.map +1 -0
- package/dist/inputs/declaration.d.ts +18 -0
- package/dist/inputs/declaration.d.ts.map +1 -0
- package/dist/inputs/declaration.js +64 -0
- package/dist/inputs/declaration.js.map +1 -0
- package/dist/inputs/env-file.d.ts +73 -0
- package/dist/inputs/env-file.d.ts.map +1 -0
- package/dist/inputs/env-file.js +134 -0
- package/dist/inputs/env-file.js.map +1 -0
- package/dist/inputs/prompt.d.ts +21 -0
- package/dist/inputs/prompt.d.ts.map +1 -0
- package/dist/inputs/prompt.js +59 -0
- package/dist/inputs/prompt.js.map +1 -0
- package/dist/inputs/resolve.d.ts +163 -0
- package/dist/inputs/resolve.d.ts.map +1 -0
- package/dist/inputs/resolve.js +290 -0
- package/dist/inputs/resolve.js.map +1 -0
- package/dist/install/host.d.ts +27 -0
- package/dist/install/host.d.ts.map +1 -0
- package/dist/install/host.js +90 -0
- package/dist/install/host.js.map +1 -0
- package/dist/install/index.d.ts +173 -0
- package/dist/install/index.d.ts.map +1 -0
- package/dist/install/index.js +793 -0
- package/dist/install/index.js.map +1 -0
- package/dist/install/wizard.d.ts +144 -0
- package/dist/install/wizard.d.ts.map +1 -0
- package/dist/install/wizard.js +362 -0
- package/dist/install/wizard.js.map +1 -0
- package/dist/lib/admin-artefacts.d.ts +70 -0
- package/dist/lib/admin-artefacts.d.ts.map +1 -0
- package/dist/lib/admin-artefacts.js +354 -0
- package/dist/lib/admin-artefacts.js.map +1 -0
- package/dist/lib/admin-surfaces.d.ts +298 -0
- package/dist/lib/admin-surfaces.d.ts.map +1 -0
- package/dist/lib/admin-surfaces.js +669 -0
- package/dist/lib/admin-surfaces.js.map +1 -0
- package/dist/lib/delegated-composer.d.ts +85 -0
- package/dist/lib/delegated-composer.d.ts.map +1 -0
- package/dist/lib/delegated-composer.js +241 -0
- package/dist/lib/delegated-composer.js.map +1 -0
- package/dist/lib/divergence-artefacts.d.ts +305 -0
- package/dist/lib/divergence-artefacts.d.ts.map +1 -0
- package/dist/lib/divergence-artefacts.js +828 -0
- package/dist/lib/divergence-artefacts.js.map +1 -0
- package/dist/lib/divergence.d.ts +337 -0
- package/dist/lib/divergence.d.ts.map +1 -0
- package/dist/lib/divergence.js +1005 -0
- package/dist/lib/divergence.js.map +1 -0
- package/dist/lib/docs-artefacts.d.ts +395 -0
- package/dist/lib/docs-artefacts.d.ts.map +1 -0
- package/dist/lib/docs-artefacts.js +781 -0
- package/dist/lib/docs-artefacts.js.map +1 -0
- package/dist/lib/emitted-exports.d.ts +21 -0
- package/dist/lib/emitted-exports.d.ts.map +1 -0
- package/dist/lib/emitted-exports.js +96 -0
- package/dist/lib/emitted-exports.js.map +1 -0
- package/dist/lib/emitted-freshness.d.ts +112 -0
- package/dist/lib/emitted-freshness.d.ts.map +1 -0
- package/dist/lib/emitted-freshness.js +288 -0
- package/dist/lib/emitted-freshness.js.map +1 -0
- package/dist/lib/entity-index-artefact.d.ts +95 -0
- package/dist/lib/entity-index-artefact.d.ts.map +1 -0
- package/dist/lib/entity-index-artefact.js +210 -0
- package/dist/lib/entity-index-artefact.js.map +1 -0
- package/dist/lib/instance-build-inputs.d.ts +108 -0
- package/dist/lib/instance-build-inputs.d.ts.map +1 -0
- package/dist/lib/instance-build-inputs.js +165 -0
- package/dist/lib/instance-build-inputs.js.map +1 -0
- package/dist/lib/module-docs.d.ts +473 -0
- package/dist/lib/module-docs.d.ts.map +1 -0
- package/dist/lib/module-docs.js +711 -0
- package/dist/lib/module-docs.js.map +1 -0
- package/dist/lib/module-package-subpaths.d.ts +56 -0
- package/dist/lib/module-package-subpaths.d.ts.map +1 -0
- package/dist/lib/module-package-subpaths.js +223 -0
- package/dist/lib/module-package-subpaths.js.map +1 -0
- package/dist/lib/module-packages.d.ts +200 -0
- package/dist/lib/module-packages.d.ts.map +1 -0
- package/dist/lib/module-packages.js +580 -0
- package/dist/lib/module-packages.js.map +1 -0
- package/dist/lib/module-population.d.ts +129 -0
- package/dist/lib/module-population.d.ts.map +1 -0
- package/dist/lib/module-population.js +172 -0
- package/dist/lib/module-population.js.map +1 -0
- package/dist/lib/module-roots.d.ts +337 -0
- package/dist/lib/module-roots.d.ts.map +1 -0
- package/dist/lib/module-roots.js +586 -0
- package/dist/lib/module-roots.js.map +1 -0
- package/dist/lib/nested-checkouts.d.ts +33 -0
- package/dist/lib/nested-checkouts.d.ts.map +1 -0
- package/dist/lib/nested-checkouts.js +160 -0
- package/dist/lib/nested-checkouts.js.map +1 -0
- package/dist/lib/platform-root.d.ts +43 -0
- package/dist/lib/platform-root.d.ts.map +1 -0
- package/dist/lib/platform-root.js +134 -0
- package/dist/lib/platform-root.js.map +1 -0
- package/dist/lib/platform-surface.d.ts +235 -0
- package/dist/lib/platform-surface.d.ts.map +1 -0
- package/dist/lib/platform-surface.js +393 -0
- package/dist/lib/platform-surface.js.map +1 -0
- package/dist/lib/port-registrations.d.ts +223 -0
- package/dist/lib/port-registrations.d.ts.map +1 -0
- package/dist/lib/port-registrations.js +532 -0
- package/dist/lib/port-registrations.js.map +1 -0
- package/dist/lib/read-size.d.ts +154 -0
- package/dist/lib/read-size.d.ts.map +1 -0
- package/dist/lib/read-size.js +182 -0
- package/dist/lib/read-size.js.map +1 -0
- package/dist/lib/registration-owners.d.ts +79 -0
- package/dist/lib/registration-owners.d.ts.map +1 -0
- package/dist/lib/registration-owners.js +77 -0
- package/dist/lib/registration-owners.js.map +1 -0
- package/dist/lib/release-index.d.ts +53 -0
- package/dist/lib/release-index.d.ts.map +1 -0
- package/dist/lib/release-index.js +162 -0
- package/dist/lib/release-index.js.map +1 -0
- package/dist/lib/repeating-timers.d.ts +79 -0
- package/dist/lib/repeating-timers.d.ts.map +1 -0
- package/dist/lib/repeating-timers.js +189 -0
- package/dist/lib/repeating-timers.js.map +1 -0
- package/dist/lib/source-text.d.ts +34 -0
- package/dist/lib/source-text.d.ts.map +1 -0
- package/dist/lib/source-text.js +80 -0
- package/dist/lib/source-text.js.map +1 -0
- package/dist/lib/specifiers.d.ts +20 -0
- package/dist/lib/specifiers.d.ts.map +1 -0
- package/dist/lib/specifiers.js +130 -0
- package/dist/lib/specifiers.js.map +1 -0
- package/dist/lib/sql-tables.d.ts +166 -0
- package/dist/lib/sql-tables.d.ts.map +1 -0
- package/dist/lib/sql-tables.js +464 -0
- package/dist/lib/sql-tables.js.map +1 -0
- package/dist/lib/switchable-modules.d.ts +54 -0
- package/dist/lib/switchable-modules.d.ts.map +1 -0
- package/dist/lib/switchable-modules.js +104 -0
- package/dist/lib/switchable-modules.js.map +1 -0
- package/dist/lib/tailwind-sources.d.ts +136 -0
- package/dist/lib/tailwind-sources.d.ts.map +1 -0
- package/dist/lib/tailwind-sources.js +307 -0
- package/dist/lib/tailwind-sources.js.map +1 -0
- package/dist/lib/ui-layer.d.ts +54 -0
- package/dist/lib/ui-layer.d.ts.map +1 -0
- package/dist/lib/ui-layer.js +57 -0
- package/dist/lib/ui-layer.js.map +1 -0
- package/dist/lib/workspace-packages.d.ts +186 -0
- package/dist/lib/workspace-packages.d.ts.map +1 -0
- package/dist/lib/workspace-packages.js +351 -0
- package/dist/lib/workspace-packages.js.map +1 -0
- package/dist/new-instance/deploy.d.ts +211 -0
- package/dist/new-instance/deploy.d.ts.map +1 -0
- package/dist/new-instance/deploy.js +1381 -0
- package/dist/new-instance/deploy.js.map +1 -0
- package/dist/new-instance/docs-toolchain.d.ts +66 -0
- package/dist/new-instance/docs-toolchain.d.ts.map +1 -0
- package/dist/new-instance/docs-toolchain.js +69 -0
- package/dist/new-instance/docs-toolchain.js.map +1 -0
- package/dist/new-instance/host.d.ts +124 -0
- package/dist/new-instance/host.d.ts.map +1 -0
- package/dist/new-instance/host.js +276 -0
- package/dist/new-instance/host.js.map +1 -0
- package/dist/new-instance/index.d.ts +118 -0
- package/dist/new-instance/index.d.ts.map +1 -0
- package/dist/new-instance/index.js +567 -0
- package/dist/new-instance/index.js.map +1 -0
- package/dist/new-instance/modules.d.ts +188 -0
- package/dist/new-instance/modules.d.ts.map +1 -0
- package/dist/new-instance/modules.js +392 -0
- package/dist/new-instance/modules.js.map +1 -0
- package/dist/new-instance/template.d.ts +505 -0
- package/dist/new-instance/template.d.ts.map +1 -0
- package/dist/new-instance/template.js +1886 -0
- package/dist/new-instance/template.js.map +1 -0
- package/dist/new-module/emit.d.ts +67 -0
- package/dist/new-module/emit.d.ts.map +1 -0
- package/dist/new-module/emit.js +1393 -0
- package/dist/new-module/emit.js.map +1 -0
- package/dist/new-module/host.d.ts +67 -0
- package/dist/new-module/host.d.ts.map +1 -0
- package/dist/new-module/host.js +224 -0
- package/dist/new-module/host.js.map +1 -0
- package/dist/new-module/index.d.ts +32 -0
- package/dist/new-module/index.d.ts.map +1 -0
- package/dist/new-module/index.js +193 -0
- package/dist/new-module/index.js.map +1 -0
- package/dist/new-module/spec.d.ts +188 -0
- package/dist/new-module/spec.d.ts.map +1 -0
- package/dist/new-module/spec.js +404 -0
- package/dist/new-module/spec.js.map +1 -0
- package/dist/new-module/text.d.ts +15 -0
- package/dist/new-module/text.d.ts.map +1 -0
- package/dist/new-module/text.js +22 -0
- package/dist/new-module/text.js.map +1 -0
- package/dist/new-storefront/dockerfile.d.ts +20 -0
- package/dist/new-storefront/dockerfile.d.ts.map +1 -0
- package/dist/new-storefront/dockerfile.js +131 -0
- package/dist/new-storefront/dockerfile.js.map +1 -0
- package/dist/new-storefront/gitignore.d.ts +23 -0
- package/dist/new-storefront/gitignore.d.ts.map +1 -0
- package/dist/new-storefront/gitignore.js +39 -0
- package/dist/new-storefront/gitignore.js.map +1 -0
- package/dist/new-storefront/index.d.ts +93 -0
- package/dist/new-storefront/index.d.ts.map +1 -0
- package/dist/new-storefront/index.js +329 -0
- package/dist/new-storefront/index.js.map +1 -0
- package/dist/new-storefront/npmrc.d.ts +98 -0
- package/dist/new-storefront/npmrc.d.ts.map +1 -0
- package/dist/new-storefront/npmrc.js +217 -0
- package/dist/new-storefront/npmrc.js.map +1 -0
- package/dist/new-storefront/reference.d.ts +189 -0
- package/dist/new-storefront/reference.d.ts.map +1 -0
- package/dist/new-storefront/reference.js +430 -0
- package/dist/new-storefront/reference.js.map +1 -0
- package/dist/new-storefront/rewrite.d.ts +171 -0
- package/dist/new-storefront/rewrite.d.ts.map +1 -0
- package/dist/new-storefront/rewrite.js +701 -0
- package/dist/new-storefront/rewrite.js.map +1 -0
- package/dist/release-index.json +284 -0
- package/dist/rules/action-route-permissions.d.ts +141 -0
- package/dist/rules/action-route-permissions.d.ts.map +1 -0
- package/dist/rules/action-route-permissions.js +556 -0
- package/dist/rules/action-route-permissions.js.map +1 -0
- package/dist/rules/bundle-pairing.d.ts +74 -0
- package/dist/rules/bundle-pairing.d.ts.map +1 -0
- package/dist/rules/bundle-pairing.js +281 -0
- package/dist/rules/bundle-pairing.js.map +1 -0
- package/dist/rules/channel-resolution.d.ts +17 -0
- package/dist/rules/channel-resolution.d.ts.map +1 -0
- package/dist/rules/channel-resolution.js +382 -0
- package/dist/rules/channel-resolution.js.map +1 -0
- package/dist/rules/command-coverage.d.ts +210 -0
- package/dist/rules/command-coverage.d.ts.map +1 -0
- package/dist/rules/command-coverage.js +714 -0
- package/dist/rules/command-coverage.js.map +1 -0
- package/dist/rules/container-imports.d.ts +60 -0
- package/dist/rules/container-imports.d.ts.map +1 -0
- package/dist/rules/container-imports.js +158 -0
- package/dist/rules/container-imports.js.map +1 -0
- package/dist/rules/default-language-prose.d.ts +212 -0
- package/dist/rules/default-language-prose.d.ts.map +1 -0
- package/dist/rules/default-language-prose.js +710 -0
- package/dist/rules/default-language-prose.js.map +1 -0
- package/dist/rules/diacritic-folds.d.ts +238 -0
- package/dist/rules/diacritic-folds.d.ts.map +1 -0
- package/dist/rules/diacritic-folds.js +681 -0
- package/dist/rules/diacritic-folds.js.map +1 -0
- package/dist/rules/entity-tenant-classification.d.ts +171 -0
- package/dist/rules/entity-tenant-classification.d.ts.map +1 -0
- package/dist/rules/entity-tenant-classification.js +323 -0
- package/dist/rules/entity-tenant-classification.js.map +1 -0
- package/dist/rules/entry-presence.d.ts +142 -0
- package/dist/rules/entry-presence.d.ts.map +1 -0
- package/dist/rules/entry-presence.js +339 -0
- package/dist/rules/entry-presence.js.map +1 -0
- package/dist/rules/entry-scope.d.ts +91 -0
- package/dist/rules/entry-scope.d.ts.map +1 -0
- package/dist/rules/entry-scope.js +404 -0
- package/dist/rules/entry-scope.js.map +1 -0
- package/dist/rules/env-inputs.d.ts +222 -0
- package/dist/rules/env-inputs.d.ts.map +1 -0
- package/dist/rules/env-inputs.js +951 -0
- package/dist/rules/env-inputs.js.map +1 -0
- package/dist/rules/kernel-boundary.d.ts +37 -0
- package/dist/rules/kernel-boundary.d.ts.map +1 -0
- package/dist/rules/kernel-boundary.js +195 -0
- package/dist/rules/kernel-boundary.js.map +1 -0
- package/dist/rules/nul-bytes.d.ts +233 -0
- package/dist/rules/nul-bytes.d.ts.map +1 -0
- package/dist/rules/nul-bytes.js +332 -0
- package/dist/rules/nul-bytes.js.map +1 -0
- package/dist/rules/platform-surface.d.ts +479 -0
- package/dist/rules/platform-surface.d.ts.map +1 -0
- package/dist/rules/platform-surface.js +749 -0
- package/dist/rules/platform-surface.js.map +1 -0
- package/dist/rules/port-catches.d.ts +225 -0
- package/dist/rules/port-catches.d.ts.map +1 -0
- package/dist/rules/port-catches.js +1374 -0
- package/dist/rules/port-catches.js.map +1 -0
- package/dist/rules/port-shape.d.ts +213 -0
- package/dist/rules/port-shape.d.ts.map +1 -0
- package/dist/rules/port-shape.js +670 -0
- package/dist/rules/port-shape.js.map +1 -0
- package/dist/rules/queue-names.d.ts +108 -0
- package/dist/rules/queue-names.d.ts.map +1 -0
- package/dist/rules/queue-names.js +395 -0
- package/dist/rules/queue-names.js.map +1 -0
- package/dist/rules/singleton-identity.d.ts +205 -0
- package/dist/rules/singleton-identity.d.ts.map +1 -0
- package/dist/rules/singleton-identity.js +830 -0
- package/dist/rules/singleton-identity.js.map +1 -0
- package/dist/rules/subscribe-seam.d.ts +121 -0
- package/dist/rules/subscribe-seam.d.ts.map +1 -0
- package/dist/rules/subscribe-seam.js +594 -0
- package/dist/rules/subscribe-seam.js.map +1 -0
- package/dist/rules/transaction-context.d.ts +40 -0
- package/dist/rules/transaction-context.d.ts.map +1 -0
- package/dist/rules/transaction-context.js +294 -0
- package/dist/rules/transaction-context.js.map +1 -0
- package/package.json +59 -0
|
@@ -0,0 +1,329 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `endora new storefront <dir>` — the command.
|
|
3
|
+
*
|
|
4
|
+
* It copies the reference storefront out of this repository into a directory the
|
|
5
|
+
* client then owns outright, rewrites every declaration that names something
|
|
6
|
+
* above the storefront's own directory, and **forgets it** (D-195). There is no
|
|
7
|
+
* kit, no shell and no channel back to what it wrote: a scaffold that kept one
|
|
8
|
+
* would be a kit wearing a different name.
|
|
9
|
+
*
|
|
10
|
+
* The order is `endora new module`'s and for the same reason: **validate
|
|
11
|
+
* completely, then write**. A half-written storefront is worse than none — it
|
|
12
|
+
* installs against ranges nothing resolves, its configuration extends a file it
|
|
13
|
+
* does not have, and the author's next command is a manual clean-up.
|
|
14
|
+
*
|
|
15
|
+
* Exit codes are `contracts/cli-surface.md` §2's, unchanged: `0` it did what it
|
|
16
|
+
* was asked, `1` a refusal the author can act on, `2` an input it could not
|
|
17
|
+
* read. The three refusal classes map cleanly — a target directory that is
|
|
18
|
+
* occupied and an outward reference no rule classifies are `1`; a checkout with
|
|
19
|
+
* no reference storefront in it is `2`.
|
|
20
|
+
*
|
|
21
|
+
* ## It resolves the copy's environment inputs, in four tiers
|
|
22
|
+
*
|
|
23
|
+
* `specs/117-instance-bring-up/` FR-010…FR-015. The storefront declares what it
|
|
24
|
+
* needs (`storefront/environment-inputs.mjs`) and this command resolves each of
|
|
25
|
+
* those in one fixed order — an explicit flag, then a `.env` already placed in
|
|
26
|
+
* the target directory, then a prompt on a terminal, then a refusal naming
|
|
27
|
+
* **every** missing input at once — and writes the answers into the copy's own
|
|
28
|
+
* `.env`. The values are the operator's or they are asked for; nothing is
|
|
29
|
+
* invented, and the run says so in a provenance line whose `defaulted=` is
|
|
30
|
+
* contract-bound to `0`.
|
|
31
|
+
*
|
|
32
|
+
* FR-014 is why it is here and not only in `endora new instance`: one product
|
|
33
|
+
* means one behaviour, and the resolution is one shared module rather than a
|
|
34
|
+
* copy per command. This command already exists and already has a customer, and
|
|
35
|
+
* three of its required inputs are three of the four facts nothing reconciles
|
|
36
|
+
* across the trees today.
|
|
37
|
+
*/
|
|
38
|
+
import { existsSync, mkdirSync, readdirSync, readFileSync, writeFileSync } from 'node:fs';
|
|
39
|
+
import { dirname, isAbsolute, join, resolve, sep } from 'node:path';
|
|
40
|
+
import { scopeToMembers } from '@endora-commerce/contracts';
|
|
41
|
+
import { loadTreeDeclaration } from '../inputs/declaration.js';
|
|
42
|
+
import { parseEnvFile, writeEnvFile } from '../inputs/env-file.js';
|
|
43
|
+
import { promptForInputs } from '../inputs/prompt.js';
|
|
44
|
+
import { flagFor, generateSecret, interactivityOf, missingInputsRefusal, planResolution, provenanceLine, } from '../inputs/resolve.js';
|
|
45
|
+
import { TOKEN_VARIABLE } from './npmrc.js';
|
|
46
|
+
import { addressVariables, ENV_EXAMPLE_FILE, memberDirectories, resolveReference, STOREFRONT_DECLARATION_EXPORT, StorefrontHostError, StorefrontInputError, } from './reference.js';
|
|
47
|
+
import { planStorefront } from './rewrite.js';
|
|
48
|
+
/** Raised when required inputs are missing and this run may not ask (R7.2). */
|
|
49
|
+
export class MissingInputsError extends Error {
|
|
50
|
+
name = 'MissingInputsError';
|
|
51
|
+
}
|
|
52
|
+
export async function runNewStorefront(options) {
|
|
53
|
+
const cwd = options.cwd ?? process.cwd();
|
|
54
|
+
if (options.dir === undefined || options.dir.trim().length === 0) {
|
|
55
|
+
throw new StorefrontInputError(`\`new storefront\` takes the directory to write, and has no default. The reference ` +
|
|
56
|
+
`storefront is this repository's own application; a command that defaulted the target ` +
|
|
57
|
+
`would either overwrite it or invent a name nobody chose.`);
|
|
58
|
+
}
|
|
59
|
+
const reference = resolveReference(cwd);
|
|
60
|
+
const targetDir = isAbsolute(options.dir) ? options.dir : resolve(cwd, options.dir);
|
|
61
|
+
refuseOccupiedDirectory(targetDir);
|
|
62
|
+
if (targetDir === reference.dir || targetDir.startsWith(reference.dir + sep)) {
|
|
63
|
+
throw new StorefrontInputError(`${targetDir} is inside the reference storefront this command copies. A scaffold written ` +
|
|
64
|
+
`there would be a copy of itself, and the copy would be part of its own population on ` +
|
|
65
|
+
`the next run.`);
|
|
66
|
+
}
|
|
67
|
+
const members = memberDirectories(reference.repoRoot);
|
|
68
|
+
const plan = planStorefront(reference, members, targetDir, {
|
|
69
|
+
...(options.registry === undefined ? {} : { registry: options.registry }),
|
|
70
|
+
});
|
|
71
|
+
// Validate completely, then write — and the inputs are part of "completely".
|
|
72
|
+
// A tree written before the refusal would be a storefront on disk that cannot
|
|
73
|
+
// build, which is the half-written state this command's whole order exists to
|
|
74
|
+
// avoid.
|
|
75
|
+
const dryRun = options.dryRun === true;
|
|
76
|
+
const interactivity = interactivityOf({
|
|
77
|
+
nonInteractive: options.nonInteractive === true,
|
|
78
|
+
dryRun,
|
|
79
|
+
});
|
|
80
|
+
const declared = await loadTreeDeclaration(reference.dir, STOREFRONT_DECLARATION_EXPORT);
|
|
81
|
+
const resolution = planResolution({
|
|
82
|
+
declared,
|
|
83
|
+
// `endora new storefront` writes exactly one member. An input read only by
|
|
84
|
+
// the admin or only by the backend is out of this run's population — not
|
|
85
|
+
// resolved, not asked for, not refused — which is
|
|
86
|
+
// `specs/118-instance-member-selection/`'s scoping, applied to the command
|
|
87
|
+
// that has one member today so that it is already right for the command
|
|
88
|
+
// that has three tomorrow.
|
|
89
|
+
members: ['storefront'],
|
|
90
|
+
flags: options.inputs ?? {},
|
|
91
|
+
envFile: readTargetEnv(targetDir),
|
|
92
|
+
interactivity,
|
|
93
|
+
language: 'en',
|
|
94
|
+
});
|
|
95
|
+
if (resolution.missing.length > 0) {
|
|
96
|
+
throw new MissingInputsError(missingInputsRefusal(resolution.missing, interactivity));
|
|
97
|
+
}
|
|
98
|
+
if (dryRun) {
|
|
99
|
+
// R2.4 / R7.3 — a dry run resolves and reports; it prompts nothing and
|
|
100
|
+
// generates nothing, and it names each input it would have had to ask for.
|
|
101
|
+
// Its purpose is to be inspectable before it is trusted, and a dry run that
|
|
102
|
+
// stopped to ask for a password is not inspectable.
|
|
103
|
+
return {
|
|
104
|
+
reference,
|
|
105
|
+
targetDir,
|
|
106
|
+
plan,
|
|
107
|
+
dryRun: true,
|
|
108
|
+
nextSteps: nextSteps(targetDir, plan, declared, resolution.resolved),
|
|
109
|
+
resolved: resolution.resolved,
|
|
110
|
+
provenance: provenanceLine(resolution.resolved),
|
|
111
|
+
wouldPrompt: resolution.toPrompt.map((input) => input.name),
|
|
112
|
+
wouldGenerate: resolution.toGenerate.map((input) => input.name),
|
|
113
|
+
unset: resolution.unset.map((input) => input.name),
|
|
114
|
+
};
|
|
115
|
+
}
|
|
116
|
+
const answered = await promptForInputs(resolution.toPrompt, 'en', options.promptIo ?? { input: process.stdin, output: process.stdout });
|
|
117
|
+
const generated = resolution.toGenerate.map((input) => ({
|
|
118
|
+
name: input.name,
|
|
119
|
+
value: generateSecret(),
|
|
120
|
+
provenance: 'generated',
|
|
121
|
+
}));
|
|
122
|
+
const resolved = [...resolution.resolved, ...answered, ...generated];
|
|
123
|
+
for (const file of plan.files) {
|
|
124
|
+
const target = join(targetDir, file.path);
|
|
125
|
+
mkdirSync(dirname(target), { recursive: true });
|
|
126
|
+
if (file.content !== null)
|
|
127
|
+
writeFileSync(target, file.content, 'utf8');
|
|
128
|
+
else
|
|
129
|
+
writeFileSync(target, readFileSync(file.source));
|
|
130
|
+
}
|
|
131
|
+
writeResolvedEnv(targetDir, resolved);
|
|
132
|
+
return {
|
|
133
|
+
reference,
|
|
134
|
+
targetDir,
|
|
135
|
+
plan,
|
|
136
|
+
dryRun: false,
|
|
137
|
+
nextSteps: nextSteps(targetDir, plan, declared, resolved),
|
|
138
|
+
resolved,
|
|
139
|
+
provenance: provenanceLine(resolved),
|
|
140
|
+
wouldPrompt: [],
|
|
141
|
+
wouldGenerate: [],
|
|
142
|
+
unset: resolution.unset.map((input) => input.name),
|
|
143
|
+
};
|
|
144
|
+
}
|
|
145
|
+
/**
|
|
146
|
+
* The flags this build accepts for the reference storefront's declared inputs,
|
|
147
|
+
* without their leading dashes.
|
|
148
|
+
*
|
|
149
|
+
* The argv layer calls this **before** it parses, so `parseArgs` keeps
|
|
150
|
+
* `strict: true` and an unrecognised flag stays a refusal
|
|
151
|
+
* (`cli-surface.md` §1). The alternative — parsing leniently for this one
|
|
152
|
+
* subcommand — would trade a typo'd `--next-public-api-base-ur` from a loud
|
|
153
|
+
* refusal into a silently unset required input, which is the whole class of
|
|
154
|
+
* failure this feature exists to remove.
|
|
155
|
+
*
|
|
156
|
+
* It is derived from the declaration rather than written down, so a storefront
|
|
157
|
+
* that declares a variable this build has never heard of is supplied by its own
|
|
158
|
+
* flag with nothing here to update (D-100).
|
|
159
|
+
*/
|
|
160
|
+
export async function storefrontInputFlags(cwd) {
|
|
161
|
+
return (await storefrontDeclaredInputs(cwd)).map((input) => flagFor(input.name).slice(2));
|
|
162
|
+
}
|
|
163
|
+
/**
|
|
164
|
+
* The reference storefront's own declaration, scoped to the one member this
|
|
165
|
+
* command writes.
|
|
166
|
+
*
|
|
167
|
+
* Exported because a caller that has to *supply* these inputs needs the same
|
|
168
|
+
* population the command will *demand*, and deriving it twice is two answers
|
|
169
|
+
* waiting to disagree — which is exactly how the acceptance criterion came to
|
|
170
|
+
* invoke this command with none of them. The scoping is `planResolution`'s and
|
|
171
|
+
* is applied here so that the two cannot part company either: an input read only
|
|
172
|
+
* by the admin or only by the backend is out of this command's population, so it
|
|
173
|
+
* is out of a supplier's too.
|
|
174
|
+
*
|
|
175
|
+
* The requirement is deliberately **not** filtered here. `isRequiredGiven` reads
|
|
176
|
+
* a conditional requirement against the values a run has in hand, so which
|
|
177
|
+
* inputs are required is a property of the invocation rather than of the
|
|
178
|
+
* declaration, and answering it here would answer it for one invocation and be
|
|
179
|
+
* wrong for the next.
|
|
180
|
+
*/
|
|
181
|
+
export async function storefrontDeclaredInputs(cwd) {
|
|
182
|
+
const reference = resolveReference(cwd);
|
|
183
|
+
const declared = await loadTreeDeclaration(reference.dir, STOREFRONT_DECLARATION_EXPORT);
|
|
184
|
+
return scopeToMembers(declared, ['storefront']);
|
|
185
|
+
}
|
|
186
|
+
/** The file the copy's own runtime configuration lives in. */
|
|
187
|
+
const ENV_FILE = '.env';
|
|
188
|
+
/**
|
|
189
|
+
* Tier 2 — the `.env` **of the target directory**, never of the working
|
|
190
|
+
* directory and never of an ancestor (R1.2).
|
|
191
|
+
*
|
|
192
|
+
* That restriction is the whole of the rule: a command run inside a checkout of
|
|
193
|
+
* ours must not silently inherit that checkout's development configuration,
|
|
194
|
+
* which is how a client's first instance would come to carry
|
|
195
|
+
* `postgresql://b2b:b2b@localhost:5432/b2b`.
|
|
196
|
+
*/
|
|
197
|
+
function readTargetEnv(targetDir) {
|
|
198
|
+
const path = join(targetDir, ENV_FILE);
|
|
199
|
+
if (!existsSync(path))
|
|
200
|
+
return new Map();
|
|
201
|
+
return parseEnvFile(readFileSync(path, 'utf8'));
|
|
202
|
+
}
|
|
203
|
+
/**
|
|
204
|
+
* The answers, into the copy's own `.env`.
|
|
205
|
+
*
|
|
206
|
+
* R4.2 — a generated secret is written **where the operator can read it**,
|
|
207
|
+
* change it and copy it into a secret store. It is named in the provenance line
|
|
208
|
+
* and its value is printed nowhere.
|
|
209
|
+
*
|
|
210
|
+
* The file the operator may already have placed here is merged into rather than
|
|
211
|
+
* rewritten: its comments, its ordering and its own keys survive.
|
|
212
|
+
*/
|
|
213
|
+
function writeResolvedEnv(targetDir, resolved) {
|
|
214
|
+
const path = join(targetDir, ENV_FILE);
|
|
215
|
+
const existing = existsSync(path) ? readFileSync(path, 'utf8') : '';
|
|
216
|
+
const values = new Map(resolved.map((entry) => [entry.name, entry.value]));
|
|
217
|
+
writeFileSync(path, writeEnvFile(existing, values), 'utf8');
|
|
218
|
+
}
|
|
219
|
+
/**
|
|
220
|
+
* The target must be empty — **or hold nothing but a `.env`**.
|
|
221
|
+
*
|
|
222
|
+
* The exception is the owner's own second tier, in their own words: *"I invoke a
|
|
223
|
+
* command and I can attach arguments, **or place the required things in a
|
|
224
|
+
* `.env` beforehand**"*. Without it tier 2 is unreachable for this command,
|
|
225
|
+
* because the only directory it accepts is one that can hold no file at all —
|
|
226
|
+
* which would leave `input-resolution.md` §1's four tiers implemented as three
|
|
227
|
+
* and the operator's cheapest path refused by the command that documents it.
|
|
228
|
+
*
|
|
229
|
+
* It stays one file rather than "a few harmless ones". Everything else this
|
|
230
|
+
* command would write over is either hand-written code or a copy of the
|
|
231
|
+
* reference, and merging into either is the silent discard the refusal exists
|
|
232
|
+
* for; a `.env` is neither, being the one file whose contents this command reads
|
|
233
|
+
* *before* it writes and merges into rather than replaces.
|
|
234
|
+
*/
|
|
235
|
+
function refuseOccupiedDirectory(targetDir) {
|
|
236
|
+
if (!existsSync(targetDir))
|
|
237
|
+
return;
|
|
238
|
+
const entries = readdirSync(targetDir);
|
|
239
|
+
if (entries.length === 0)
|
|
240
|
+
return;
|
|
241
|
+
if (entries.length === 1 && entries[0] === ENV_FILE)
|
|
242
|
+
return;
|
|
243
|
+
throw new StorefrontInputError(`${targetDir} exists and is not empty (${entries.slice(0, 5).join(', ')}). This command ` +
|
|
244
|
+
`never merges into a directory: it is not idempotent over an existing storefront, and ` +
|
|
245
|
+
`pretending otherwise would silently discard hand-written code. A directory holding ` +
|
|
246
|
+
`nothing but a \`${ENV_FILE}\` is the one exception — that file is where you may place ` +
|
|
247
|
+
`the values this command would otherwise ask you for.`);
|
|
248
|
+
}
|
|
249
|
+
/**
|
|
250
|
+
* The steps that are the author's.
|
|
251
|
+
*
|
|
252
|
+
* It never runs them, for `endora new module`'s reason: a scaffold that ran the
|
|
253
|
+
* consuming project's tooling would be a channel back to the instance, and D-195
|
|
254
|
+
* is that there is none.
|
|
255
|
+
*
|
|
256
|
+
* **The first step is about the registry, and it changed with publication**
|
|
257
|
+
* (feature 104, § 1.5). It used to tell its reader to pack tarballs and pin them
|
|
258
|
+
* through `pnpm.overrides`, which was honest while nothing under `packages/` was
|
|
259
|
+
* published and became wrong the moment something was — instructions in a copy a
|
|
260
|
+
* client owns outright are not something anybody comes back to correct.
|
|
261
|
+
*/
|
|
262
|
+
function nextSteps(targetDir, plan, declared, resolved) {
|
|
263
|
+
const published = plan.ranges.length;
|
|
264
|
+
const ranges = `the ${String(published)} \`@endora-commerce/*\` ${published === 1 ? 'range' : 'ranges'}`;
|
|
265
|
+
const install = plan.registry === null
|
|
266
|
+
? `cd ${targetDir} && pnpm install — ${ranges} in the manifest are published semver and ` +
|
|
267
|
+
`resolve at the public npm registry, which is what this command assumes when it is not ` +
|
|
268
|
+
`told otherwise. If your instance installs them from a private registry, scaffold again ` +
|
|
269
|
+
`with \`--registry <url>\`: it writes the \`.npmrc\` for you, with the token as an ` +
|
|
270
|
+
`environment reference and never as a value.`
|
|
271
|
+
: `cd ${targetDir} && export ${TOKEN_VARIABLE}=… && pnpm install — the \`.npmrc\` this ` +
|
|
272
|
+
`command wrote points ${ranges} at ${plan.registry}. The file holds no secret: the ` +
|
|
273
|
+
`token is \${${TOKEN_VARIABLE}}, expanded at install time, so commit the file and keep ` +
|
|
274
|
+
`the value in your environment. If a fetch reports that a package "is not in the npm ` +
|
|
275
|
+
`registry", read the last line of pnpm's output before believing it — the registry ` +
|
|
276
|
+
`answers an expired credential with 404, in the same words it uses for a package that ` +
|
|
277
|
+
`genuinely does not exist.`;
|
|
278
|
+
// The names are the copy's own declaration, never a pair written here: this
|
|
279
|
+
// step used to name `PUBLIC_API_BASE_URL`, which nothing in the storefront
|
|
280
|
+
// reads, and the fetchers fall back to `http://localhost:3001` in silence — so
|
|
281
|
+
// an author who followed it had a storefront talking to nothing in particular
|
|
282
|
+
// and no error anywhere to say so.
|
|
283
|
+
//
|
|
284
|
+
// **It is `addressOf`, not the shape of the value in `.env.example`.** That
|
|
285
|
+
// was the derivation until `NEXT_PUBLIC_SITE_URL` was supplied there, at which
|
|
286
|
+
// point a predicate reading *absolute `http(s)` URL* would have swept the
|
|
287
|
+
// shop's **own** public address into this sentence and told its owner it
|
|
288
|
+
// "names the backend this storefront talks to" — in a file they own outright
|
|
289
|
+
// and nobody comes back to correct.
|
|
290
|
+
const backendVariables = addressVariables(declared, 'backend');
|
|
291
|
+
// Which of those the run already answered. The step below stops telling an
|
|
292
|
+
// author to set a value that is already in the file this command wrote:
|
|
293
|
+
// instructions in a copy the client owns outright are not something anybody
|
|
294
|
+
// comes back to correct, so a stale one stays wrong for the life of the shop.
|
|
295
|
+
const answered = new Set(resolved.map((entry) => entry.name));
|
|
296
|
+
// Next's own convention, not ours: a `NEXT_PUBLIC_` variable is inlined into
|
|
297
|
+
// the client bundle by `next build`, so setting it afterwards changes nothing
|
|
298
|
+
// a browser sees. Saying which of the copy's variables that is costs a prefix
|
|
299
|
+
// test and saves the author a rebuild they would otherwise discover.
|
|
300
|
+
const baked = backendVariables.filter((name) => name.startsWith('NEXT_PUBLIC_'));
|
|
301
|
+
const unanswered = backendVariables.filter((name) => !answered.has(name));
|
|
302
|
+
const backendStep = () => unanswered.length === 0
|
|
303
|
+
? `check ${ENV_FILE} — this command wrote it, and every value in it is one you supplied ` +
|
|
304
|
+
`on the command line, one you had already put there, or one you were asked for. ` +
|
|
305
|
+
`${backendVariables.length === 0 ? '' : `${backendVariables.join(' and ')} name the ` +
|
|
306
|
+
`backend this storefront talks to; change ${backendVariables.length === 1 ? 'it' : 'them'} there. `}Nothing in it was invented — a generated secret is named in the ` +
|
|
307
|
+
`\`[inputs] resolved:\` line above and its value is in the file, never on your screen.`
|
|
308
|
+
: `set ${unanswered.join(' and ')} (and the rest of ${ENV_EXAMPLE_FILE}) to the ` +
|
|
309
|
+
`backend this storefront talks to. Its fetchers fall back to a compiled-in address when ` +
|
|
310
|
+
`the environment names none, so an instance that sets none of them talks to that ` +
|
|
311
|
+
`address rather than refusing.${baked.length === 0 ? '' : ` Next inlines ${baked.join(' and ')} into the browser bundle at build time, so set ${baked.length === 1 ? 'it' : 'them'} before \`pnpm run build\` rather than after.`}`;
|
|
312
|
+
return [
|
|
313
|
+
install,
|
|
314
|
+
backendStep(),
|
|
315
|
+
`pnpm run build — it runs \`themes:generate\`, \`next build\` and \`check:themes\`.`,
|
|
316
|
+
// Baseline step E4 (`specs/125-first-mile-install/spec.md` §2.3), which was
|
|
317
|
+
// printed nowhere: `storefront/package.json` has declared `start` all
|
|
318
|
+
// along, and a client who followed this block to the end had a built
|
|
319
|
+
// storefront and no command to serve it with.
|
|
320
|
+
`pnpm run start — the built storefront, served. \`pnpm run dev\` is the other one: the ` +
|
|
321
|
+
`same pages, rebuilt as you edit them, and the only one of the two that does not need a ` +
|
|
322
|
+
`build first.`,
|
|
323
|
+
`this storefront is yours now. There is no kit to upgrade and no shell to keep in step: a ` +
|
|
324
|
+
`fix to the platform reaches you through \`@endora-commerce/contracts\`, where a wire ` +
|
|
325
|
+
`change is a compile error rather than a runtime surprise.`,
|
|
326
|
+
];
|
|
327
|
+
}
|
|
328
|
+
export { StorefrontHostError, StorefrontInputError };
|
|
329
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/new-storefront/index.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The environment variable the auth line refers to.
|
|
3
|
+
*
|
|
4
|
+
* One name, spelled here and in `.gitlab-ci.yml`'s `publish:packages` job,
|
|
5
|
+
* because it is the name the contract writes (R3) and the one an operator is told
|
|
6
|
+
* to set. It is deliberately not an option: a per-scaffold variable name is a
|
|
7
|
+
* support conversation per client for no capability.
|
|
8
|
+
*/
|
|
9
|
+
export declare const TOKEN_VARIABLE = "ENDORA_NPM_TOKEN";
|
|
10
|
+
/**
|
|
11
|
+
* The registry URL as an `.npmrc` line writes it: absolute, `http(s)`, with the
|
|
12
|
+
* trailing slash GitLab's own troubleshooting requires (R3.2).
|
|
13
|
+
*/
|
|
14
|
+
export declare function normalizeRegistry(registry: string): string;
|
|
15
|
+
/**
|
|
16
|
+
* The scopes a scaffolded storefront installs from a registry.
|
|
17
|
+
*
|
|
18
|
+
* Read off the reference storefront's `workspace:` ranges — the packages that
|
|
19
|
+
* stop resolving the moment the copy leaves the workspace — rather than off the
|
|
20
|
+
* checkout's members. The two populations are not the same question: what the
|
|
21
|
+
* platform *publishes* is `check:release-intent`'s, and what this storefront
|
|
22
|
+
* *installs* is this one's.
|
|
23
|
+
*/
|
|
24
|
+
export declare function installedScopes(manifest: Record<string, unknown>): readonly string[];
|
|
25
|
+
/**
|
|
26
|
+
* The keys the auth lines are written under: the endpoint, and the host it is on.
|
|
27
|
+
*
|
|
28
|
+
* Both are npm's own spelling for a credential — the request URL with its scheme
|
|
29
|
+
* removed — and both matter, for two different fetches.
|
|
30
|
+
*
|
|
31
|
+
* **The endpoint key** is the narrowest key covering the one address the operator
|
|
32
|
+
* actually named, and it is what GitLab's own documentation writes. It is kept
|
|
33
|
+
* rather than replaced by the broader one below: pnpm was measured walking a
|
|
34
|
+
* request path upward — a key on `//host/api/v4/` authenticates a tarball under
|
|
35
|
+
* `/api/v4/projects/…` — so for pnpm the endpoint key is redundant, and a client
|
|
36
|
+
* matching these keys **exactly** would still authenticate the packument with it.
|
|
37
|
+
* No such client was measured here, so the honest reason to keep the line is the
|
|
38
|
+
* smaller one: dropping it would make the file say less than it knows about the
|
|
39
|
+
* one address the operator gave.
|
|
40
|
+
*
|
|
41
|
+
* **The host key** is the one that covers a tarball. It is broad on purpose: the
|
|
42
|
+
* tarball URL is chosen by the server and appears for the first time inside a
|
|
43
|
+
* packument this file will never see, so the only statically derivable key
|
|
44
|
+
* guaranteed to cover it is the whole host. Measured with a local registry
|
|
45
|
+
* standing in for GitLab's shape — a packument served on the endpoint whose
|
|
46
|
+
* `dist.tarball` names `/api/v4/projects/302/packages/npm/…` on the same host —
|
|
47
|
+
* under pnpm 9.15.0, the version CI pins, and under pnpm 10:
|
|
48
|
+
*
|
|
49
|
+
* endpoint key alone ERR_PNPM_FETCH_404 … Not Found - 404
|
|
50
|
+
* "No authorization header was set for the request."
|
|
51
|
+
* endpoint + host key the tarball request carries the header; the install
|
|
52
|
+
* completes.
|
|
53
|
+
*
|
|
54
|
+
* ### Why not a narrower prefix
|
|
55
|
+
*
|
|
56
|
+
* Not because a narrower one would fail — measured, `//host/api/v4/` and
|
|
57
|
+
* `//host/api/v4/projects/` both authenticate that same tarball, because pnpm
|
|
58
|
+
* walks a request's path upward looking for a key. The mechanism is not the
|
|
59
|
+
* obstacle; the **derivation** is. Getting `/api/v4/` out of
|
|
60
|
+
* `/api/v4/packages/npm/` means knowing GitLab's URL layout, which is trading one
|
|
61
|
+
* unexamined premise about the server for a narrower one — and `--registry` names
|
|
62
|
+
* *a registry*, not *a GitLab*: the flag is documented as the endpoint the
|
|
63
|
+
* storefront installs from, and a Verdaccio or an Artifactory behind it has its
|
|
64
|
+
* own layout. `ENDORA_NPM_REGISTRY` is masked and may be the instance endpoint or
|
|
65
|
+
* a group one, so the file cannot even be written against one observed shape.
|
|
66
|
+
*
|
|
67
|
+
* ### What is given up, stated rather than glossed
|
|
68
|
+
*
|
|
69
|
+
* The credential is offered to **every** request pnpm makes to this host and
|
|
70
|
+
* port, not only to the endpoint's own subtree. That is broader than the single
|
|
71
|
+
* line this file used to write. It is accepted because the host is the one the
|
|
72
|
+
* operator named on the command line, the credential a client is handed is a
|
|
73
|
+
* deploy token scoped `read_package_registry` (R3.3) whose whole authority on
|
|
74
|
+
* that host is reading packages, and the alternative — the credential not
|
|
75
|
+
* reaching the address the registry itself directed the client to — is an install
|
|
76
|
+
* that cannot work.
|
|
77
|
+
*
|
|
78
|
+
* And what it does **not** cover, so nobody reads it as more than it is: a
|
|
79
|
+
* registry that serves tarballs from a **different host** (a CDN, a storage
|
|
80
|
+
* bucket) is not reached by this key or by any other one derivable here, because
|
|
81
|
+
* that host appears nowhere in the input. Such a registry needs a line naming it,
|
|
82
|
+
* and the symptom would be this same 404 on the tarball alone.
|
|
83
|
+
*
|
|
84
|
+
* A registry configured at the root of its host makes the two keys identical, and
|
|
85
|
+
* then there is one line rather than two: a duplicate would not be wrong, it
|
|
86
|
+
* would read as though it said something.
|
|
87
|
+
*/
|
|
88
|
+
export declare function authKeys(registry: string): readonly string[];
|
|
89
|
+
/**
|
|
90
|
+
* The file's text: one registry line per scope, and the auth lines `authKeys`
|
|
91
|
+
* derives.
|
|
92
|
+
*
|
|
93
|
+
* There is one set of auth lines however many scopes there are, because a
|
|
94
|
+
* credential is a property of the endpoint rather than of a scope — the half of
|
|
95
|
+
* this file's original reasoning that survived the measurement above.
|
|
96
|
+
*/
|
|
97
|
+
export declare function npmrcContent(registry: string, scopes: readonly string[]): string;
|
|
98
|
+
//# sourceMappingURL=npmrc.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"npmrc.d.ts","sourceRoot":"","sources":["../../src/new-storefront/npmrc.ts"],"names":[],"mappings":"AAoDA;;;;;;;GAOG;AACH,eAAO,MAAM,cAAc,qBAAqB,CAAC;AAEjD;;;GAGG;AACH,wBAAgB,iBAAiB,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CA2C1D;AAED;;;;;;;;GAQG;AACH,wBAAgB,eAAe,CAAC,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,SAAS,MAAM,EAAE,CAQpF;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8DG;AACH,wBAAgB,QAAQ,CAAC,QAAQ,EAAE,MAAM,GAAG,SAAS,MAAM,EAAE,CAK5D;AAED;;;;;;;GAOG;AACH,wBAAgB,YAAY,CAAC,QAAQ,EAAE,MAAM,EAAE,MAAM,EAAE,SAAS,MAAM,EAAE,GAAG,MAAM,CAwBhF"}
|