@theholocron/cli 5.0.0-alpha.20 → 5.0.0-alpha.200
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 +305 -55
- package/dist/cli.mjs +6730 -2616
- package/dist/cli.mjs.map +1 -1
- package/dist/index.d.mts +222 -127
- package/dist/index.mjs +39 -54
- package/dist/plugin/capabilities.d.mts +647 -48
- package/dist/plugin/capabilities.mjs +2 -1
- package/package.json +19 -13
package/dist/index.mjs
CHANGED
|
@@ -1,14 +1,16 @@
|
|
|
1
1
|
import { CARDINALITY, ProviderApiError, REQUIRED_CAPABILITIES, WebhookVerificationError, isMulti } from "./plugin/capabilities.mjs";
|
|
2
2
|
import { AuthError, createResolveToken as createResolveToken$1, createRestClient } from "@theholocron/http-client";
|
|
3
|
-
import { createEnvLookup } from "@theholocron/env-utils";
|
|
3
|
+
import { createEnvLookup, withEnvPrefix } from "@theholocron/env-utils";
|
|
4
4
|
import { Entry, findCredentials } from "@napi-rs/keyring";
|
|
5
|
-
import { readFile } from "node:fs/promises";
|
|
6
5
|
import { basename, dirname, join } from "node:path";
|
|
7
|
-
import {
|
|
8
|
-
import { promisify } from "node:util";
|
|
6
|
+
import { readPackageJson } from "@theholocron/pkg-utils";
|
|
9
7
|
import { loadTasksConfig } from "@theholocron/astromech/config";
|
|
10
8
|
import { ConfigFileError, ConfigFileError as ConfigFileError$1, loadConfigFile } from "@theholocron/datapad";
|
|
11
|
-
|
|
9
|
+
import { readGitRemote } from "@theholocron/git-utils";
|
|
10
|
+
//#region src/env/env.ts
|
|
11
|
+
/** Singleton env for simple global lookups throughout the CLI. */
|
|
12
|
+
const env = createEnvLookup();
|
|
13
|
+
withEnvPrefix(env, "HOLOCRON");
|
|
12
14
|
/**
|
|
13
15
|
* Create an injectable env for commands that accept a fake env in tests.
|
|
14
16
|
* Pass `input.env` when available, falls back to `process.env`.
|
|
@@ -17,7 +19,7 @@ function makeEnv(source) {
|
|
|
17
19
|
return createEnvLookup(source);
|
|
18
20
|
}
|
|
19
21
|
//#endregion
|
|
20
|
-
//#region src/auth/keyring.ts
|
|
22
|
+
//#region src/auth/keyring/keyring.ts
|
|
21
23
|
/**
|
|
22
24
|
* Keyring-backed bootstrap credential store.
|
|
23
25
|
*
|
|
@@ -87,7 +89,7 @@ function listStoredProviders() {
|
|
|
87
89
|
}
|
|
88
90
|
}
|
|
89
91
|
//#endregion
|
|
90
|
-
//#region src/auth/auth-resolver.ts
|
|
92
|
+
//#region src/auth/auth-resolver/auth-resolver.ts
|
|
91
93
|
/** Wraps `createResolveToken` from `@theholocron/http` and injects the
|
|
92
94
|
* system keyring so plugins stay at a one-liner call site. */
|
|
93
95
|
function createResolveToken(config) {
|
|
@@ -113,7 +115,7 @@ function createFeatureResolver(config) {
|
|
|
113
115
|
};
|
|
114
116
|
}
|
|
115
117
|
//#endregion
|
|
116
|
-
//#region src/commands/setup/derived-properties.ts
|
|
118
|
+
//#region src/commands/setup/derived-properties/derived-properties.ts
|
|
117
119
|
/**
|
|
118
120
|
* Repo archetype, in priority order:
|
|
119
121
|
* 1. `*-template` repo name → `template` (independent of package shape).
|
|
@@ -184,7 +186,7 @@ function deriveCapabilities(providers) {
|
|
|
184
186
|
return Object.keys(providers ?? {}).sort();
|
|
185
187
|
}
|
|
186
188
|
/**
|
|
187
|
-
* `source` + `ci` are the minimal baseline every repo `holocron setup`
|
|
189
|
+
* `source` + `ci` are the minimal baseline every repo `holocron repo setup`
|
|
188
190
|
* touches wires — every `holocron.config.ts` in this org already satisfies
|
|
189
191
|
* this, so `non-compliant` here means drift (a provider manually removed
|
|
190
192
|
* after setup), not an unmet aspirational policy. Deliberately not a richer
|
|
@@ -213,14 +215,14 @@ function missingCapabilities(capabilities) {
|
|
|
213
215
|
*/
|
|
214
216
|
async function readWorkspacePackageJsons(repoRoot, workspacePackages) {
|
|
215
217
|
const results = [];
|
|
216
|
-
for (const { slug, dir = "packages" } of workspacePackages)
|
|
217
|
-
const
|
|
218
|
-
results.push(
|
|
219
|
-
}
|
|
218
|
+
for (const { slug, dir = "packages" } of workspacePackages) {
|
|
219
|
+
const pkg = await readPackageJson(join(repoRoot, dir, slug));
|
|
220
|
+
if (pkg) results.push(pkg);
|
|
221
|
+
}
|
|
220
222
|
return results;
|
|
221
223
|
}
|
|
222
224
|
//#endregion
|
|
223
|
-
//#region src/config/config.ts
|
|
225
|
+
//#region src/config/config/config.ts
|
|
224
226
|
var ConfigError = class extends Error {
|
|
225
227
|
name = "ConfigError";
|
|
226
228
|
};
|
|
@@ -324,11 +326,12 @@ function resolveConfig(raw) {
|
|
|
324
326
|
docs,
|
|
325
327
|
env: raw.env,
|
|
326
328
|
log: raw.log,
|
|
327
|
-
telemetry: raw.telemetry
|
|
329
|
+
telemetry: raw.telemetry,
|
|
330
|
+
eslint: raw.eslint
|
|
328
331
|
};
|
|
329
332
|
}
|
|
330
333
|
//#endregion
|
|
331
|
-
//#region src/config/compose.ts
|
|
334
|
+
//#region src/config/compose/compose.ts
|
|
332
335
|
function taskName(e) {
|
|
333
336
|
return typeof e === "string" ? e : e.name;
|
|
334
337
|
}
|
|
@@ -416,12 +419,12 @@ function compose(...args) {
|
|
|
416
419
|
};
|
|
417
420
|
}
|
|
418
421
|
//#endregion
|
|
419
|
-
//#region src/config/define-config.ts
|
|
422
|
+
//#region src/config/define-config/define-config.ts
|
|
420
423
|
function defineConfig(config) {
|
|
421
424
|
return config;
|
|
422
425
|
}
|
|
423
426
|
//#endregion
|
|
424
|
-
//#region src/config/load-config.ts
|
|
427
|
+
//#region src/config/load-config/load-config.ts
|
|
425
428
|
/**
|
|
426
429
|
* `holocron.config.{ts,js,mjs,cjs,json}` loader.
|
|
427
430
|
*
|
|
@@ -433,34 +436,39 @@ function defineConfig(config) {
|
|
|
433
436
|
* Probe order is TS-first (`.ts` → `.js` → `.mjs` → `.cjs` → `.json`) —
|
|
434
437
|
* see ADR-0010 / issue #75 / #81.
|
|
435
438
|
*/
|
|
436
|
-
const execFileAsync = promisify(execFile);
|
|
437
439
|
/**
|
|
438
|
-
* Read + parse + resolve `holocron.config.*` from the given
|
|
440
|
+
* Read + parse + resolve `holocron.config.*` starting from the given
|
|
441
|
+
* directory, walking up through ancestors to the nearest `.git` boundary
|
|
442
|
+
* when `cwd` itself has no match — every command is usable from any
|
|
443
|
+
* subdirectory of a repo, not only its exact root (see
|
|
444
|
+
* `@theholocron/datapad`'s own doc comment for the stop conditions).
|
|
439
445
|
* Throws {@link ConfigFileError} when nothing is found or a file cannot
|
|
440
|
-
* be loaded, or `ConfigError` when the config
|
|
446
|
+
* be loaded, or `ConfigError` when the config fails schema checks.
|
|
441
447
|
*/
|
|
442
448
|
async function loadConfig(cwd) {
|
|
443
449
|
const found = await loadConfigFile({
|
|
444
450
|
cwd,
|
|
445
|
-
name: "holocron"
|
|
451
|
+
name: "holocron",
|
|
452
|
+
walkUp: true
|
|
446
453
|
});
|
|
447
454
|
if (!found) throw new ConfigFileError$1(`no holocron.config.{ts,js,mjs,cjs,json} found in ${cwd}. Create one — see the README for the schema.`);
|
|
448
455
|
return {
|
|
449
|
-
resolved: resolveConfig(await deriveDefaults(
|
|
456
|
+
resolved: resolveConfig(await deriveDefaults(found)),
|
|
450
457
|
filepath: found.filepath
|
|
451
458
|
};
|
|
452
459
|
}
|
|
453
|
-
async function deriveDefaults(
|
|
454
|
-
const
|
|
460
|
+
async function deriveDefaults(found) {
|
|
461
|
+
const configDir = dirname(found.filepath);
|
|
462
|
+
const result = { ...found.config };
|
|
455
463
|
if (!result.name) result.name = await readPackageJsonName(configDir) ?? basename(configDir);
|
|
456
464
|
if (result.repo && !result.repo.name) {
|
|
457
|
-
const
|
|
458
|
-
if (
|
|
465
|
+
const remote = await readGitRemote(configDir);
|
|
466
|
+
if (remote?.host === "github.com") result.repo = {
|
|
459
467
|
...result.repo,
|
|
460
|
-
name:
|
|
468
|
+
name: remote.slug
|
|
461
469
|
};
|
|
462
470
|
}
|
|
463
|
-
const manifest = await loadTasksConfig(configDir);
|
|
471
|
+
const manifest = await loadTasksConfig(configDir, { holocron: found });
|
|
464
472
|
if (manifest.tasks) result.tasks = manifest.tasks;
|
|
465
473
|
if (manifest.syncScripts !== void 0) result.syncScripts = manifest.syncScripts;
|
|
466
474
|
if (manifest.holocronScript !== void 0) result.holocronScript = manifest.holocronScript;
|
|
@@ -469,31 +477,8 @@ async function deriveDefaults(configDir, raw) {
|
|
|
469
477
|
return result;
|
|
470
478
|
}
|
|
471
479
|
async function readPackageJsonName(dir) {
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
const pkg = JSON.parse(content);
|
|
475
|
-
return typeof pkg.name === "string" ? pkg.name.replace(/^@[^/]+\//, "") : void 0;
|
|
476
|
-
} catch {
|
|
477
|
-
return;
|
|
478
|
-
}
|
|
479
|
-
}
|
|
480
|
-
async function readGitRemote(dir) {
|
|
481
|
-
try {
|
|
482
|
-
const { stdout } = await execFileAsync("git", [
|
|
483
|
-
"remote",
|
|
484
|
-
"get-url",
|
|
485
|
-
"origin"
|
|
486
|
-
], { cwd: dir });
|
|
487
|
-
return parseGitRemoteUrl(stdout.trim());
|
|
488
|
-
} catch {
|
|
489
|
-
return;
|
|
490
|
-
}
|
|
491
|
-
}
|
|
492
|
-
function parseGitRemoteUrl(url) {
|
|
493
|
-
const httpsMatch = url.match(/github\.com\/([^/]+\/[^/]+?)(?:\.git)?$/);
|
|
494
|
-
if (httpsMatch) return httpsMatch[1];
|
|
495
|
-
const sshMatch = url.match(/github\.com:([^/]+\/[^/]+?)(?:\.git)?$/);
|
|
496
|
-
if (sshMatch) return sshMatch[1];
|
|
480
|
+
const name = (await readPackageJson(dir))?.name;
|
|
481
|
+
return name === void 0 ? void 0 : name.replace(/^@[^/]+\//, "");
|
|
497
482
|
}
|
|
498
483
|
//#endregion
|
|
499
484
|
export { AuthError, CARDINALITY, ConfigError, ConfigFileError, ProviderApiError, REQUIRED_CAPABILITIES, WebhookVerificationError, compose, createFeatureResolver, createResolveToken, createRestClient, defineConfig, deleteToken, deriveCapabilities, deriveCompliance, deriveProfile, deriveStack, getToken, isMulti, listStoredProviders, loadConfig, missingCapabilities, readWorkspacePackageJsons, resolveConfig, resolveEntry, resolvePluginPackage, setToken };
|