@theholocron/cli 5.0.0-alpha.16 → 5.0.0-alpha.160

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/dist/index.d.mts CHANGED
@@ -1,18 +1,22 @@
1
- import { Analytics, Auth, AuthDescription, AuthEvent, AuthEventType, AuthIdentity, AuthUser, CARDINALITY, CapabilityImpls, CapabilityKey, Cardinality, CardinalityFor, Ci, CiRun, CiRunFilter, CiRunStatus, ConnectionStringOptions, CreateAuthUserInput, Deployment, DeploymentProject, DeploymentProjectSettings, DeploymentRecord, DeploymentTarget, DeploymentTrigger, Dns, DnsRecord, DnsRecordType, EnsureResult, Environment, EnvironmentReviewer, Environments, Errors, Issue, IssueSearchFilter, Issues, LabelDef, LifecycleResult, LifecycleSlot, Logs, NormalizedAuthUser, Notifications, PagesConfig, ParseWebhookInput, ProviderApiError, ProviderIdentity, PullRequest, REQUIRED_CAPABILITIES, RepoRef, RepoSettings, ResolvedCapability, Ruleset, SecretScope, Secrets, Source, StatusCategory, Storage, StorageBranch, TeamEntry, TeamPermission, Tooling, ToolingDoctorReport, TrackerDoctorReport, TrackerUser, Vault, WebhookDashboardInfo, WebhookVerificationError, Wiki, WikiDnsRecord, WikiProvisionOpts, WikiProxyConfig, Workers, isMulti } from "./plugin/capabilities.mjs";
1
+ import { Analytics, Auth, AuthDescription, AuthEvent, AuthEventType, AuthIdentity, AuthUser, CARDINALITY, CapabilityImpls, CapabilityKey, Cardinality, CardinalityFor, Ci, CiRun, CiRunFilter, CiRunStatus, ConnectionStringOptions, CreateAuthUserInput, DeployFunctionConfig, DeployFunctionResult, DeployScriptConfig, DeployScriptResult, Deployment, DeploymentProject, DeploymentProjectSettings, DeploymentRecord, DeploymentTarget, DeploymentTrigger, Dns, DnsRecord, DnsRecordRequest, DnsRecordType, EnsureResult, Environment, EnvironmentReviewer, Environments, Errors, Issue, IssueSearchFilter, Issues, LabelDef, LifecycleResult, LifecycleSlot, Logs, Monitoring, MonitoringAssertion, MonitoringAssertionComparison, MonitoringAssertionSource, MonitoringCheck, MonitoringCheckInput, MonitoringHttpMethod, NormalizedAuthUser, Notifications, PagesConfig, ParseWebhookInput, ProviderApiError, ProviderIdentity, PullRequest, REQUIRED_CAPABILITIES, RepoRef, RepoSettings, ResolvedCapability, Ruleset, SecretScope, Secrets, Source, StatusCategory, Storage, StorageBranch, TeamEntry, TeamPermission, Tooling, ToolingDoctorReport, TrackerDoctorReport, TrackerUser, Vault, WebhookDashboardInfo, WebhookVerificationError, Wiki, WikiProvisionOpts, WikiProxyConfig, Workers, isMulti } from "./plugin/capabilities.mjs";
2
2
  import { AuthError, RequestOptions, ResolveTokenConfig as ResolveTokenConfig$1, ResolveTokenInput, RestClient, RestClientConfig, createRestClient } from "@theholocron/http-client";
3
+ import { PackageJson } from "@theholocron/pkg-utils";
3
4
  import { ConfigFileError } from "@theholocron/datapad";
4
5
  import { LogLevel } from "@theholocron/observability/core";
5
- //#region src/auth/auth-resolver.d.ts
6
+ import { WorkspacePackage } from "@theholocron/astromech";
7
+ //#region src/auth/auth-resolver/auth-resolver.type.d.ts
6
8
  type ResolveTokenConfig = Omit<ResolveTokenConfig$1, "getKeyringToken">;
7
- /** Wraps `createResolveToken` from `@theholocron/http` and injects the
8
- * system keyring so plugins stay at a one-liner call site. */
9
- declare function createResolveToken(config: ResolveTokenConfig): (input?: ResolveTokenInput) => string;
10
9
  interface FeatureResolverConfig {
11
10
  /** Env var name for this feature, e.g. `"HOLOCRON_ISSUES_TOKEN"`. */
12
11
  envName: string;
13
12
  /** Keyring account key, e.g. `"github.issues"`. */
14
13
  keyringKey: string;
15
14
  }
15
+ //#endregion
16
+ //#region src/auth/auth-resolver/auth-resolver.d.ts
17
+ /** Wraps `createResolveToken` from `@theholocron/http` and injects the
18
+ * system keyring so plugins stay at a one-liner call site. */
19
+ declare function createResolveToken(config: ResolveTokenConfig): (input?: ResolveTokenInput) => string;
16
20
  /**
17
21
  * Build a strict, single-feature token resolver.
18
22
  *
@@ -22,7 +26,7 @@ interface FeatureResolverConfig {
22
26
  */
23
27
  declare function createFeatureResolver(config: FeatureResolverConfig): (input?: ResolveTokenInput) => string;
24
28
  //#endregion
25
- //#region src/auth/keyring.d.ts
29
+ //#region src/auth/keyring/keyring.d.ts
26
30
  /**
27
31
  * Keyring-backed bootstrap credential store.
28
32
  *
@@ -66,7 +70,20 @@ declare function deleteToken(provider: string): boolean;
66
70
  */
67
71
  declare function listStoredProviders(): string[];
68
72
  //#endregion
69
- //#region src/config/config.d.ts
73
+ //#region src/commands/auth/auth.type.d.ts
74
+ interface VerifyTokenSuccess {
75
+ ok: true;
76
+ /** "workplace: acme" / "user: cnewton@x" — surfaced in success output. */
77
+ subject: string;
78
+ }
79
+ interface VerifyTokenFailure {
80
+ ok: false;
81
+ /** Reason the token was rejected. Surfaces to the operator. */
82
+ message: string;
83
+ }
84
+ type VerifyTokenResult = VerifyTokenSuccess | VerifyTokenFailure;
85
+ //#endregion
86
+ //#region src/config/config/config.type.d.ts
70
87
  /** Structured-logging config. The Axiom **token** never lives here — only in
71
88
  * env vars or the OS keyring — but the non-secret dataset name may. */
72
89
  interface LogConfig {
@@ -140,7 +157,7 @@ interface DocsConfig {
140
157
  * GitHub Pages build source.
141
158
  * "workflow" → GitHub Actions (PUT { build_type: "workflow" })
142
159
  * "branch" → classic gh-pages branch (PUT { build_type: "legacy", source: { branch: "gh-pages", path: "/" } })
143
- * When absent, Pages is not managed by `holocron setup`.
160
+ * When absent, Pages is not managed by `holocron repo setup`.
144
161
  */
145
162
  build?: "workflow" | "branch";
146
163
  /**
@@ -162,7 +179,22 @@ interface RepoConfig {
162
179
  /** "owner/name" — the GitHub repository coordinate. Derived from the git remote when absent. */
163
180
  name?: string;
164
181
  /**
165
- * Branch protection preset applied by `holocron setup`. When omitted,
182
+ * GitHub's repo-level default branch (`HEAD`) — what a fresh clone checks
183
+ * out, what `gh pr create`/the compare UI target by default, and what
184
+ * Sentinel's `validateConfig()` reads (D6: the App only ever reads config
185
+ * from the repo's default branch, never a PR ref, as a security boundary
186
+ * — never widen that to read PR branches instead of fixing this field).
187
+ * Synced by `holocron repo setup`. Omit to leave GitHub's current setting
188
+ * untouched — most repos never need this. Exists for a repo using a
189
+ * `main`/`alpha` prerelease-channel split (CLAUDE.md's Releases section)
190
+ * where active development happens on a non-`main` branch: set this to
191
+ * that branch so Sentinel validates against what's actually being
192
+ * developed, then change it back once that branch merges to `main` for a
193
+ * stable cut and stops being the active branch.
194
+ */
195
+ defaultBranch?: string;
196
+ /**
197
+ * Branch protection preset applied by `holocron repo setup`. When omitted,
166
198
  * no protection is applied and no `branch_protection_level` property is set.
167
199
  * Required-status-check contexts for `"strict"` are derived from the task
168
200
  * manifest — `{ required: true }` tasks + top-level `extraRequiredChecks`
@@ -170,7 +202,7 @@ interface RepoConfig {
170
202
  */
171
203
  protection?: RepoProtection;
172
204
  /**
173
- * GitHub teams granted repository access. Synced by `holocron setup`, which
205
+ * GitHub teams granted repository access. Synced by `holocron repo setup`, which
174
206
  * also writes `.github/CODEOWNERS` for teams with write-or-higher permission.
175
207
  * String shorthand defaults to `push` (Write).
176
208
  */
@@ -270,7 +302,7 @@ interface StorybookDeployProject {
270
302
  * `run-chromatic` accepts either a plain boolean (single-project) or a
271
303
  * `ChromaticProjectConfig[]` object (multi-project monorepo).
272
304
  *
273
- * `docs` / `storybook` are high-level deploy shorthand that `holocron setup`
305
+ * `docs` / `storybook` are high-level deploy shorthand that `holocron repo setup`
274
306
  * translates to `type` / `storybook-projects` before writing the thin caller.
275
307
  * They also drive automatic `paths:` derivation so you never need to write
276
308
  * `paths:` manually for deploy entries.
@@ -298,18 +330,18 @@ interface TaskEntryConfig {
298
330
  with?: WorkflowWithConfig;
299
331
  paths?: string[];
300
332
  linters?: string[];
301
- /** Emit a `.github/workflows/<name>.yml` thin caller + include in `holocron ci`. Default `true`. */
333
+ /** Emit a `.github/workflows/<name>.yml` thin caller + include in `holocron run ci`. Default `true`. */
302
334
  ci?: boolean;
303
335
  /** Write a `package.json` script + let `holocron run <name>` resolve the task. Default `true`. */
304
336
  local?: boolean;
305
- /** The task's CI check context is a required status check + part of `holocron ci`'s default run. */
337
+ /** The task's CI check context is a required status check + part of `holocron run ci`'s default run. */
306
338
  required?: boolean;
307
339
  }
308
340
  interface HolocronConfig {
309
341
  /** Project name. Derived from package.json when absent. */
310
342
  name?: string;
311
343
  description?: string;
312
- /** Project homepage URL. Synced to package.json#homepage and the GitHub repo's website field by `holocron sync`. */
344
+ /** Project homepage URL. Synced to package.json#homepage and the GitHub repo's website field by `holocron repo sync`. */
313
345
  homepage?: string;
314
346
  /**
315
347
  * Active org name for namespaced keyring lookup. When set, token resolution
@@ -335,7 +367,7 @@ interface HolocronConfig {
335
367
  * The task manifest — what this repo runs. Each entry is a task name
336
368
  * (backed by a reusable workflow in `theholocron/.github`), or the object
337
369
  * form to pass `with:` inputs. `@theholocron/astromech` reads this as the
338
- * single source for `holocron run` / `holocron ci` / the generated CI
370
+ * single source for `holocron run` / `holocron run ci` / the generated CI
339
371
  * workflows / `package.json` scripts.
340
372
  *
341
373
  * Supported values (intent-facing vocabulary — epic #672, D3):
@@ -348,7 +380,7 @@ interface HolocronConfig {
348
380
  * "knowledge.wiki" | "knowledge.docs" | "knowledge.components" |
349
381
  * "review" | "tag" | "stale" | "greetings" | "dependencies" | "bookkeeping"
350
382
  *
351
- * `holocron setup` writes `.github/workflows/<name>.yml` for each entry,
383
+ * `holocron repo setup` writes `.github/workflows/<name>.yml` for each entry,
352
384
  * calling the corresponding reusable workflow in `theholocron/.github`.
353
385
  * Files are overwritten on each run — they are generated artifacts.
354
386
  *
@@ -397,7 +429,7 @@ interface HolocronConfig {
397
429
  * }
398
430
  * ```
399
431
  * Each `tokenName` maps to a repository secret named
400
- * `CHROMATIC_PROJECT_TOKEN_<TOKENNAME>`. `holocron setup` expands this
432
+ * `CHROMATIC_PROJECT_TOKEN_<TOKENNAME>`. `holocron repo setup` expands this
401
433
  * to the flat `run-chromatic: true` + `chromatic-projects: <json>` inputs
402
434
  * that the reusable workflow accepts.
403
435
  *
@@ -407,7 +439,7 @@ interface HolocronConfig {
407
439
  */
408
440
  tasks?: Array<string | TaskEntryConfig>;
409
441
  /**
410
- * Opt out of `holocron sync`'s `package.json` script writes. Default `true`.
442
+ * Opt out of `holocron repo sync`'s `package.json` script writes. Default `true`.
411
443
  */
412
444
  syncScripts?: boolean;
413
445
  /**
@@ -418,15 +450,15 @@ interface HolocronConfig {
418
450
  holocronScript?: string;
419
451
  /**
420
452
  * Required status-check contexts not backed by a `required` task (codecov
421
- * gates, the bundle-build check, …). `holocron setup` appends these to the
453
+ * gates, the bundle-build check, …). `holocron repo setup` appends these to the
422
454
  * task-derived list from `astromech.requiredChecks()`.
423
455
  */
424
456
  extraRequiredChecks?: string[];
425
457
  /**
426
- * Git hooks `holocron setup` installs. `true` / `{ prePush: true }` writes
427
- * `.husky/pre-push` (runs `holocron ci` before every push); `false` /
458
+ * Git hooks `holocron repo setup` installs. `true` / `{ prePush: true }` writes
459
+ * `.husky/pre-push` (runs `holocron run ci` before every push); `false` /
428
460
  * `{ prePush: false }` opts out. Omitted → on for `protection: "strict"`,
429
- * off otherwise. `--hooks` / `--no-hooks` on `holocron setup` override.
461
+ * off otherwise. `--hooks` / `--no-hooks` on `holocron repo setup` override.
430
462
  */
431
463
  hooks?: boolean | {
432
464
  prePush?: boolean;
@@ -435,7 +467,7 @@ interface HolocronConfig {
435
467
  apps?: AppConfig[];
436
468
  doctor?: DoctorConfig;
437
469
  /**
438
- * Agent runtime that determines where skills are installed by `holocron setup`.
470
+ * Agent runtime that determines where skills are installed by `holocron repo setup`.
439
471
  * Skills are installed to `.agents/skills/<name>/` (canonical) with a
440
472
  * relative symlink at the agent-specific path:
441
473
  * - `"claude"` → `.claude/skills/<name>` → `../../.agents/skills/<name>`
@@ -443,7 +475,7 @@ interface HolocronConfig {
443
475
  */
444
476
  agent?: "claude" | "codex" | "gemini";
445
477
  /**
446
- * Skill names from `@theholocron/skills` to install during `holocron setup`.
478
+ * Skill names from `@theholocron/skills` to install during `holocron repo setup`.
447
479
  * Installed paths are gitignored and managed by setup — do not commit them.
448
480
  *
449
481
  * @example
@@ -451,7 +483,7 @@ interface HolocronConfig {
451
483
  */
452
484
  skills?: string[];
453
485
  /**
454
- * GitHub Pages configuration. When present, `holocron setup` calls the
486
+ * GitHub Pages configuration. When present, `holocron repo setup` calls the
455
487
  * Pages API using `HOLOCRON_DEPLOY_TOKEN` (requires `pages:write` + `repo` scope).
456
488
  * When absent, Pages is left as-is.
457
489
  *
@@ -487,6 +519,29 @@ interface HolocronConfig {
487
519
  * { analytics: "none" }
488
520
  */
489
521
  telemetry?: TelemetryConfig;
522
+ /**
523
+ * ESLint bundle option overrides that Sentinel's centralized static-
524
+ * analysis check (holocron#849) can't otherwise see. Bucket 1 checks
525
+ * never read a PR's own committed files for config — this is the
526
+ * declared source of truth Sentinel reads instead, so its check stays
527
+ * in sync with what each package's own `eslint.config.ts` already
528
+ * enforces locally and in CI.
529
+ */
530
+ eslint?: EslintConfig;
531
+ }
532
+ /**
533
+ * Repo-root-relative directories treated as browser-targeted for eslint's
534
+ * node-builtins compatibility checks — mirrors
535
+ * `@theholocron/eslint-config`'s `library({ browserPackages })` option.
536
+ * Only needed for a package whose own `eslint.config.ts` already declares
537
+ * `browserPackages` (a deliberate outlier, not the norm — see that
538
+ * package's own config file for why).
539
+ *
540
+ * @example
541
+ * { browserPackages: ["packages/github-client/src/app-auth"] }
542
+ */
543
+ interface EslintConfig {
544
+ browserPackages?: string[];
490
545
  }
491
546
  interface ResolvedTuple {
492
547
  provider: string;
@@ -526,7 +581,10 @@ interface ResolvedHolocronConfig {
526
581
  env?: EnvConfig;
527
582
  log?: LogConfig;
528
583
  telemetry?: TelemetryConfig;
584
+ eslint?: EslintConfig;
529
585
  }
586
+ //#endregion
587
+ //#region src/config/config/config.d.ts
530
588
  declare class ConfigError extends Error {
531
589
  name: string;
532
590
  }
@@ -539,7 +597,7 @@ declare function resolvePluginPackage(provider: string): string;
539
597
  declare function resolveEntry(key: CapabilityKey, raw: RawProviderEntry): ResolvedProviderEntry;
540
598
  declare function resolveConfig(raw: HolocronConfig): ResolvedHolocronConfig;
541
599
  //#endregion
542
- //#region src/config/compose.d.ts
600
+ //#region src/config/compose/compose.type.d.ts
543
601
  type TaskEntry = NonNullable<HolocronConfig["tasks"]>[number];
544
602
  /** A single composable capability fragment. */
545
603
  interface Capability {
@@ -578,6 +636,8 @@ interface ComposedPreset {
578
636
  domain?: string;
579
637
  docs?: DocsConfig;
580
638
  }
639
+ //#endregion
640
+ //#region src/config/compose/compose.d.ts
581
641
  /**
582
642
  * Merge any number of capability fragments into a single preset object that
583
643
  * spreads directly into `defineConfig()`.
@@ -601,20 +661,99 @@ interface ComposedPreset {
601
661
  */
602
662
  declare function compose(...args: (Capability | Capability[])[]): ComposedPreset;
603
663
  //#endregion
604
- //#region src/config/define-config.d.ts
664
+ //#region src/config/define-config/define-config.d.ts
605
665
  declare function defineConfig(config: HolocronConfig): HolocronConfig;
606
666
  //#endregion
607
- //#region src/config/load-config.d.ts
667
+ //#region src/config/load-config/load-config.type.d.ts
608
668
  interface LoadedConfig {
609
669
  resolved: ResolvedHolocronConfig;
610
670
  /** Absolute path to the file the config was read from. */
611
671
  filepath: string;
612
672
  }
673
+ //#endregion
674
+ //#region src/config/load-config/load-config.d.ts
613
675
  /**
614
- * Read + parse + resolve `holocron.config.*` from the given directory.
676
+ * Read + parse + resolve `holocron.config.*` starting from the given
677
+ * directory, walking up through ancestors to the nearest `.git` boundary
678
+ * when `cwd` itself has no match — every command is usable from any
679
+ * subdirectory of a repo, not only its exact root (see
680
+ * `@theholocron/datapad`'s own doc comment for the stop conditions).
615
681
  * Throws {@link ConfigFileError} when nothing is found or a file cannot
616
- * be loaded, or `ConfigError` when the config is invalid.
682
+ * be loaded, or `ConfigError` when the config fails schema checks.
617
683
  */
618
684
  declare function loadConfig(cwd: string): Promise<LoadedConfig>;
619
685
  //#endregion
620
- export { Analytics, AppConfig, Auth, AuthDescription, AuthError, AuthEvent, AuthEventType, AuthIdentity, AuthUser, CARDINALITY, Capability, CapabilityConfigPackage, CapabilityImpls, CapabilityKey, Cardinality, CardinalityFor, ChromaticProjectConfig, Ci, CiRun, CiRunFilter, CiRunStatus, ComposedPreset, ConfigError, ConfigFileError, ConnectionStringOptions, CreateAuthUserInput, Deployment, DeploymentProject, DeploymentProjectSettings, DeploymentRecord, DeploymentTarget, DeploymentTrigger, Dns, DnsRecord, DnsRecordType, DocsConfig, DoctorConfig, EnsureResult, EnvConfig, Environment, EnvironmentReviewer, Environments, Errors, FeatureResolverConfig, HolocronConfig, Issue, IssueSearchFilter, Issues, LabelDef, LifecycleResult, LifecycleSlot, LoadedConfig, LogConfig, Logs, MultiEntry, NormalizedAuthUser, Notifications, PagesConfig, ParseWebhookInput, ProviderApiError, ProviderIdentity, ProviderOptions, PullRequest, REQUIRED_CAPABILITIES, RawProviderEntry, RawProvidersConfig, RepoConfig, RepoProperties, RepoProtection, RepoRef, RepoSettings, type RequestOptions, ResolveTokenConfig, type ResolveTokenInput, ResolvedCapability, ResolvedHolocronConfig, ResolvedProviderEntry, ResolvedProvidersConfig, ResolvedTuple, type RestClient, type RestClientConfig, Ruleset, SecretScope, Secrets, SingleEntry, Source, StatusCategory, Storage, StorageBranch, StorybookDeployProject, TaskEntryConfig, TeamEntry, TeamPermission, TelemetryConfig, Tooling, ToolingDoctorReport, TrackerDoctorReport, TrackerUser, Vault, WebhookDashboardInfo, WebhookVerificationError, Wiki, WikiDnsRecord, WikiProvisionOpts, WikiProxyConfig, Workers, WorkflowWithConfig, compose, createFeatureResolver, createResolveToken, createRestClient, defineConfig, deleteToken, getToken, isMulti, listStoredProviders, loadConfig, resolveConfig, resolveEntry, resolvePluginPackage, setToken };
686
+ //#region src/commands/setup/derived-properties/derived-properties.type.d.ts
687
+ /**
688
+ * Derived custom-properties (#677). Unlike the existing 6 GitHub
689
+ * custom-properties fields (`lifecycle`, `open_source`, `runtime_environment`,
690
+ * `uses_external_packages`, `monorepo`, `branch_protection_level`) — which
691
+ * mirror what `holocron.config.ts` already states explicitly — these four are
692
+ * *derived*: signal that isn't an explicit config field today (framework
693
+ * choice, repo archetype, capability drift). See
694
+ * `.notes/tech-holocron-platform.spec.md` → "Custom-properties sync — field
695
+ * definitions (#677)" for the full design.
696
+ */
697
+ type HolocronProfile = "library" | "cli" | "plugin" | "template" | "app" | "docs" | "platform";
698
+ /** The `package.json` shape profile derivation reads — `@theholocron/pkg-utils`'s `PackageJson`, under the name Sentinel already imports. */
699
+ type PackageJsonLike = PackageJson;
700
+ interface DeriveProfileInput {
701
+ rootPackageJson: PackageJsonLike | null;
702
+ repoName: string;
703
+ isMonorepo: boolean;
704
+ /** `packages/*` package.json contents, monorepo repos only — used to find the primary published artifact. */
705
+ workspacePackageJsons: PackageJsonLike[];
706
+ }
707
+ //#endregion
708
+ //#region src/commands/setup/derived-properties/derived-properties.d.ts
709
+ /**
710
+ * Repo archetype, in priority order:
711
+ * 1. `*-template` repo name → `template` (independent of package shape).
712
+ * 2. Monorepo whose primary published artifact is a CLI (some workspace
713
+ * package has `bin`) → `platform` — matches `holocron` itself: the CLI is
714
+ * the deliverable, the plugin packages are supporting infrastructure for
715
+ * it, not separate products.
716
+ * 3. Monorepo with no CLI but at least one non-private workspace package →
717
+ * `library` — matches `clients`/`configs`/`utils`/`themes`/
718
+ * `observability`: a family of published packages, none of them a CLI.
719
+ * Checked *before* falling into the root-package branch below, because
720
+ * these repos' own root `package.json` is private and often carries
721
+ * `@theholocron/astro-config` for a docs site built from the monorepo
722
+ * root — without this check they'd wrongly resolve to `docs` off that
723
+ * root-level signal alone, when the docs site is a secondary concern of
724
+ * a library collection, not what the repo fundamentally is.
725
+ * 4. Single-package repo with `package.json#bin` → `cli`.
726
+ * 5. Docs-only site (astro/starlight present, root package private, no
727
+ * publishable exports) → `docs`.
728
+ * 6. Private, non-publishable, non-docs → `app`.
729
+ * 7. Otherwise, a single publishable package → `library`.
730
+ */
731
+ declare function deriveProfile(input: DeriveProfileInput): HolocronProfile;
732
+ /**
733
+ * Detected build/framework tooling — the literal "does this repo need
734
+ * next/vite/tsdown" signal `holocron.config.ts` has no field for today
735
+ * (framework choice isn't a config concept, unlike `providers`/`tasks`).
736
+ * Curated table, not exhaustive by design — add to `KNOWN_STACK_DEPS` as new
737
+ * frameworks show up rather than trying to detect anything on npm.
738
+ */
739
+ declare function deriveStack(pkg: PackageJsonLike | null): string[];
740
+ /** The provider capability keys actually wired in `providers: {}` — zero heuristics. */
741
+ declare function deriveCapabilities(providers: ResolvedProvidersConfig | undefined): string[];
742
+ declare function deriveCompliance(capabilities: readonly string[]): "compliant" | "non-compliant";
743
+ /**
744
+ * The Phase B refinement `deriveCompliance()`'s own doc comment names —
745
+ * *why* a repo is non-compliant, not just that it is. `[]` when compliant.
746
+ * Same `REQUIRED_BASELINE` `deriveCompliance()` checks against — one
747
+ * table, not two independently-maintained baselines.
748
+ */
749
+ declare function missingCapabilities(capabilities: readonly string[]): string[];
750
+ /**
751
+ * Reads each workspace package's actual `package.json` content (not just
752
+ * `readWorkspacePackages()`'s `{ slug, name, dir }` — `deriveProfile()`'s
753
+ * `platform` detection needs `bin`, which that helper doesn't carry).
754
+ * Missing/invalid files are skipped, matching `readWorkspacePackages()`'s
755
+ * own soft-fail behavior.
756
+ */
757
+ declare function readWorkspacePackageJsons(repoRoot: string, workspacePackages: readonly WorkspacePackage[]): Promise<PackageJsonLike[]>;
758
+ //#endregion
759
+ export { Analytics, type AppConfig, Auth, AuthDescription, AuthError, AuthEvent, AuthEventType, AuthIdentity, AuthUser, CARDINALITY, type Capability, type CapabilityConfigPackage, CapabilityImpls, CapabilityKey, Cardinality, CardinalityFor, type ChromaticProjectConfig, Ci, CiRun, CiRunFilter, CiRunStatus, type ComposedPreset, ConfigError, ConfigFileError, ConnectionStringOptions, CreateAuthUserInput, DeployFunctionConfig, DeployFunctionResult, DeployScriptConfig, DeployScriptResult, Deployment, DeploymentProject, DeploymentProjectSettings, DeploymentRecord, DeploymentTarget, DeploymentTrigger, type DeriveProfileInput, Dns, DnsRecord, DnsRecordRequest, DnsRecordType, type DocsConfig, type DoctorConfig, EnsureResult, type EnvConfig, Environment, EnvironmentReviewer, Environments, Errors, type EslintConfig, type FeatureResolverConfig, type HolocronConfig, type HolocronProfile, Issue, IssueSearchFilter, Issues, LabelDef, LifecycleResult, LifecycleSlot, type LoadedConfig, type LogConfig, Logs, Monitoring, MonitoringAssertion, MonitoringAssertionComparison, MonitoringAssertionSource, MonitoringCheck, MonitoringCheckInput, MonitoringHttpMethod, type MultiEntry, NormalizedAuthUser, Notifications, type PackageJsonLike, PagesConfig, ParseWebhookInput, ProviderApiError, ProviderIdentity, type ProviderOptions, PullRequest, REQUIRED_CAPABILITIES, type RawProviderEntry, type RawProvidersConfig, type RepoConfig, type RepoProperties, type RepoProtection, RepoRef, RepoSettings, type RequestOptions, type ResolveTokenConfig, type ResolveTokenInput, ResolvedCapability, type ResolvedHolocronConfig, type ResolvedProviderEntry, type ResolvedProvidersConfig, type ResolvedTuple, type RestClient, type RestClientConfig, Ruleset, SecretScope, Secrets, type SingleEntry, Source, StatusCategory, Storage, StorageBranch, type StorybookDeployProject, type TaskEntry, type TaskEntryConfig, TeamEntry, TeamPermission, type TelemetryConfig, Tooling, ToolingDoctorReport, TrackerDoctorReport, TrackerUser, Vault, type VerifyTokenFailure, type VerifyTokenResult, type VerifyTokenSuccess, WebhookDashboardInfo, WebhookVerificationError, Wiki, WikiProvisionOpts, WikiProxyConfig, Workers, type WorkflowWithConfig, compose, createFeatureResolver, createResolveToken, createRestClient, defineConfig, deleteToken, deriveCapabilities, deriveCompliance, deriveProfile, deriveStack, getToken, isMulti, listStoredProviders, loadConfig, missingCapabilities, readWorkspacePackageJsons, resolveConfig, resolveEntry, resolvePluginPackage, setToken };
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 { execFile } from "node:child_process";
6
- import { readFile } from "node:fs/promises";
7
5
  import { basename, dirname, join } from "node:path";
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
- createEnvLookup();
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,114 @@ function createFeatureResolver(config) {
113
115
  };
114
116
  }
115
117
  //#endregion
116
- //#region src/config/config.ts
118
+ //#region src/commands/setup/derived-properties/derived-properties.ts
119
+ /**
120
+ * Repo archetype, in priority order:
121
+ * 1. `*-template` repo name → `template` (independent of package shape).
122
+ * 2. Monorepo whose primary published artifact is a CLI (some workspace
123
+ * package has `bin`) → `platform` — matches `holocron` itself: the CLI is
124
+ * the deliverable, the plugin packages are supporting infrastructure for
125
+ * it, not separate products.
126
+ * 3. Monorepo with no CLI but at least one non-private workspace package →
127
+ * `library` — matches `clients`/`configs`/`utils`/`themes`/
128
+ * `observability`: a family of published packages, none of them a CLI.
129
+ * Checked *before* falling into the root-package branch below, because
130
+ * these repos' own root `package.json` is private and often carries
131
+ * `@theholocron/astro-config` for a docs site built from the monorepo
132
+ * root — without this check they'd wrongly resolve to `docs` off that
133
+ * root-level signal alone, when the docs site is a secondary concern of
134
+ * a library collection, not what the repo fundamentally is.
135
+ * 4. Single-package repo with `package.json#bin` → `cli`.
136
+ * 5. Docs-only site (astro/starlight present, root package private, no
137
+ * publishable exports) → `docs`.
138
+ * 6. Private, non-publishable, non-docs → `app`.
139
+ * 7. Otherwise, a single publishable package → `library`.
140
+ */
141
+ function deriveProfile(input) {
142
+ if (/-template$/.test(input.repoName)) return "template";
143
+ if (input.isMonorepo) {
144
+ if (input.workspacePackageJsons.some((pkg) => Boolean(pkg.bin))) return "platform";
145
+ if (input.workspacePackageJsons.some((pkg) => pkg.private !== true)) return "library";
146
+ }
147
+ const pkg = input.rootPackageJson;
148
+ if (pkg?.bin) return "cli";
149
+ const deps = {
150
+ ...pkg?.dependencies,
151
+ ...pkg?.devDependencies
152
+ };
153
+ const isDocsSite = Boolean(deps["@theholocron/astro-config"] || deps["astro"]);
154
+ if (pkg?.private && isDocsSite) return "docs";
155
+ if (pkg?.private) return "app";
156
+ return "library";
157
+ }
158
+ const KNOWN_STACK_DEPS = [
159
+ "next",
160
+ "vite",
161
+ "astro",
162
+ "tsdown",
163
+ "rollup",
164
+ "webpack",
165
+ "storybook",
166
+ "vitest",
167
+ "playwright",
168
+ "turbo"
169
+ ];
170
+ /**
171
+ * Detected build/framework tooling — the literal "does this repo need
172
+ * next/vite/tsdown" signal `holocron.config.ts` has no field for today
173
+ * (framework choice isn't a config concept, unlike `providers`/`tasks`).
174
+ * Curated table, not exhaustive by design — add to `KNOWN_STACK_DEPS` as new
175
+ * frameworks show up rather than trying to detect anything on npm.
176
+ */
177
+ function deriveStack(pkg) {
178
+ const deps = {
179
+ ...pkg?.dependencies,
180
+ ...pkg?.devDependencies
181
+ };
182
+ return KNOWN_STACK_DEPS.filter((name) => name in deps);
183
+ }
184
+ /** The provider capability keys actually wired in `providers: {}` — zero heuristics. */
185
+ function deriveCapabilities(providers) {
186
+ return Object.keys(providers ?? {}).sort();
187
+ }
188
+ /**
189
+ * `source` + `ci` are the minimal baseline every repo `holocron repo setup`
190
+ * touches wires — every `holocron.config.ts` in this org already satisfies
191
+ * this, so `non-compliant` here means drift (a provider manually removed
192
+ * after setup), not an unmet aspirational policy. Deliberately not a richer
193
+ * per-profile policy yet (e.g. "a `library` must have `deployment`") — that's
194
+ * a Phase B (GitHub App) refinement once it can post *why* on a check run.
195
+ */
196
+ const REQUIRED_BASELINE = ["source", "ci"];
197
+ function deriveCompliance(capabilities) {
198
+ return REQUIRED_BASELINE.every((key) => capabilities.includes(key)) ? "compliant" : "non-compliant";
199
+ }
200
+ /**
201
+ * The Phase B refinement `deriveCompliance()`'s own doc comment names —
202
+ * *why* a repo is non-compliant, not just that it is. `[]` when compliant.
203
+ * Same `REQUIRED_BASELINE` `deriveCompliance()` checks against — one
204
+ * table, not two independently-maintained baselines.
205
+ */
206
+ function missingCapabilities(capabilities) {
207
+ return REQUIRED_BASELINE.filter((key) => !capabilities.includes(key));
208
+ }
209
+ /**
210
+ * Reads each workspace package's actual `package.json` content (not just
211
+ * `readWorkspacePackages()`'s `{ slug, name, dir }` — `deriveProfile()`'s
212
+ * `platform` detection needs `bin`, which that helper doesn't carry).
213
+ * Missing/invalid files are skipped, matching `readWorkspacePackages()`'s
214
+ * own soft-fail behavior.
215
+ */
216
+ async function readWorkspacePackageJsons(repoRoot, workspacePackages) {
217
+ const results = [];
218
+ for (const { slug, dir = "packages" } of workspacePackages) {
219
+ const pkg = await readPackageJson(join(repoRoot, dir, slug));
220
+ if (pkg) results.push(pkg);
221
+ }
222
+ return results;
223
+ }
224
+ //#endregion
225
+ //#region src/config/config/config.ts
117
226
  var ConfigError = class extends Error {
118
227
  name = "ConfigError";
119
228
  };
@@ -217,11 +326,12 @@ function resolveConfig(raw) {
217
326
  docs,
218
327
  env: raw.env,
219
328
  log: raw.log,
220
- telemetry: raw.telemetry
329
+ telemetry: raw.telemetry,
330
+ eslint: raw.eslint
221
331
  };
222
332
  }
223
333
  //#endregion
224
- //#region src/config/compose.ts
334
+ //#region src/config/compose/compose.ts
225
335
  function taskName(e) {
226
336
  return typeof e === "string" ? e : e.name;
227
337
  }
@@ -309,12 +419,12 @@ function compose(...args) {
309
419
  };
310
420
  }
311
421
  //#endregion
312
- //#region src/config/define-config.ts
422
+ //#region src/config/define-config/define-config.ts
313
423
  function defineConfig(config) {
314
424
  return config;
315
425
  }
316
426
  //#endregion
317
- //#region src/config/load-config.ts
427
+ //#region src/config/load-config/load-config.ts
318
428
  /**
319
429
  * `holocron.config.{ts,js,mjs,cjs,json}` loader.
320
430
  *
@@ -326,34 +436,39 @@ function defineConfig(config) {
326
436
  * Probe order is TS-first (`.ts` → `.js` → `.mjs` → `.cjs` → `.json`) —
327
437
  * see ADR-0010 / issue #75 / #81.
328
438
  */
329
- const execFileAsync = promisify(execFile);
330
439
  /**
331
- * Read + parse + resolve `holocron.config.*` from the given directory.
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).
332
445
  * Throws {@link ConfigFileError} when nothing is found or a file cannot
333
- * be loaded, or `ConfigError` when the config is invalid.
446
+ * be loaded, or `ConfigError` when the config fails schema checks.
334
447
  */
335
448
  async function loadConfig(cwd) {
336
449
  const found = await loadConfigFile({
337
450
  cwd,
338
- name: "holocron"
451
+ name: "holocron",
452
+ walkUp: true
339
453
  });
340
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.`);
341
455
  return {
342
- resolved: resolveConfig(await deriveDefaults(dirname(found.filepath), found.config)),
456
+ resolved: resolveConfig(await deriveDefaults(found)),
343
457
  filepath: found.filepath
344
458
  };
345
459
  }
346
- async function deriveDefaults(configDir, raw) {
347
- const result = { ...raw };
460
+ async function deriveDefaults(found) {
461
+ const configDir = dirname(found.filepath);
462
+ const result = { ...found.config };
348
463
  if (!result.name) result.name = await readPackageJsonName(configDir) ?? basename(configDir);
349
464
  if (result.repo && !result.repo.name) {
350
- const repoName = await readGitRemote(configDir);
351
- if (repoName) result.repo = {
465
+ const remote = await readGitRemote(configDir);
466
+ if (remote?.host === "github.com") result.repo = {
352
467
  ...result.repo,
353
- name: repoName
468
+ name: remote.slug
354
469
  };
355
470
  }
356
- const manifest = await loadTasksConfig(configDir);
471
+ const manifest = await loadTasksConfig(configDir, { holocron: found });
357
472
  if (manifest.tasks) result.tasks = manifest.tasks;
358
473
  if (manifest.syncScripts !== void 0) result.syncScripts = manifest.syncScripts;
359
474
  if (manifest.holocronScript !== void 0) result.holocronScript = manifest.holocronScript;
@@ -362,31 +477,8 @@ async function deriveDefaults(configDir, raw) {
362
477
  return result;
363
478
  }
364
479
  async function readPackageJsonName(dir) {
365
- try {
366
- const content = await readFile(join(dir, "package.json"), "utf8");
367
- const pkg = JSON.parse(content);
368
- return typeof pkg.name === "string" ? pkg.name.replace(/^@[^/]+\//, "") : void 0;
369
- } catch {
370
- return;
371
- }
372
- }
373
- async function readGitRemote(dir) {
374
- try {
375
- const { stdout } = await execFileAsync("git", [
376
- "remote",
377
- "get-url",
378
- "origin"
379
- ], { cwd: dir });
380
- return parseGitRemoteUrl(stdout.trim());
381
- } catch {
382
- return;
383
- }
384
- }
385
- function parseGitRemoteUrl(url) {
386
- const httpsMatch = url.match(/github\.com\/([^/]+\/[^/]+?)(?:\.git)?$/);
387
- if (httpsMatch) return httpsMatch[1];
388
- const sshMatch = url.match(/github\.com:([^/]+\/[^/]+?)(?:\.git)?$/);
389
- if (sshMatch) return sshMatch[1];
480
+ const name = (await readPackageJson(dir))?.name;
481
+ return name === void 0 ? void 0 : name.replace(/^@[^/]+\//, "");
390
482
  }
391
483
  //#endregion
392
- export { AuthError, CARDINALITY, ConfigError, ConfigFileError, ProviderApiError, REQUIRED_CAPABILITIES, WebhookVerificationError, compose, createFeatureResolver, createResolveToken, createRestClient, defineConfig, deleteToken, getToken, isMulti, listStoredProviders, loadConfig, resolveConfig, resolveEntry, resolvePluginPackage, setToken };
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 };