@pithy-sh/cli 0.1.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/package.json +72 -0
- package/scripts/templateManifest.ts +49 -0
- package/scripts/tsconfig.json +26 -0
- package/scripts/vendorTemplate.ts +84 -0
- package/scripts/verifyPack.ts +88 -0
- package/src/audit/cliAudit.ts +406 -0
- package/src/bin.ts +111 -0
- package/src/capabilities/add.ts +288 -0
- package/src/capabilities/addBootstrap.ts +275 -0
- package/src/capabilities/catalog.ts +175 -0
- package/src/capabilities/compose.ts +39 -0
- package/src/capabilities/configConstants.ts +74 -0
- package/src/capabilities/configImports.ts +397 -0
- package/src/capabilities/eject.ts +331 -0
- package/src/capabilities/emailProvisioner.ts +346 -0
- package/src/capabilities/entitlementGap.ts +70 -0
- package/src/capabilities/entryExports.ts +162 -0
- package/src/capabilities/flow.ts +550 -0
- package/src/capabilities/hostRegistry.ts +368 -0
- package/src/capabilities/loadFailure.ts +208 -0
- package/src/capabilities/manifests.ts +238 -0
- package/src/capabilities/mediaProvisioner.ts +471 -0
- package/src/capabilities/mintSecrets.ts +306 -0
- package/src/capabilities/paymentsProvisioner.ts +207 -0
- package/src/capabilities/prerequisites.ts +168 -0
- package/src/capabilities/r2Bucket.ts +113 -0
- package/src/capabilities/reconcile.ts +1483 -0
- package/src/capabilities/remove.ts +597 -0
- package/src/capabilities/requiredOptions.ts +92 -0
- package/src/capabilities/rotateSecrets.ts +305 -0
- package/src/capabilities/secrets.ts +178 -0
- package/src/capabilities/secretsDispatcher.ts +29 -0
- package/src/capabilities/secretsProvisioner.ts +389 -0
- package/src/capabilities/storageProvisioner.ts +414 -0
- package/src/capabilities/supportProvisioner.ts +515 -0
- package/src/capabilities/testersLoader.ts +52 -0
- package/src/capabilities/testersProvisioner.ts +236 -0
- package/src/capabilities/turnstileProvisioner.ts +347 -0
- package/src/capabilities/vectorProvisioner.ts +260 -0
- package/src/ci/fileModes.ts +223 -0
- package/src/ci/sourceFiles.ts +200 -0
- package/src/ci/workflowDrivers.ts +524 -0
- package/src/cloudflare/accountAnswer.ts +110 -0
- package/src/cloudflare/config.ts +685 -0
- package/src/cloudflare/storeId.ts +129 -0
- package/src/commands/add.ts +372 -0
- package/src/commands/alias.ts +205 -0
- package/src/commands/dashboard.ts +651 -0
- package/src/commands/deploy.ts +150 -0
- package/src/commands/dev.ts +37 -0
- package/src/commands/doctor.ts +2059 -0
- package/src/commands/email.ts +425 -0
- package/src/commands/env.ts +155 -0
- package/src/commands/feature.ts +359 -0
- package/src/commands/init.ts +538 -0
- package/src/commands/media.ts +303 -0
- package/src/commands/migrate.ts +129 -0
- package/src/commands/payments.ts +336 -0
- package/src/commands/provision.ts +368 -0
- package/src/commands/remove.ts +151 -0
- package/src/commands/secrets.ts +652 -0
- package/src/commands/seed.ts +229 -0
- package/src/commands/storage.ts +309 -0
- package/src/commands/support.ts +331 -0
- package/src/commands/testers.ts +1020 -0
- package/src/commands/token.ts +364 -0
- package/src/commands/turnstile.ts +271 -0
- package/src/commands/ui.ts +222 -0
- package/src/commands/upgrade.ts +517 -0
- package/src/commands/vector.ts +390 -0
- package/src/commands/worker.ts +295 -0
- package/src/dashboard/api.ts +323 -0
- package/src/dashboard/connect.ts +758 -0
- package/src/dashboard/contract.ts +289 -0
- package/src/dashboard/grant.ts +124 -0
- package/src/dashboard/registry.ts +519 -0
- package/src/dashboard/resolveTarget.ts +119 -0
- package/src/dev/delivery.ts +174 -0
- package/src/dev/devLogin.ts +155 -0
- package/src/dev/devLoginTargets.ts +91 -0
- package/src/dev/env.ts +206 -0
- package/src/dev/hostWorkers.ts +290 -0
- package/src/dev/keys.ts +111 -0
- package/src/dev/logging.ts +87 -0
- package/src/dev/openUrl.ts +75 -0
- package/src/dev/orchestrator.ts +1014 -0
- package/src/dev/ports.ts +220 -0
- package/src/dev/readyWatch.ts +142 -0
- package/src/dev/state.ts +90 -0
- package/src/devSecrets/bootstrapVars.ts +265 -0
- package/src/devSecrets/devVars.ts +240 -0
- package/src/devSecrets/edit.ts +256 -0
- package/src/devSecrets/file.ts +277 -0
- package/src/devSecrets/generate.ts +428 -0
- package/src/devSecrets/location.ts +80 -0
- package/src/devSecrets/mode.ts +71 -0
- package/src/devSecrets/records.ts +30 -0
- package/src/devSecrets/report.ts +99 -0
- package/src/devSecrets/seed.ts +344 -0
- package/src/devSecrets/store.ts +262 -0
- package/src/devSecrets/targets.ts +204 -0
- package/src/dispatch.ts +147 -0
- package/src/docs/catalog.ts +246 -0
- package/src/docs/writeCatalog.ts +45 -0
- package/src/doctor/cloudflare.ts +287 -0
- package/src/doctor/devPreferences.ts +155 -0
- package/src/doctor/devSecrets.ts +464 -0
- package/src/doctor/devVars.ts +414 -0
- package/src/doctor/devVarsLocal.ts +138 -0
- package/src/doctor/environments.ts +155 -0
- package/src/doctor/health.ts +354 -0
- package/src/doctor/localDelivery.ts +91 -0
- package/src/doctor/portsRegistry.ts +252 -0
- package/src/doctor/projectName.ts +584 -0
- package/src/doctor/secretBindings.ts +166 -0
- package/src/doctor/settings.ts +274 -0
- package/src/doctor/settingsSources.ts +202 -0
- package/src/doctor/workerName.ts +174 -0
- package/src/doctor/wranglerVars.ts +33 -0
- package/src/feature/bindings.ts +93 -0
- package/src/feature/create.ts +179 -0
- package/src/feature/destroy.ts +160 -0
- package/src/feature/devConfig.ts +201 -0
- package/src/feature/identity.ts +100 -0
- package/src/feature/manifest.ts +132 -0
- package/src/feature/ports.ts +615 -0
- package/src/feature/provision.ts +362 -0
- package/src/feature/sync.ts +148 -0
- package/src/feature/worktree.ts +282 -0
- package/src/help/groups.ts +47 -0
- package/src/help/rootUsage.ts +135 -0
- package/src/main.ts +73 -0
- package/src/migrations/ledger.ts +129 -0
- package/src/migrations/registry.ts +47 -0
- package/src/migrations/run.ts +1066 -0
- package/src/notifier/check.ts +129 -0
- package/src/notifier/installer.ts +48 -0
- package/src/notifier/notify.ts +152 -0
- package/src/notifier/state.ts +248 -0
- package/src/notifier/version.ts +59 -0
- package/src/platform/editor.ts +333 -0
- package/src/platform/rc.ts +118 -0
- package/src/platform/shell.ts +83 -0
- package/src/project/appBindings.ts +184 -0
- package/src/project/appWorkflows.ts +266 -0
- package/src/project/applyDomains.ts +166 -0
- package/src/project/askDomains.ts +220 -0
- package/src/project/atomic.ts +466 -0
- package/src/project/bindingEntries.ts +425 -0
- package/src/project/config.ts +701 -0
- package/src/project/dashboard.ts +118 -0
- package/src/project/deploy.ts +364 -0
- package/src/project/devVars.ts +113 -0
- package/src/project/domainPrompt.ts +191 -0
- package/src/project/domains.ts +386 -0
- package/src/project/envInventory.ts +356 -0
- package/src/project/environment.ts +125 -0
- package/src/project/extensions.ts +69 -0
- package/src/project/jsonc.ts +289 -0
- package/src/project/packageManager.ts +238 -0
- package/src/project/readOptionalFile.ts +342 -0
- package/src/project/rollback.ts +145 -0
- package/src/project/scaffold.ts +1088 -0
- package/src/project/templateFiles.ts +53 -0
- package/src/project/verifyDeploy.ts +230 -0
- package/src/project/versionMetadata.ts +77 -0
- package/src/project/workerAddress.ts +176 -0
- package/src/project/workerCommand.ts +564 -0
- package/src/project/workerIdentity.ts +50 -0
- package/src/project/workerManifest.ts +135 -0
- package/src/project/workerScaffold.ts +289 -0
- package/src/project/workerScope.ts +394 -0
- package/src/project/workers.ts +86 -0
- package/src/project/workflows.ts +281 -0
- package/src/project/wrangler.ts +168 -0
- package/src/provision/confirm.ts +86 -0
- package/src/provision/environment.ts +407 -0
- package/src/provision/featureConfig.ts +98 -0
- package/src/provision/mode.ts +62 -0
- package/src/provision/pendingSecrets.ts +96 -0
- package/src/provision/resources.ts +126 -0
- package/src/provision/secretBindings.ts +149 -0
- package/src/provision/store.ts +33 -0
- package/src/provision/unprovisioned.ts +114 -0
- package/src/provision/wranglerEnv.ts +220 -0
- package/src/rootFlags.ts +48 -0
- package/src/seed/drivers.ts +423 -0
- package/src/seed/media.ts +187 -0
- package/src/seed/plan.ts +137 -0
- package/src/seed/prepare.ts +224 -0
- package/src/seed/registry.ts +25 -0
- package/src/seed/run.ts +793 -0
- package/src/seed/safety.ts +206 -0
- package/src/terminal/logger.ts +42 -0
- package/src/terminal/output.ts +64 -0
- package/src/terminal/style.ts +132 -0
- package/src/test-utils/doctorHarness.ts +190 -0
- package/src/test-utils/migrateHarness.ts +126 -0
- package/src/test-utils/seedHarness.ts +173 -0
- package/src/test-utils/tempRepo.ts +45 -0
- package/src/tokens/config.ts +16 -0
- package/src/tokens/engine.ts +345 -0
- package/src/tokens/mintedTokens.ts +233 -0
- package/src/tokens/sinks.ts +84 -0
- package/src/ui/flow.ts +451 -0
- package/src/ui/react.ts +112 -0
- package/src/ui/routeAllowlist.ts +208 -0
- package/src/ui/scaffold.ts +113 -0
- package/src/ui/screenStyles.ts +127 -0
- package/src/ui/stubs.ts +135 -0
- package/src/ui/templates.ts +52 -0
- package/src/ui/wire.ts +311 -0
- package/src/ui/workerUi.ts +172 -0
- package/templates/starter/.dev.secrets.example.jsonc +43 -0
- package/templates/starter/.dev.vars.example +30 -0
- package/templates/starter/apps/api/package.json +22 -0
- package/templates/starter/apps/api/pithy.config.ts +65 -0
- package/templates/starter/apps/api/pithy.worker.jsonc +11 -0
- package/templates/starter/apps/api/src/bindings.workers.test.ts +18 -0
- package/templates/starter/apps/api/src/cloudflare-test.d.ts +11 -0
- package/templates/starter/apps/api/src/index.ts +8 -0
- package/templates/starter/apps/api/tsconfig.json +26 -0
- package/templates/starter/apps/api/wrangler.jsonc +68 -0
- package/templates/starter/biome.template.jsonc +75 -0
- package/templates/starter/gitignore +37 -0
- package/templates/starter/package.json +28 -0
- package/templates/starter/pithy.config.ts +67 -0
- package/templates/starter/plugins/no-console.grit +25 -0
- package/templates/starter/plugins/no-process-io.grit +25 -0
- package/templates/starter/tsconfig.json +14 -0
- package/templates/starter/tsconfig.tools.json +30 -0
- package/templates/starter/vitest.config.ts +124 -0
- package/templates/starter/vitest.workers.config.ts +26 -0
|
@@ -0,0 +1,200 @@
|
|
|
1
|
+
// SPDX-FileCopyrightText: 2026 Pithy
|
|
2
|
+
// SPDX-License-Identifier: MIT
|
|
3
|
+
|
|
4
|
+
import { type Dirent, readdirSync, readFileSync } from "node:fs";
|
|
5
|
+
import { join, sep } from "node:path";
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* The one walk over this repository's own source.
|
|
9
|
+
*
|
|
10
|
+
* Several tripwires here read every source file in the tree and assert something about the set —
|
|
11
|
+
* which modules can reach a `rename` (`project/atomic.test.ts`), which can probe with something that
|
|
12
|
+
* follows a link or run a recursive delete (`project/scaffold.test.ts`), which can resolve an editor
|
|
13
|
+
* (`platform/editor.test.ts`), which can export a pure value out of a Workers-runtime module
|
|
14
|
+
* (`capabilities/configEntrypoints.test.ts`) — and both halves of CI's own planner read every test file,
|
|
15
|
+
* one to work out which suites assert about which paths (`.github/scripts/crossPackageReads.ts`) and one
|
|
16
|
+
* to weight the shards they are dealt into (`.github/scripts/planShards.ts`).
|
|
17
|
+
*
|
|
18
|
+
* Each of those had written its own traversal, which made each one a separate place to get the same
|
|
19
|
+
* two things wrong. #157's was hardened when it was written and `atomic.test.ts`'s was not, so
|
|
20
|
+
* `atomic.test.ts` kept the bug: `ENOENT … packages/cli/.smoke-OXGbGb/pithy.config.ts` on a full-suite
|
|
21
|
+
* run (#185). A tripwire that flakes gets muted, and a muted tripwire is the defect it was built to
|
|
22
|
+
* catch, shipping.
|
|
23
|
+
*
|
|
24
|
+
* **Both halves of that failure live here, once.**
|
|
25
|
+
*
|
|
26
|
+
* 1. **The tree is not still.** Other suites scaffold whole projects into `packages/cli/.smoke-*` and
|
|
27
|
+
* `.e2e-*` and delete them on the way out, and `.worktrees/` holds entire second checkouts of this
|
|
28
|
+
* repository. A dotted directory is skipped — `.github` excepted, because its scripts are source
|
|
29
|
+
* this repository runs its CI on — which removes most of that outright, and a directory that
|
|
30
|
+
* cannot be listed and a file that vanished between the listing and the read are both skipped
|
|
31
|
+
* rather than fatal. A file that is not there is not a file that breaks a rule.
|
|
32
|
+
* `packages/cli/templates/`, which appears and disappears around `bun pm pack`, is the one that
|
|
33
|
+
* cannot be dotted; see {@link VENDORED_TEMPLATES}. The dotted rule is the one thing a caller may
|
|
34
|
+
* turn off — `dotted: true`, off by default, for the caller asking about *shipped files* rather than
|
|
35
|
+
* about this tree's source; see {@link SourceWalk.dotted} (#215).
|
|
36
|
+
* 2. **A symlink is not descended.** `withFileTypes` reports a link as a link rather than as the
|
|
37
|
+
* directory behind it, so a walk cannot loop on a link to an ancestor or read a package twice
|
|
38
|
+
* through the `node_modules` entry that points at it.
|
|
39
|
+
*
|
|
40
|
+
* Synchronous on purpose. It is read-only, it is called from tests and from the two CI scripts that run
|
|
41
|
+
* before `bun install`, and the async form bought a sequential `await` per directory rather than any
|
|
42
|
+
* concurrency. This module imports nothing but `node:fs` and `node:path` for the same reason: the
|
|
43
|
+
* `plan` job in `ci.yml` has no install step, so its whole import graph has to be builtins and relative
|
|
44
|
+
* paths. Adding a package dependency here breaks both scripts at once and is a change to that job.
|
|
45
|
+
*
|
|
46
|
+
* **That this is the only walk is a gate, not a claim.** #185 said it in a changeset and it was not true —
|
|
47
|
+
* five private traversals were never migrated, and none of them received the ENOENT tolerance above or
|
|
48
|
+
* #192's `templates` exclusion (#202). `sourceFiles.test.ts` now fails the build on any module that defines
|
|
49
|
+
* a function which lists a directory and calls itself, with the handful that cannot reach this one written
|
|
50
|
+
* down by name and reason. That list is now only the ones that *cannot*: `planShards.ts` was the last that
|
|
51
|
+
* merely had not been, and its `statSync` was the #185 race sitting in the script the whole matrix hangs
|
|
52
|
+
* off (#211).
|
|
53
|
+
*
|
|
54
|
+
* **The comment stripper these gates read with is no longer here.** `blankComments` was written beside
|
|
55
|
+
* this walk (#437) and moved to `@pithy-sh/core/src/text/comments` (#439), because
|
|
56
|
+
* `packages/core/src/worker-safety.test.ts` needs it and `@pithy-sh/core` must not depend on
|
|
57
|
+
* `@pithy-sh/cli`. Its own docblock carries the reasoning. Nothing in this module uses it, so the import
|
|
58
|
+
* graph above is unchanged: builtins and relative paths, still loadable by the `plan` job.
|
|
59
|
+
*/
|
|
60
|
+
|
|
61
|
+
/** A file the walk found, with the text it still held when the walk read it. */
|
|
62
|
+
export interface SourceFile {
|
|
63
|
+
/** Absolute path to the file. */
|
|
64
|
+
readonly path: string;
|
|
65
|
+
/** Its contents at the moment it was read. */
|
|
66
|
+
readonly text: string;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
/** How a walk narrows the tree — and, in one case, widens it. */
|
|
70
|
+
export interface SourceWalk {
|
|
71
|
+
/** Directory names never descended into, on top of the built-in set. */
|
|
72
|
+
readonly skip?: readonly string[];
|
|
73
|
+
/** Which files to keep, by base name. Defaults to {@link isShippedSource}. */
|
|
74
|
+
readonly keep?: (name: string) => boolean;
|
|
75
|
+
/**
|
|
76
|
+
* Enter dotted directories as well. **Off unless a caller says otherwise**, because the rule it lifts
|
|
77
|
+
* is what keeps `.smoke-*`, `.e2e-*` and `.worktrees/` out of every other caller (#185).
|
|
78
|
+
*
|
|
79
|
+
* For the caller whose question is about *shipped files* rather than about this repository's source: a
|
|
80
|
+
* license audit asks that every file a template carries has the right header, and a template that grew
|
|
81
|
+
* a `.vscode/` or a `.husky/` would ship every file in it unchecked. A gate whose reach is narrower
|
|
82
|
+
* than the rule it enforces under-reports in silence (#215).
|
|
83
|
+
*
|
|
84
|
+
* It widens the dotted rule and nothing else. `node_modules`, `dist`, `coverage`, whatever the caller
|
|
85
|
+
* named in `skip`, the vendored template copy and a symlinked directory are all still refused, and
|
|
86
|
+
* `keep` still decides which files are taken.
|
|
87
|
+
*
|
|
88
|
+
* **It has no caller in this repository, deliberately, and it stays (#222).** The caller it was built
|
|
89
|
+
* for is `tooling/license-headers`, which cannot import `@pithy-sh/cli` — #211 declined that edge on
|
|
90
|
+
* direction of narrowing, since the linter that stamps this package's own headers running in
|
|
91
|
+
* `lint-staged` must not become a dependent of the largest thing it lints. What the option buys is not
|
|
92
|
+
* a call site. It is that the exception recorded against that walk in `./sourceFiles.test.ts` states a
|
|
93
|
+
* true reason: #202's entry named the `templates` skip as the blocker and #211 found that false, and
|
|
94
|
+
* the real blocker it recorded in its place — this walker cannot enter a dotted directory, and the
|
|
95
|
+
* license audit must — would be false in the other direction if this were removed. An exception list
|
|
96
|
+
* whose reasons have quietly stopped being true is the failure mode #211 corrected, and removing the
|
|
97
|
+
* option to re-add it with the edge would cost the same work twice. One branch, asserted where it is.
|
|
98
|
+
*/
|
|
99
|
+
readonly dotted?: boolean;
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
/**
|
|
103
|
+
* Never walked: dependencies, build output, coverage. Every other exclusion is the dotted rule, which
|
|
104
|
+
* covers `.git`, `.turbo`, `.changeset`, `.worktrees`, and the test scaffolds this exists for.
|
|
105
|
+
*/
|
|
106
|
+
const NEVER = ["node_modules", "dist", "coverage"];
|
|
107
|
+
|
|
108
|
+
/** The one dotted directory that holds source: this repository's CI scripts. */
|
|
109
|
+
const DOTTED_SOURCE = ".github";
|
|
110
|
+
|
|
111
|
+
/**
|
|
112
|
+
* The one transient the dotted rule cannot cover: `packages/cli/templates`, the copy of the repo root's
|
|
113
|
+
* `templates/starter` that `prepack` vendors in and `postpack` takes out again.
|
|
114
|
+
*
|
|
115
|
+
* It cannot be dotted and it cannot move. `files` in the CLI's manifest carries exactly this path, and
|
|
116
|
+
* that is the entire mechanism by which a published `@pithy-sh/cli` ships a starter at all (#143, #152).
|
|
117
|
+
* So the walk skips it by where it is instead — by path, never by name, because the repo root's
|
|
118
|
+
* `templates/` is the source of truth these tripwires exist to read.
|
|
119
|
+
*
|
|
120
|
+
* **Skipping is right whether or not a pack is in flight.** It is a file-by-file copy of a directory the
|
|
121
|
+
* same walk already visits at the repo root, so descending into it can only ever report a source twice,
|
|
122
|
+
* under a second path that `postpack` is about to delete — and a pack that fails after `prepack` leaves
|
|
123
|
+
* the copy behind for good, gitignored and silent, which makes the duplicate permanent rather than
|
|
124
|
+
* transient. Either way a gate that reports a path, counts files, or asserts a set gets a different
|
|
125
|
+
* answer depending on what a packer did, and a report naming the copy names a file nobody can open (#192).
|
|
126
|
+
*/
|
|
127
|
+
const VENDORED_TEMPLATES = join("packages", "cli", "templates");
|
|
128
|
+
|
|
129
|
+
/** A `.ts` file that ships — neither a test nor a generated declaration. */
|
|
130
|
+
export function isShippedSource(name: string): boolean {
|
|
131
|
+
return name.endsWith(".ts") && !name.endsWith(".test.ts") && !name.endsWith(".d.ts");
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
/** A test file, in every spelling this repository uses — `x.test.ts` and `x.workers.test.ts` alike. */
|
|
135
|
+
export function isTestFile(name: string): boolean {
|
|
136
|
+
return name.endsWith(".test.ts");
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
/** A walk with every default resolved, so {@link descend} decides nothing for itself. */
|
|
140
|
+
interface Walk {
|
|
141
|
+
/** Directory names never descended into: the built-in set and the caller's own. */
|
|
142
|
+
readonly skip: ReadonlySet<string>;
|
|
143
|
+
/** Which files to keep, by base name. */
|
|
144
|
+
readonly keep: (name: string) => boolean;
|
|
145
|
+
/** Whether a dotted directory is entered. See {@link SourceWalk.dotted}. */
|
|
146
|
+
readonly dotted: boolean;
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
/** Every file under `root` that `keep` accepts, absolute and sorted. A root that is not there is empty. */
|
|
150
|
+
export function sourcePaths(root: string, options: SourceWalk = {}): string[] {
|
|
151
|
+
const walk: Walk = {
|
|
152
|
+
skip: new Set([...NEVER, ...(options.skip ?? [])]),
|
|
153
|
+
keep: options.keep ?? isShippedSource,
|
|
154
|
+
dotted: options.dotted ?? false,
|
|
155
|
+
};
|
|
156
|
+
const found: string[] = [];
|
|
157
|
+
descend(root, walk, found);
|
|
158
|
+
return found.sort();
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
/** `path`'s contents, or null if it is no longer there — or was never readable. */
|
|
162
|
+
export function readSource(path: string): string | null {
|
|
163
|
+
try {
|
|
164
|
+
return readFileSync(path, "utf8");
|
|
165
|
+
} catch {
|
|
166
|
+
return null;
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
/** Every file {@link sourcePaths} finds, with its text. One that vanished before the read is dropped. */
|
|
171
|
+
export function sourceFiles(root: string, options?: SourceWalk): SourceFile[] {
|
|
172
|
+
const found: SourceFile[] = [];
|
|
173
|
+
for (const path of sourcePaths(root, options)) {
|
|
174
|
+
const text = readSource(path);
|
|
175
|
+
if (text !== null) found.push({ path, text });
|
|
176
|
+
}
|
|
177
|
+
return found;
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
/** One directory, and everything below it. A directory that cannot be listed contributes nothing. */
|
|
181
|
+
function descend(directory: string, walk: Walk, into: string[]): void {
|
|
182
|
+
let entries: Dirent[];
|
|
183
|
+
try {
|
|
184
|
+
entries = readdirSync(directory, { withFileTypes: true });
|
|
185
|
+
} catch {
|
|
186
|
+
return;
|
|
187
|
+
}
|
|
188
|
+
for (const entry of entries) {
|
|
189
|
+
const path = join(directory, entry.name);
|
|
190
|
+
if (entry.isDirectory()) {
|
|
191
|
+
if (walk.skip.has(entry.name)) continue;
|
|
192
|
+
if (!walk.dotted && entry.name.startsWith(".") && entry.name !== DOTTED_SOURCE) continue;
|
|
193
|
+
// Whatever root the walk began at, the path it built carries the ancestry that identifies the copy.
|
|
194
|
+
if (path === VENDORED_TEMPLATES || path.endsWith(`${sep}${VENDORED_TEMPLATES}`)) continue;
|
|
195
|
+
descend(path, walk, into);
|
|
196
|
+
continue;
|
|
197
|
+
}
|
|
198
|
+
if (entry.isFile() && walk.keep(entry.name)) into.push(path);
|
|
199
|
+
}
|
|
200
|
+
}
|