@savvy-web/silk-effects 7.3.2 → 7.5.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/changesets/remark/plugins/maintenance-note.js +16 -2
- package/changesets/services/config-inspector.js +6 -1
- package/changesets/utils/version-files.js +9 -5
- package/index.d.ts +186 -29
- package/index.js +2 -1
- package/package.json +16 -16
- package/schemas/SavvyInstallSection.js +232 -0
- package/schemas/WorkspaceAnalysisSchemas.js +8 -2
|
@@ -1,6 +1,19 @@
|
|
|
1
1
|
import { getHeadingText, getVersionBlocks } from "../../utils/version-blocks.js";
|
|
2
|
+
import { toString } from "mdast-util-to-string";
|
|
2
3
|
|
|
3
4
|
//#region src/changesets/remark/plugins/maintenance-note.ts
|
|
5
|
+
/**
|
|
6
|
+
* Placeholder sentence `@changesets/apply-release-plan` (>= 8.1.0) emits as the
|
|
7
|
+
* body of a version block that would otherwise render as a bare heading. Older
|
|
8
|
+
* engine versions left such a block structurally empty.
|
|
9
|
+
*/
|
|
10
|
+
const ENGINE_PLACEHOLDER = "No changes in this release.";
|
|
11
|
+
/** True when the block's only content is the engine's empty-release placeholder. */
|
|
12
|
+
function isPlaceholderOnly(tree, block) {
|
|
13
|
+
if (block.endIndex - block.startIndex !== 1) return false;
|
|
14
|
+
const node = tree.children[block.startIndex];
|
|
15
|
+
return node.type === "paragraph" && toString(node).trim() === ENGINE_PLACEHOLDER;
|
|
16
|
+
}
|
|
4
17
|
function buildNoteChildren(reason) {
|
|
5
18
|
if (reason.kind === "unspecified" || reason.triggers.length === 0) return [{
|
|
6
19
|
type: "text",
|
|
@@ -31,7 +44,8 @@ const MaintenanceNotePlugin = (options) => {
|
|
|
31
44
|
return (tree) => {
|
|
32
45
|
const block = getVersionBlocks(tree).find((b) => getHeadingText(tree.children[b.headingIndex]) === options.version);
|
|
33
46
|
if (!block) return;
|
|
34
|
-
|
|
47
|
+
const placeholderOnly = isPlaceholderOnly(tree, block);
|
|
48
|
+
if (block.endIndex > block.startIndex && !placeholderOnly) return;
|
|
35
49
|
const heading = {
|
|
36
50
|
type: "heading",
|
|
37
51
|
depth: 3,
|
|
@@ -53,7 +67,7 @@ const MaintenanceNotePlugin = (options) => {
|
|
|
53
67
|
}]
|
|
54
68
|
}]
|
|
55
69
|
};
|
|
56
|
-
tree.children.splice(block.startIndex, 0, heading, list);
|
|
70
|
+
tree.children.splice(block.startIndex, placeholderOnly ? 1 : 0, heading, list);
|
|
57
71
|
};
|
|
58
72
|
};
|
|
59
73
|
|
|
@@ -52,7 +52,12 @@ const ResolvedVersionFileSchema = Schema.Struct({
|
|
|
52
52
|
const ResolvedPackageScopeSchema = Schema.Struct({
|
|
53
53
|
name: Schema.String,
|
|
54
54
|
workspaceDir: Schema.String,
|
|
55
|
-
|
|
55
|
+
/**
|
|
56
|
+
* The package's declared version, absent when its manifest carries none — legal for a private
|
|
57
|
+
* package and the ordinary shape for a private monorepo root. A scope with no version has
|
|
58
|
+
* nothing to stamp into its `versionFiles` targets, so `VersionFiles.applyScopes` skips it.
|
|
59
|
+
*/
|
|
60
|
+
version: Schema.optional(Schema.String),
|
|
56
61
|
additionalScopes: Schema.Array(Schema.String),
|
|
57
62
|
additionalScopeFiles: Schema.Array(Schema.String),
|
|
58
63
|
versionFiles: Schema.Array(ResolvedVersionFileSchema)
|
|
@@ -368,11 +368,15 @@ var VersionFiles = class VersionFiles {
|
|
|
368
368
|
static processResolvedVersionFiles(scopes, dryRun = false) {
|
|
369
369
|
return Effect.gen(function* () {
|
|
370
370
|
const updates = [];
|
|
371
|
-
for (const scope of scopes)
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
371
|
+
for (const scope of scopes) {
|
|
372
|
+
if (scope.version === void 0) continue;
|
|
373
|
+
const version = scope.version;
|
|
374
|
+
for (const vf of scope.versionFiles) {
|
|
375
|
+
const jsonPaths = vf.paths.length > 0 ? vf.paths : ["$.version"];
|
|
376
|
+
for (const filePath of vf.matchedFiles) {
|
|
377
|
+
const result = yield* VersionFiles.applyOne(filePath, jsonPaths, version, dryRun);
|
|
378
|
+
if (result) updates.push(result);
|
|
379
|
+
}
|
|
376
380
|
}
|
|
377
381
|
}
|
|
378
382
|
return updates;
|
package/index.d.ts
CHANGED
|
@@ -2805,7 +2805,7 @@ declare const ChangesetConfigError_base: new <A extends Record<string, any> = {}
|
|
|
2805
2805
|
* @since 0.1.0
|
|
2806
2806
|
* @public
|
|
2807
2807
|
*/
|
|
2808
|
-
declare class ChangesetConfigError extends ChangesetConfigError_base<{
|
|
2808
|
+
export declare class ChangesetConfigError extends ChangesetConfigError_base<{
|
|
2809
2809
|
readonly path: string;
|
|
2810
2810
|
readonly reason: string;
|
|
2811
2811
|
}> {
|
|
@@ -2932,7 +2932,7 @@ declare const ChangesetConfigReader_base: Context.ServiceClass<ChangesetConfigRe
|
|
|
2932
2932
|
* @since 0.1.0
|
|
2933
2933
|
* @public
|
|
2934
2934
|
*/
|
|
2935
|
-
declare class ChangesetConfigReader extends ChangesetConfigReader_base {
|
|
2935
|
+
export declare class ChangesetConfigReader extends ChangesetConfigReader_base {
|
|
2936
2936
|
/**
|
|
2937
2937
|
* Production implementation of {@link ChangesetConfigReader}.
|
|
2938
2938
|
*
|
|
@@ -2959,7 +2959,12 @@ type ResolvedVersionFile = typeof ResolvedVersionFileSchema.Type;
|
|
|
2959
2959
|
declare const ResolvedPackageScopeSchema: Schema.Struct<{
|
|
2960
2960
|
readonly name: Schema.String;
|
|
2961
2961
|
readonly workspaceDir: Schema.String;
|
|
2962
|
-
|
|
2962
|
+
/**
|
|
2963
|
+
* The package's declared version, absent when its manifest carries none — legal for a private
|
|
2964
|
+
* package and the ordinary shape for a private monorepo root. A scope with no version has
|
|
2965
|
+
* nothing to stamp into its `versionFiles` targets, so `VersionFiles.applyScopes` skips it.
|
|
2966
|
+
*/
|
|
2967
|
+
readonly version: Schema.optional<Schema.String>;
|
|
2963
2968
|
readonly additionalScopes: Schema.$Array<Schema.String>;
|
|
2964
2969
|
readonly additionalScopeFiles: Schema.$Array<Schema.String>;
|
|
2965
2970
|
readonly versionFiles: Schema.$Array<Schema.Struct<{
|
|
@@ -2981,7 +2986,12 @@ declare const InspectedConfigSchema: Schema.Struct<{
|
|
|
2981
2986
|
readonly packages: Schema.$Array<Schema.Struct<{
|
|
2982
2987
|
readonly name: Schema.String;
|
|
2983
2988
|
readonly workspaceDir: Schema.String;
|
|
2984
|
-
|
|
2989
|
+
/**
|
|
2990
|
+
* The package's declared version, absent when its manifest carries none — legal for a private
|
|
2991
|
+
* package and the ordinary shape for a private monorepo root. A scope with no version has
|
|
2992
|
+
* nothing to stamp into its `versionFiles` targets, so `VersionFiles.applyScopes` skips it.
|
|
2993
|
+
*/
|
|
2994
|
+
readonly version: Schema.optional<Schema.String>;
|
|
2985
2995
|
readonly additionalScopes: Schema.$Array<Schema.String>;
|
|
2986
2996
|
readonly additionalScopeFiles: Schema.$Array<Schema.String>;
|
|
2987
2997
|
readonly versionFiles: Schema.$Array<Schema.Struct<{
|
|
@@ -3670,7 +3680,7 @@ declare const ChangesetConfig_base: Context.ServiceClass<ChangesetConfig, "@savv
|
|
|
3670
3680
|
* @since 0.4.0
|
|
3671
3681
|
* @public
|
|
3672
3682
|
*/
|
|
3673
|
-
declare class ChangesetConfig extends ChangesetConfig_base {
|
|
3683
|
+
export declare class ChangesetConfig extends ChangesetConfig_base {
|
|
3674
3684
|
/**
|
|
3675
3685
|
* The one ignore matcher: exact name match, or `@scope/*` wildcard.
|
|
3676
3686
|
*
|
|
@@ -6801,7 +6811,7 @@ declare const BiomeSyncError_base: new <A extends Record<string, any> = {}>(args
|
|
|
6801
6811
|
* @since 0.1.0
|
|
6802
6812
|
* @public
|
|
6803
6813
|
*/
|
|
6804
|
-
declare class BiomeSyncError extends BiomeSyncError_base<{
|
|
6814
|
+
export declare class BiomeSyncError extends BiomeSyncError_base<{
|
|
6805
6815
|
readonly path: string;
|
|
6806
6816
|
readonly reason: string;
|
|
6807
6817
|
}> {
|
|
@@ -6823,7 +6833,7 @@ declare const ConfigNotFoundError_base: new <A extends Record<string, any> = {}>
|
|
|
6823
6833
|
* @since 0.1.0
|
|
6824
6834
|
* @public
|
|
6825
6835
|
*/
|
|
6826
|
-
declare class ConfigNotFoundError extends ConfigNotFoundError_base<{
|
|
6836
|
+
export declare class ConfigNotFoundError extends ConfigNotFoundError_base<{
|
|
6827
6837
|
readonly name: string;
|
|
6828
6838
|
readonly searchedPaths: ReadonlyArray<string>;
|
|
6829
6839
|
}> {
|
|
@@ -6853,7 +6863,7 @@ declare const PublishTargetBindingError_base: new <A extends Record<string, any>
|
|
|
6853
6863
|
* @since 3.1.0
|
|
6854
6864
|
* @public
|
|
6855
6865
|
*/
|
|
6856
|
-
declare class PublishTargetBindingError extends PublishTargetBindingError_base<{
|
|
6866
|
+
export declare class PublishTargetBindingError extends PublishTargetBindingError_base<{
|
|
6857
6867
|
/** The package whose targets were being resolved. */
|
|
6858
6868
|
readonly pkg: string;
|
|
6859
6869
|
/** The directory detection selected, relative to the package root. */
|
|
@@ -6879,7 +6889,7 @@ declare const WorkspaceAnalysisError_base: new <A extends Record<string, any> =
|
|
|
6879
6889
|
* @since 0.2.0
|
|
6880
6890
|
* @public
|
|
6881
6891
|
*/
|
|
6882
|
-
declare class WorkspaceAnalysisError extends WorkspaceAnalysisError_base<{
|
|
6892
|
+
export declare class WorkspaceAnalysisError extends WorkspaceAnalysisError_base<{
|
|
6883
6893
|
readonly root: string;
|
|
6884
6894
|
readonly reason: string;
|
|
6885
6895
|
}> {
|
|
@@ -9832,6 +9842,148 @@ declare const ConfigDiscoveryOptions: Schema.Struct<{
|
|
|
9832
9842
|
*/
|
|
9833
9843
|
type ConfigDiscoveryOptions = typeof ConfigDiscoveryOptions.Type;
|
|
9834
9844
|
//#endregion
|
|
9845
|
+
//#region src/schemas/SavvyInstallSection.d.ts
|
|
9846
|
+
/**
|
|
9847
|
+
* The hooks {@link savvyInstallDeps} can be generated for.
|
|
9848
|
+
*
|
|
9849
|
+
* @remarks
|
|
9850
|
+
* Both are needed, and `post-merge` is the one that matters most in practice:
|
|
9851
|
+
* a fast-forward `git pull` — the batch-alignment case this exists for — fires
|
|
9852
|
+
* `post-merge` and never `post-checkout`. They are separate spellings rather
|
|
9853
|
+
* than one argument-sniffing block because the two hooks disagree on both
|
|
9854
|
+
* halves of the decision: `post-checkout` is handed `<prev> <new> <flag>` and
|
|
9855
|
+
* must ignore a file checkout, while `post-merge` is handed only a squash flag
|
|
9856
|
+
* and has to recover its own range from `ORIG_HEAD`.
|
|
9857
|
+
*
|
|
9858
|
+
* @since 7.5.0
|
|
9859
|
+
* @public
|
|
9860
|
+
*/
|
|
9861
|
+
type SavvyInstallHook = "post-checkout" | "post-merge";
|
|
9862
|
+
/**
|
|
9863
|
+
* Section identity for the dependency auto-install block.
|
|
9864
|
+
*
|
|
9865
|
+
* `toolName` is `"savvy-install"`; pair with {@link savvyInstallDeps}.
|
|
9866
|
+
*
|
|
9867
|
+
* @since 7.5.0
|
|
9868
|
+
* @public
|
|
9869
|
+
*/
|
|
9870
|
+
export declare const SavvyInstallSection: SectionId;
|
|
9871
|
+
/**
|
|
9872
|
+
* Dependency auto-install shared across Silk Suite hook files.
|
|
9873
|
+
*
|
|
9874
|
+
* @remarks
|
|
9875
|
+
* Brings `node_modules` back in line after a branch switch or a pull, so a batch
|
|
9876
|
+
* of repos pulled to align their dependencies does not each need a manual
|
|
9877
|
+
* install. Installs with lifecycle scripts skipped — `--ignore-scripts`, or
|
|
9878
|
+
* `--mode=skip-build` for Yarn Berry, which dropped the former — because the goal
|
|
9879
|
+
* is to get the dependency tree on disk, not to run a full postinstall.
|
|
9880
|
+
*
|
|
9881
|
+
* **That flag has a cost, and one shape of repo cannot pay it.** Where a package
|
|
9882
|
+
* publishes through a built link directory — `publishConfig.directory` with
|
|
9883
|
+
* `linkDirectory: true`, which is how this monorepo wires `dist/dev/pkg` — the
|
|
9884
|
+
* workspace resolves its own dependencies through a directory that a `prepare`
|
|
9885
|
+
* script has to build, and skipping scripts yields a populated `node_modules`
|
|
9886
|
+
* pointing at nothing.
|
|
9887
|
+
*
|
|
9888
|
+
* Those repos ask for a full install through the LOCAL git config key
|
|
9889
|
+
* `savvy.installLifecycleScripts`, which `savvy init` sets when it finds the
|
|
9890
|
+
* shape. The decision deliberately does NOT read the checked-out tree. Doing so
|
|
9891
|
+
* failed in both directions at once: a branch that merely declared the shape
|
|
9892
|
+
* could turn lifecycle scripts back on just by being checked out, making
|
|
9893
|
+
* `git checkout` of an untrusted revision a code-execution path; and the `jq`
|
|
9894
|
+
* the scan needed is absent on stock macOS and Ubuntu, where the missing answer
|
|
9895
|
+
* silently skipped scripts in precisely the repos that cannot survive it.
|
|
9896
|
+
* `.git/config` is neither checked out nor parsed with `jq`, so it has neither
|
|
9897
|
+
* failure mode.
|
|
9898
|
+
*
|
|
9899
|
+
* The package managers gate dependency scripts themselves on top of this —
|
|
9900
|
+
* pnpm's `strictDepBuilds` with an `allowBuilds` allowlist being the case in
|
|
9901
|
+
* point — but workspace and root lifecycle scripts still run, which is why the
|
|
9902
|
+
* opt-in is local rather than inferred. With the flag on, the hook says on the
|
|
9903
|
+
* way out that scripts were skipped rather than leaving it to be discovered.
|
|
9904
|
+
*
|
|
9905
|
+
* Deliberately self-contained, like `savvyToolchainCheck`: its homes carry
|
|
9906
|
+
* `SavvyHooksSection` but no `SavvyBaseSection`, so it defines its own root, CI
|
|
9907
|
+
* and package-manager lookups rather than depending on `ROOT`, `in_ci` or `PM`.
|
|
9908
|
+
*
|
|
9909
|
+
* Four guards keep it from firing on the many checkouts that are not dependency
|
|
9910
|
+
* events, each a silent no-op:
|
|
9911
|
+
*
|
|
9912
|
+
* - CI, where the runtime action owns installation by construction.
|
|
9913
|
+
* - `SAVVY_SKIP_INSTALL`, the escape hatch for a bisect or a scripted sweep that
|
|
9914
|
+
* does not want an install between steps.
|
|
9915
|
+
* - `post-checkout` only: a branch-flag of `0`, which is `git checkout -- <file>`
|
|
9916
|
+
* and not a move between commits.
|
|
9917
|
+
* - **The gate that makes this affordable:** nothing dependency-related actually
|
|
9918
|
+
* changed across the move. Without it every branch switch would pay for a full
|
|
9919
|
+
* install. A missing `node_modules` overrides it, since there is nothing to be
|
|
9920
|
+
* stale.
|
|
9921
|
+
*
|
|
9922
|
+
* A fresh clone is not among the cases it handles, and cannot be: husky sets
|
|
9923
|
+
* `core.hooksPath` from its own `prepare` script, so until the first manual
|
|
9924
|
+
* install has run there is no hook installed to fire.
|
|
9925
|
+
*
|
|
9926
|
+
* The install's exit status is swallowed and its output goes to stderr. Git
|
|
9927
|
+
* ignores what `post-checkout` and `post-merge` return, so a failure here must
|
|
9928
|
+
* not look like a failed checkout; the hint names the escape hatch instead.
|
|
9929
|
+
*
|
|
9930
|
+
* Every probe that can legitimately fail — no `ORIG_HEAD` to compare against, an
|
|
9931
|
+
* unresolvable range — is neutralised with `|| true` rather than left to its own
|
|
9932
|
+
* status. These blocks are co-owned and consumer content can sit below them, so
|
|
9933
|
+
* under a hook running `set -e` a bare failing substitution would abort the whole
|
|
9934
|
+
* file and take those later sections with it.
|
|
9935
|
+
*
|
|
9936
|
+
* @param hook - Which hook the block is being generated for; decides the
|
|
9937
|
+
* argument guard and how the comparison range is recovered.
|
|
9938
|
+
* @returns The install shell, with no surrounding markers or trailing newline.
|
|
9939
|
+
*
|
|
9940
|
+
* @since 7.5.0
|
|
9941
|
+
* @public
|
|
9942
|
+
*/
|
|
9943
|
+
export declare function savvyInstallDeps(hook: SavvyInstallHook): string;
|
|
9944
|
+
/**
|
|
9945
|
+
* The local git config key that authorizes lifecycle scripts during a hook install.
|
|
9946
|
+
*
|
|
9947
|
+
* @remarks
|
|
9948
|
+
* Local scope only. It lives in `.git/config`, which is never checked out, so no
|
|
9949
|
+
* incoming revision can set it — that is the whole point of reading the decision
|
|
9950
|
+
* from here rather than from a manifest in the tree.
|
|
9951
|
+
*
|
|
9952
|
+
* @since 7.5.0
|
|
9953
|
+
* @public
|
|
9954
|
+
*/
|
|
9955
|
+
export declare const LIFECYCLE_SCRIPTS_CONFIG_KEY = "savvy.installLifecycleScripts";
|
|
9956
|
+
/**
|
|
9957
|
+
* Whether `manifest` publishes through a built link directory.
|
|
9958
|
+
*
|
|
9959
|
+
* @remarks
|
|
9960
|
+
* `publishConfig.directory` with `linkDirectory: true` means consumers of this
|
|
9961
|
+
* package resolve it through a directory that a `prepare` script has to produce,
|
|
9962
|
+
* so an install that skips lifecycle scripts leaves the link pointing at nothing.
|
|
9963
|
+
* A workspace containing any such package is one whose owner probably wants
|
|
9964
|
+
* {@link LIFECYCLE_SCRIPTS_CONFIG_KEY} set.
|
|
9965
|
+
*
|
|
9966
|
+
* Reporting the shape is deliberately separate from acting on it: this answers
|
|
9967
|
+
* "does this repo need scripts", and a human still decides whether hook-time
|
|
9968
|
+
* installs may run them.
|
|
9969
|
+
*
|
|
9970
|
+
* @param manifest - A parsed `package.json`; any non-object reads as `false`.
|
|
9971
|
+
*
|
|
9972
|
+
* @since 7.5.0
|
|
9973
|
+
* @public
|
|
9974
|
+
*/
|
|
9975
|
+
export declare function publishesBuiltLinkDirectory(manifest: unknown): boolean;
|
|
9976
|
+
/**
|
|
9977
|
+
* Build the dependency auto-install block for `hook`.
|
|
9978
|
+
*
|
|
9979
|
+
* @param hook - Which hook the section is destined for.
|
|
9980
|
+
* @returns A shell `Section` (`commentStyle: hash`) keyed `SAVVY-INSTALL`.
|
|
9981
|
+
*
|
|
9982
|
+
* @since 7.5.0
|
|
9983
|
+
* @public
|
|
9984
|
+
*/
|
|
9985
|
+
export declare function savvyInstallBlock(hook: SavvyInstallHook): Section;
|
|
9986
|
+
//#endregion
|
|
9835
9987
|
//#region src/schemas/SavvySections.d.ts
|
|
9836
9988
|
/**
|
|
9837
9989
|
* Section identity for the shared package-manager preamble.
|
|
@@ -9846,7 +9998,7 @@ type ConfigDiscoveryOptions = typeof ConfigDiscoveryOptions.Type;
|
|
|
9846
9998
|
* @since 0.5.0
|
|
9847
9999
|
* @public
|
|
9848
10000
|
*/
|
|
9849
|
-
declare const SavvyBaseSection: SectionId;
|
|
10001
|
+
export declare const SavvyBaseSection: SectionId;
|
|
9850
10002
|
/**
|
|
9851
10003
|
* Section identity for the shared repo-hygiene block.
|
|
9852
10004
|
*
|
|
@@ -9855,7 +10007,7 @@ declare const SavvyBaseSection: SectionId;
|
|
|
9855
10007
|
* @since 0.5.0
|
|
9856
10008
|
* @public
|
|
9857
10009
|
*/
|
|
9858
|
-
declare const SavvyHooksSection: SectionId;
|
|
10010
|
+
export declare const SavvyHooksSection: SectionId;
|
|
9859
10011
|
/**
|
|
9860
10012
|
* Package-manager detection preamble shared across Silk Suite hook files.
|
|
9861
10013
|
*
|
|
@@ -9870,7 +10022,7 @@ declare const SavvyHooksSection: SectionId;
|
|
|
9870
10022
|
* @since 0.5.0
|
|
9871
10023
|
* @public
|
|
9872
10024
|
*/
|
|
9873
|
-
declare function savvyBasePreamble(): string;
|
|
10025
|
+
export declare function savvyBasePreamble(): string;
|
|
9874
10026
|
/**
|
|
9875
10027
|
* Repo-hygiene block shared across Silk Suite hook files.
|
|
9876
10028
|
*
|
|
@@ -9883,7 +10035,7 @@ declare function savvyBasePreamble(): string;
|
|
|
9883
10035
|
* @since 0.5.0
|
|
9884
10036
|
* @public
|
|
9885
10037
|
*/
|
|
9886
|
-
declare function savvyHooksHygiene(): string;
|
|
10038
|
+
export declare function savvyHooksHygiene(): string;
|
|
9887
10039
|
/**
|
|
9888
10040
|
* Build a consumer's one-line tool section so every consumer calls the shared base
|
|
9889
10041
|
* helpers identically.
|
|
@@ -9912,7 +10064,7 @@ declare function savvyHooksHygiene(): string;
|
|
|
9912
10064
|
* @since 0.5.0
|
|
9913
10065
|
* @public
|
|
9914
10066
|
*/
|
|
9915
|
-
declare function savvyToolSection(toolName: string, command: string): Section;
|
|
10067
|
+
export declare function savvyToolSection(toolName: string, command: string): Section;
|
|
9916
10068
|
/**
|
|
9917
10069
|
* Section identity for the package-manager toolchain drift check.
|
|
9918
10070
|
*
|
|
@@ -9921,7 +10073,7 @@ declare function savvyToolSection(toolName: string, command: string): Section;
|
|
|
9921
10073
|
* @since 7.3.0
|
|
9922
10074
|
* @public
|
|
9923
10075
|
*/
|
|
9924
|
-
declare const SavvyToolchainSection: SectionId;
|
|
10076
|
+
export declare const SavvyToolchainSection: SectionId;
|
|
9925
10077
|
/**
|
|
9926
10078
|
* Package-manager drift check shared across Silk Suite hook files.
|
|
9927
10079
|
*
|
|
@@ -9949,7 +10101,7 @@ declare const SavvyToolchainSection: SectionId;
|
|
|
9949
10101
|
* @since 7.3.0
|
|
9950
10102
|
* @public
|
|
9951
10103
|
*/
|
|
9952
|
-
declare function savvyToolchainCheck(): string;
|
|
10104
|
+
export declare function savvyToolchainCheck(): string;
|
|
9953
10105
|
//#endregion
|
|
9954
10106
|
//#region src/schemas/WorkspaceAnalysisSchemas.d.ts
|
|
9955
10107
|
declare const SilkPublishConfig_base: Schema.Class<SilkPublishConfig, Schema.Struct<{
|
|
@@ -9979,11 +10131,11 @@ declare const SilkPublishConfig_base: Schema.Class<SilkPublishConfig, Schema.Str
|
|
|
9979
10131
|
* @since 0.2.0
|
|
9980
10132
|
* @public
|
|
9981
10133
|
*/
|
|
9982
|
-
declare class SilkPublishConfig extends SilkPublishConfig_base {}
|
|
10134
|
+
export declare class SilkPublishConfig extends SilkPublishConfig_base {}
|
|
9983
10135
|
declare const AnalyzedWorkspace_base: Schema.Class<AnalyzedWorkspace, Schema.TaggedStruct<"AnalyzedWorkspace", {
|
|
9984
10136
|
readonly name: Schema.String;
|
|
9985
10137
|
readonly version: Schema.Struct<{
|
|
9986
|
-
readonly current: Schema.String
|
|
10138
|
+
readonly current: Schema.optional<Schema.String>;
|
|
9987
10139
|
}>;
|
|
9988
10140
|
readonly path: Schema.String;
|
|
9989
10141
|
readonly root: Schema.Boolean;
|
|
@@ -10003,7 +10155,7 @@ declare const AnalyzedWorkspace_base: Schema.Class<AnalyzedWorkspace, Schema.Tag
|
|
|
10003
10155
|
* @since 0.2.0
|
|
10004
10156
|
* @public
|
|
10005
10157
|
*/
|
|
10006
|
-
declare class AnalyzedWorkspace extends AnalyzedWorkspace_base {
|
|
10158
|
+
export declare class AnalyzedWorkspace extends AnalyzedWorkspace_base {
|
|
10007
10159
|
get isRoot(): boolean;
|
|
10008
10160
|
get isPublishable(): boolean;
|
|
10009
10161
|
get isReleasable(): boolean;
|
|
@@ -10085,7 +10237,7 @@ declare const WorkspaceAnalysis_base: Schema.Class<WorkspaceAnalysis, Schema.Tag
|
|
|
10085
10237
|
* @since 0.2.0
|
|
10086
10238
|
* @public
|
|
10087
10239
|
*/
|
|
10088
|
-
declare class WorkspaceAnalysis extends WorkspaceAnalysis_base {
|
|
10240
|
+
export declare class WorkspaceAnalysis extends WorkspaceAnalysis_base {
|
|
10089
10241
|
findWorkspace(name: string): Option.Option<AnalyzedWorkspace>;
|
|
10090
10242
|
get rootWorkspace(): Option.Option<AnalyzedWorkspace>;
|
|
10091
10243
|
get publishableWorkspaces(): ReadonlyArray<AnalyzedWorkspace>;
|
|
@@ -10111,7 +10263,7 @@ declare class WorkspaceAnalysis extends WorkspaceAnalysis_base {
|
|
|
10111
10263
|
* @since 0.1.0
|
|
10112
10264
|
* @public
|
|
10113
10265
|
*/
|
|
10114
|
-
declare function extractSemver(version: string): string;
|
|
10266
|
+
export declare function extractSemver(version: string): string;
|
|
10115
10267
|
/**
|
|
10116
10268
|
* Build the expected Biome JSON schema URL for a given version.
|
|
10117
10269
|
*
|
|
@@ -10121,7 +10273,7 @@ declare function extractSemver(version: string): string;
|
|
|
10121
10273
|
* @since 0.1.0
|
|
10122
10274
|
* @public
|
|
10123
10275
|
*/
|
|
10124
|
-
declare function buildSchemaUrl(version: string): string;
|
|
10276
|
+
export declare function buildSchemaUrl(version: string): string;
|
|
10125
10277
|
/**
|
|
10126
10278
|
* The {@link BiomeSchemaSync} service shape.
|
|
10127
10279
|
*
|
|
@@ -10182,7 +10334,7 @@ declare const BiomeSchemaSync_base: Context.ServiceClass<BiomeSchemaSync, "@savv
|
|
|
10182
10334
|
* @since 0.1.0
|
|
10183
10335
|
* @public
|
|
10184
10336
|
*/
|
|
10185
|
-
declare class BiomeSchemaSync extends BiomeSchemaSync_base {
|
|
10337
|
+
export declare class BiomeSchemaSync extends BiomeSchemaSync_base {
|
|
10186
10338
|
/**
|
|
10187
10339
|
* Production implementation of {@link BiomeSchemaSync}.
|
|
10188
10340
|
*
|
|
@@ -10258,7 +10410,7 @@ declare const ConfigDiscovery_base: Context.ServiceClass<ConfigDiscovery, "@savv
|
|
|
10258
10410
|
* @since 0.1.0
|
|
10259
10411
|
* @public
|
|
10260
10412
|
*/
|
|
10261
|
-
declare class ConfigDiscovery extends ConfigDiscovery_base {
|
|
10413
|
+
export declare class ConfigDiscovery extends ConfigDiscovery_base {
|
|
10262
10414
|
/**
|
|
10263
10415
|
* Production implementation of {@link ConfigDiscovery}.
|
|
10264
10416
|
*
|
|
@@ -10366,7 +10518,12 @@ interface RawPackageJson {
|
|
|
10366
10518
|
*/
|
|
10367
10519
|
interface PublishablePackage {
|
|
10368
10520
|
readonly name: string;
|
|
10369
|
-
|
|
10521
|
+
/**
|
|
10522
|
+
* The declared version, absent when the manifest carries none. Publishability is decided by
|
|
10523
|
+
* `publishConfig`, not by `version`, so a version-less package can still resolve targets —
|
|
10524
|
+
* it simply has no version to publish under until one is declared.
|
|
10525
|
+
*/
|
|
10526
|
+
readonly version: string | undefined;
|
|
10370
10527
|
readonly path: string;
|
|
10371
10528
|
readonly targetCount: number;
|
|
10372
10529
|
}
|
|
@@ -10381,7 +10538,7 @@ interface PublishablePackage {
|
|
|
10381
10538
|
* @since 0.4.0
|
|
10382
10539
|
* @public
|
|
10383
10540
|
*/
|
|
10384
|
-
declare class SilkPublishability {
|
|
10541
|
+
export declare class SilkPublishability {
|
|
10385
10542
|
/**
|
|
10386
10543
|
* Apply silk publishability rules to a raw `package.json` and the bundler's resolved
|
|
10387
10544
|
* target binding. Targets-first precedence:
|
|
@@ -10464,7 +10621,7 @@ declare class SilkPublishability {
|
|
|
10464
10621
|
* @since 1.0.0
|
|
10465
10622
|
* @public
|
|
10466
10623
|
*/
|
|
10467
|
-
declare const readTargetsBinding: (fs: FileSystem.FileSystem, pkgPath: string) => Effect.Effect<TargetsBinding | null>;
|
|
10624
|
+
export declare const readTargetsBinding: (fs: FileSystem.FileSystem, pkgPath: string) => Effect.Effect<TargetsBinding | null>;
|
|
10468
10625
|
//#endregion
|
|
10469
10626
|
//#region src/services/SilkWorkspaceAnalyzer.d.ts
|
|
10470
10627
|
/**
|
|
@@ -10515,7 +10672,7 @@ declare const SilkWorkspaceAnalyzer_base: Context.ServiceClass<SilkWorkspaceAnal
|
|
|
10515
10672
|
* @since 0.2.0
|
|
10516
10673
|
* @public
|
|
10517
10674
|
*/
|
|
10518
|
-
declare class SilkWorkspaceAnalyzer extends SilkWorkspaceAnalyzer_base {
|
|
10675
|
+
export declare class SilkWorkspaceAnalyzer extends SilkWorkspaceAnalyzer_base {
|
|
10519
10676
|
/**
|
|
10520
10677
|
* Production implementation of {@link SilkWorkspaceAnalyzer}.
|
|
10521
10678
|
*
|
|
@@ -10885,5 +11042,5 @@ declare namespace index_d_exports$5 {
|
|
|
10885
11042
|
export { AffectedResult, AffectedResultType, CacheDiagnosis, CacheDiagnosisType, DryRunParseError, GlobalHashSummary, GraphNode, MissExplanation, NotATurboRepoError, PackageCacheStatus, TaskGraphResult, TaskGraphResultType, TurboCache, TurboDigest, TurboDryRun, TurboDryRunType, TurboDryTask, TurboDryTaskType, TurboEnvVars, TurboError, TurboExecError, TurboGlobalCacheInputs, TurboInspector, TurboInspectorShape, TurboNotInstalledError };
|
|
10886
11043
|
}
|
|
10887
11044
|
//#endregion
|
|
10888
|
-
export {
|
|
11045
|
+
export { type BiomeSchemaSyncShape, type BiomeSyncOptions, type BiomeSyncResult, type ChangesetConfigFile, type ChangesetConfigReaderShape, type ChangesetConfigShape, type ChangesetMode, index_d_exports as Changesets, index_d_exports$1 as Commitlint, type CommitlintPlugin, type CommitlintUserConfig, type ConfigDiscoveryOptions, type ConfigDiscoveryShape, type ConfigLocation, type ConfigSource, index_d_exports$2 as Lint, index_d_exports$3 as PrBody, type PromptConfig, type PromptSettings, type PublishablePackage, type RawPackageJson, type RawPublishConfig, type RawPublishTargets, type RawTargetObject, type RawTargetValue, index_d_exports$4 as Repos, type RuleApplicability, type RuleConfigTuple, type RuleSeverity, type RulesConfig, type SavvyInstallHook, type SilkChangesetConfigFile, type SilkWorkspaceAnalyzerShape, type TargetBinding, type TargetGroupBinding, type TargetsBinding, index_d_exports$5 as Turbo };
|
|
10889
11046
|
//# sourceMappingURL=index.d.ts.map
|
package/index.js
CHANGED
|
@@ -12,10 +12,11 @@ import { WorkspaceAnalysisError } from "./errors/WorkspaceAnalysisError.js";
|
|
|
12
12
|
import { lint_exports } from "./lint/index.js";
|
|
13
13
|
import { pr_body_exports } from "./pr-body/index.js";
|
|
14
14
|
import { repos_exports } from "./repos/index.js";
|
|
15
|
+
import { LIFECYCLE_SCRIPTS_CONFIG_KEY, SavvyInstallSection, publishesBuiltLinkDirectory, savvyInstallBlock, savvyInstallDeps } from "./schemas/SavvyInstallSection.js";
|
|
15
16
|
import { AnalyzedWorkspace, SilkPublishConfig, WorkspaceAnalysis } from "./schemas/WorkspaceAnalysisSchemas.js";
|
|
16
17
|
import { BiomeSchemaSync, buildSchemaUrl, extractSemver } from "./services/BiomeSchemaSync.js";
|
|
17
18
|
import { ConfigDiscovery } from "./services/ConfigDiscovery.js";
|
|
18
19
|
import { SilkWorkspaceAnalyzer } from "./services/SilkWorkspaceAnalyzer.js";
|
|
19
20
|
import { turbo_exports } from "./turbo/index.js";
|
|
20
21
|
|
|
21
|
-
export { AnalyzedWorkspace, BiomeSchemaSync, BiomeSyncError, ChangesetConfig, ChangesetConfigError, ChangesetConfigReader, changesets_exports as Changesets, commitlint_exports as Commitlint, ConfigDiscovery, ConfigNotFoundError, lint_exports as Lint, pr_body_exports as PrBody, PublishTargetBindingError, repos_exports as Repos, SavvyBaseSection, SavvyHooksSection, SavvyToolchainSection, SilkPublishConfig, SilkPublishability, SilkWorkspaceAnalyzer, turbo_exports as Turbo, WorkspaceAnalysis, WorkspaceAnalysisError, buildSchemaUrl, extractSemver, readTargetsBinding, savvyBasePreamble, savvyHooksHygiene, savvyToolSection, savvyToolchainCheck };
|
|
22
|
+
export { AnalyzedWorkspace, BiomeSchemaSync, BiomeSyncError, ChangesetConfig, ChangesetConfigError, ChangesetConfigReader, changesets_exports as Changesets, commitlint_exports as Commitlint, ConfigDiscovery, ConfigNotFoundError, LIFECYCLE_SCRIPTS_CONFIG_KEY, lint_exports as Lint, pr_body_exports as PrBody, PublishTargetBindingError, repos_exports as Repos, SavvyBaseSection, SavvyHooksSection, SavvyInstallSection, SavvyToolchainSection, SilkPublishConfig, SilkPublishability, SilkWorkspaceAnalyzer, turbo_exports as Turbo, WorkspaceAnalysis, WorkspaceAnalysisError, buildSchemaUrl, extractSemver, publishesBuiltLinkDirectory, readTargetsBinding, savvyBasePreamble, savvyHooksHygiene, savvyInstallBlock, savvyInstallDeps, savvyToolSection, savvyToolchainCheck };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@savvy-web/silk-effects",
|
|
3
|
-
"version": "7.
|
|
3
|
+
"version": "7.5.0",
|
|
4
4
|
"private": false,
|
|
5
5
|
"description": "Shared Effect library for Silk Suite conventions",
|
|
6
6
|
"homepage": "https://github.com/savvy-web/systems/tree/main/packages/silk-effects",
|
|
@@ -29,19 +29,19 @@
|
|
|
29
29
|
"./package.json": "./package.json"
|
|
30
30
|
},
|
|
31
31
|
"dependencies": {
|
|
32
|
-
"@changesets/apply-release-plan": "^8.
|
|
32
|
+
"@changesets/apply-release-plan": "^8.1.0",
|
|
33
33
|
"@changesets/changelog-git": "^1.0.0",
|
|
34
34
|
"@changesets/config": "^4.0.0",
|
|
35
|
-
"@changesets/get-github-info": "^1.0.
|
|
36
|
-
"@changesets/get-release-plan": "^5.0.
|
|
37
|
-
"@effected/github-references": "^0.
|
|
38
|
-
"@effected/glob": "^0.
|
|
39
|
-
"@effected/jsonc": "^0.
|
|
40
|
-
"@effected/markdown": "^0.
|
|
41
|
-
"@effected/package-json": "^0.
|
|
42
|
-
"@effected/templates": "^0.
|
|
43
|
-
"@effected/walker": "^0.
|
|
44
|
-
"@effected/yaml": "^0.
|
|
35
|
+
"@changesets/get-github-info": "^1.0.1",
|
|
36
|
+
"@changesets/get-release-plan": "^5.0.1",
|
|
37
|
+
"@effected/github-references": "^0.2.0",
|
|
38
|
+
"@effected/glob": "^0.5.0",
|
|
39
|
+
"@effected/jsonc": "^0.9.0",
|
|
40
|
+
"@effected/markdown": "^0.9.0",
|
|
41
|
+
"@effected/package-json": "^0.14.0",
|
|
42
|
+
"@effected/templates": "^0.5.0",
|
|
43
|
+
"@effected/walker": "^0.6.0",
|
|
44
|
+
"@effected/yaml": "^0.13.0",
|
|
45
45
|
"@manypkg/get-packages": "^3.1.0",
|
|
46
46
|
"mdast-util-heading-range": "^4.0.0",
|
|
47
47
|
"mdast-util-to-string": "^4.0.0",
|
|
@@ -54,9 +54,9 @@
|
|
|
54
54
|
"unist-util-visit": "^5.1.0"
|
|
55
55
|
},
|
|
56
56
|
"peerDependencies": {
|
|
57
|
-
"@effected/commands": "^0.
|
|
58
|
-
"@effected/git": "^0.
|
|
59
|
-
"@effected/workspaces": "^0.
|
|
60
|
-
"effect": "4.0.0-rc.
|
|
57
|
+
"@effected/commands": "^0.6.0",
|
|
58
|
+
"@effected/git": "^0.11.0",
|
|
59
|
+
"@effected/workspaces": "^0.20.0",
|
|
60
|
+
"effect": "4.0.0-rc.112"
|
|
61
61
|
}
|
|
62
62
|
}
|
|
@@ -0,0 +1,232 @@
|
|
|
1
|
+
import { CommentStyle, SectionId } from "@effected/templates";
|
|
2
|
+
|
|
3
|
+
//#region src/schemas/SavvyInstallSection.ts
|
|
4
|
+
/**
|
|
5
|
+
* Section identity for the dependency auto-install block.
|
|
6
|
+
*
|
|
7
|
+
* `toolName` is `"savvy-install"`; pair with {@link savvyInstallDeps}.
|
|
8
|
+
*
|
|
9
|
+
* @since 7.5.0
|
|
10
|
+
* @public
|
|
11
|
+
*/
|
|
12
|
+
const SavvyInstallSection = SectionId.make({
|
|
13
|
+
key: "SAVVY-INSTALL",
|
|
14
|
+
commentStyle: CommentStyle.hash
|
|
15
|
+
});
|
|
16
|
+
/**
|
|
17
|
+
* Pathspecs whose change across a checkout or merge means `node_modules` is stale.
|
|
18
|
+
*
|
|
19
|
+
* @remarks
|
|
20
|
+
* Git's default pathspec globbing does not stop a wildcard at a slash, so the
|
|
21
|
+
* one nested-manifest entry below covers every workspace manifest at any depth
|
|
22
|
+
* without needing a recursive spelling. Manifests are listed alongside lockfiles
|
|
23
|
+
* because a dependency edit that has not been installed yet moves the manifest
|
|
24
|
+
* first and the lockfile not at all.
|
|
25
|
+
*/
|
|
26
|
+
const DEPENDENCY_PATHS = [
|
|
27
|
+
"package.json",
|
|
28
|
+
"*/package.json",
|
|
29
|
+
"pnpm-lock.yaml",
|
|
30
|
+
"pnpm-workspace.yaml",
|
|
31
|
+
"package-lock.json",
|
|
32
|
+
"npm-shrinkwrap.json",
|
|
33
|
+
"yarn.lock",
|
|
34
|
+
"bun.lock",
|
|
35
|
+
"bun.lockb"
|
|
36
|
+
].map((path) => `'${path}'`).join(" ");
|
|
37
|
+
/**
|
|
38
|
+
* Dependency auto-install shared across Silk Suite hook files.
|
|
39
|
+
*
|
|
40
|
+
* @remarks
|
|
41
|
+
* Brings `node_modules` back in line after a branch switch or a pull, so a batch
|
|
42
|
+
* of repos pulled to align their dependencies does not each need a manual
|
|
43
|
+
* install. Installs with lifecycle scripts skipped — `--ignore-scripts`, or
|
|
44
|
+
* `--mode=skip-build` for Yarn Berry, which dropped the former — because the goal
|
|
45
|
+
* is to get the dependency tree on disk, not to run a full postinstall.
|
|
46
|
+
*
|
|
47
|
+
* **That flag has a cost, and one shape of repo cannot pay it.** Where a package
|
|
48
|
+
* publishes through a built link directory — `publishConfig.directory` with
|
|
49
|
+
* `linkDirectory: true`, which is how this monorepo wires `dist/dev/pkg` — the
|
|
50
|
+
* workspace resolves its own dependencies through a directory that a `prepare`
|
|
51
|
+
* script has to build, and skipping scripts yields a populated `node_modules`
|
|
52
|
+
* pointing at nothing.
|
|
53
|
+
*
|
|
54
|
+
* Those repos ask for a full install through the LOCAL git config key
|
|
55
|
+
* `savvy.installLifecycleScripts`, which `savvy init` sets when it finds the
|
|
56
|
+
* shape. The decision deliberately does NOT read the checked-out tree. Doing so
|
|
57
|
+
* failed in both directions at once: a branch that merely declared the shape
|
|
58
|
+
* could turn lifecycle scripts back on just by being checked out, making
|
|
59
|
+
* `git checkout` of an untrusted revision a code-execution path; and the `jq`
|
|
60
|
+
* the scan needed is absent on stock macOS and Ubuntu, where the missing answer
|
|
61
|
+
* silently skipped scripts in precisely the repos that cannot survive it.
|
|
62
|
+
* `.git/config` is neither checked out nor parsed with `jq`, so it has neither
|
|
63
|
+
* failure mode.
|
|
64
|
+
*
|
|
65
|
+
* The package managers gate dependency scripts themselves on top of this —
|
|
66
|
+
* pnpm's `strictDepBuilds` with an `allowBuilds` allowlist being the case in
|
|
67
|
+
* point — but workspace and root lifecycle scripts still run, which is why the
|
|
68
|
+
* opt-in is local rather than inferred. With the flag on, the hook says on the
|
|
69
|
+
* way out that scripts were skipped rather than leaving it to be discovered.
|
|
70
|
+
*
|
|
71
|
+
* Deliberately self-contained, like `savvyToolchainCheck`: its homes carry
|
|
72
|
+
* `SavvyHooksSection` but no `SavvyBaseSection`, so it defines its own root, CI
|
|
73
|
+
* and package-manager lookups rather than depending on `ROOT`, `in_ci` or `PM`.
|
|
74
|
+
*
|
|
75
|
+
* Four guards keep it from firing on the many checkouts that are not dependency
|
|
76
|
+
* events, each a silent no-op:
|
|
77
|
+
*
|
|
78
|
+
* - CI, where the runtime action owns installation by construction.
|
|
79
|
+
* - `SAVVY_SKIP_INSTALL`, the escape hatch for a bisect or a scripted sweep that
|
|
80
|
+
* does not want an install between steps.
|
|
81
|
+
* - `post-checkout` only: a branch-flag of `0`, which is `git checkout -- <file>`
|
|
82
|
+
* and not a move between commits.
|
|
83
|
+
* - **The gate that makes this affordable:** nothing dependency-related actually
|
|
84
|
+
* changed across the move. Without it every branch switch would pay for a full
|
|
85
|
+
* install. A missing `node_modules` overrides it, since there is nothing to be
|
|
86
|
+
* stale.
|
|
87
|
+
*
|
|
88
|
+
* A fresh clone is not among the cases it handles, and cannot be: husky sets
|
|
89
|
+
* `core.hooksPath` from its own `prepare` script, so until the first manual
|
|
90
|
+
* install has run there is no hook installed to fire.
|
|
91
|
+
*
|
|
92
|
+
* The install's exit status is swallowed and its output goes to stderr. Git
|
|
93
|
+
* ignores what `post-checkout` and `post-merge` return, so a failure here must
|
|
94
|
+
* not look like a failed checkout; the hint names the escape hatch instead.
|
|
95
|
+
*
|
|
96
|
+
* Every probe that can legitimately fail — no `ORIG_HEAD` to compare against, an
|
|
97
|
+
* unresolvable range — is neutralised with `|| true` rather than left to its own
|
|
98
|
+
* status. These blocks are co-owned and consumer content can sit below them, so
|
|
99
|
+
* under a hook running `set -e` a bare failing substitution would abort the whole
|
|
100
|
+
* file and take those later sections with it.
|
|
101
|
+
*
|
|
102
|
+
* @param hook - Which hook the block is being generated for; decides the
|
|
103
|
+
* argument guard and how the comparison range is recovered.
|
|
104
|
+
* @returns The install shell, with no surrounding markers or trailing newline.
|
|
105
|
+
*
|
|
106
|
+
* @since 7.5.0
|
|
107
|
+
* @public
|
|
108
|
+
*/
|
|
109
|
+
function savvyInstallDeps(hook) {
|
|
110
|
+
const skip = `! { [ -n "$CI" ] || [ -n "$GITHUB_ACTIONS" ] || [ -n "$SAVVY_SKIP_INSTALL" ]; }`;
|
|
111
|
+
return `if ${hook === "post-checkout" ? `${skip} && [ "$3" = "1" ]` : skip}; then
|
|
112
|
+
install_root=$(git rev-parse --show-toplevel 2>/dev/null) || true
|
|
113
|
+
${hook === "post-checkout" ? ` install_from="$1"
|
|
114
|
+
install_to="$2"` : ` install_from=$(git rev-parse --verify --quiet ORIG_HEAD 2>/dev/null) || true
|
|
115
|
+
install_to="HEAD"`}
|
|
116
|
+
install_pm=""
|
|
117
|
+
if [ -n "$install_root" ] && [ -f "$install_root/package.json" ]; then
|
|
118
|
+
if command -v jq >/dev/null 2>&1; then
|
|
119
|
+
install_pm=$(jq -r '.packageManager // empty' "$install_root/package.json" 2>/dev/null | cut -d'@' -f1)
|
|
120
|
+
fi
|
|
121
|
+
if [ -z "$install_pm" ]; then
|
|
122
|
+
if [ -f "$install_root/pnpm-lock.yaml" ]; then install_pm="pnpm"
|
|
123
|
+
elif [ -f "$install_root/yarn.lock" ]; then install_pm="yarn"
|
|
124
|
+
elif [ -f "$install_root/bun.lock" ] || [ -f "$install_root/bun.lockb" ]; then install_pm="bun"
|
|
125
|
+
else install_pm="npm"; fi
|
|
126
|
+
fi
|
|
127
|
+
fi
|
|
128
|
+
# packageManager comes from the checked-out revision, so it names an executable
|
|
129
|
+
# the tree controls. 'command -v' proves a binary exists, not that it is a
|
|
130
|
+
# package manager, so the name is checked against the supported four first.
|
|
131
|
+
case "$install_pm" in
|
|
132
|
+
npm|pnpm|yarn|bun) ;;
|
|
133
|
+
*) install_pm="" ;;
|
|
134
|
+
esac
|
|
135
|
+
# Nothing to bring up to date unless a manifest or lockfile actually moved.
|
|
136
|
+
# A missing node_modules skips the diff outright: there is no tree to be stale.
|
|
137
|
+
install_stale=""
|
|
138
|
+
if [ -n "$install_pm" ]; then
|
|
139
|
+
if [ ! -d "$install_root/node_modules" ]; then
|
|
140
|
+
install_stale=1
|
|
141
|
+
elif [ -n "$install_from" ] && [ -n "$install_to" ]; then
|
|
142
|
+
install_stale=$(git diff --name-only "$install_from" "$install_to" -- ${DEPENDENCY_PATHS} 2>/dev/null | head -n 1) || true
|
|
143
|
+
fi
|
|
144
|
+
fi
|
|
145
|
+
if [ -n "$install_stale" ] && command -v "$install_pm" >/dev/null 2>&1; then
|
|
146
|
+
# Whether lifecycle scripts run is a LOCAL decision, read from .git/config,
|
|
147
|
+
# which no checkout can rewrite. Default off. 'savvy init' turns it on for a
|
|
148
|
+
# workspace that publishes through built link directories, where the links
|
|
149
|
+
# point at directories a prepare script has to produce.
|
|
150
|
+
install_scripts=$(git -C "$install_root" config --bool --get savvy.installLifecycleScripts 2>/dev/null) || true
|
|
151
|
+
if [ "$install_scripts" = "true" ]; then
|
|
152
|
+
install_flag=""
|
|
153
|
+
else
|
|
154
|
+
# Berry dropped --ignore-scripts for the install mode; Classic never knew the
|
|
155
|
+
# mode. An unreadable major reads as Berry, the likelier of the two today.
|
|
156
|
+
install_flag="--ignore-scripts"
|
|
157
|
+
if [ "$install_pm" = "yarn" ]; then
|
|
158
|
+
case "$(yarn --version 2>/dev/null | cut -d. -f1)" in
|
|
159
|
+
1) ;;
|
|
160
|
+
*) install_flag="--mode=skip-build" ;;
|
|
161
|
+
esac
|
|
162
|
+
fi
|
|
163
|
+
fi
|
|
164
|
+
# ':+' so a full install announces itself as "pnpm install", not "pnpm install ".
|
|
165
|
+
printf '↻ dependencies changed, running %s install%s\\n' "$install_pm" "\${install_flag:+ $install_flag}" >&2
|
|
166
|
+
# Unquoted on purpose: empty must expand to NO argument rather than an empty
|
|
167
|
+
# one. Safe because every value is a static flag literal from this generator.
|
|
168
|
+
if ( cd "$install_root" && "$install_pm" install $install_flag ) >&2; then
|
|
169
|
+
if [ -n "$install_flag" ]; then
|
|
170
|
+
printf ' Lifecycle scripts were skipped. Run a full install if you need build outputs.\\n' >&2
|
|
171
|
+
fi
|
|
172
|
+
else
|
|
173
|
+
printf '⚠ %s install failed; run it yourself to see why.\\n' "$install_pm" >&2
|
|
174
|
+
printf ' Set SAVVY_SKIP_INSTALL=1 to stop this hook from trying.\\n' >&2
|
|
175
|
+
fi
|
|
176
|
+
fi
|
|
177
|
+
unset install_root install_from install_to install_pm install_stale install_scripts install_flag
|
|
178
|
+
fi`;
|
|
179
|
+
}
|
|
180
|
+
/**
|
|
181
|
+
* The local git config key that authorizes lifecycle scripts during a hook install.
|
|
182
|
+
*
|
|
183
|
+
* @remarks
|
|
184
|
+
* Local scope only. It lives in `.git/config`, which is never checked out, so no
|
|
185
|
+
* incoming revision can set it — that is the whole point of reading the decision
|
|
186
|
+
* from here rather than from a manifest in the tree.
|
|
187
|
+
*
|
|
188
|
+
* @since 7.5.0
|
|
189
|
+
* @public
|
|
190
|
+
*/
|
|
191
|
+
const LIFECYCLE_SCRIPTS_CONFIG_KEY = "savvy.installLifecycleScripts";
|
|
192
|
+
/**
|
|
193
|
+
* Whether `manifest` publishes through a built link directory.
|
|
194
|
+
*
|
|
195
|
+
* @remarks
|
|
196
|
+
* `publishConfig.directory` with `linkDirectory: true` means consumers of this
|
|
197
|
+
* package resolve it through a directory that a `prepare` script has to produce,
|
|
198
|
+
* so an install that skips lifecycle scripts leaves the link pointing at nothing.
|
|
199
|
+
* A workspace containing any such package is one whose owner probably wants
|
|
200
|
+
* {@link LIFECYCLE_SCRIPTS_CONFIG_KEY} set.
|
|
201
|
+
*
|
|
202
|
+
* Reporting the shape is deliberately separate from acting on it: this answers
|
|
203
|
+
* "does this repo need scripts", and a human still decides whether hook-time
|
|
204
|
+
* installs may run them.
|
|
205
|
+
*
|
|
206
|
+
* @param manifest - A parsed `package.json`; any non-object reads as `false`.
|
|
207
|
+
*
|
|
208
|
+
* @since 7.5.0
|
|
209
|
+
* @public
|
|
210
|
+
*/
|
|
211
|
+
function publishesBuiltLinkDirectory(manifest) {
|
|
212
|
+
if (typeof manifest !== "object" || manifest === null) return false;
|
|
213
|
+
const { publishConfig } = manifest;
|
|
214
|
+
if (typeof publishConfig !== "object" || publishConfig === null) return false;
|
|
215
|
+
const { directory, linkDirectory } = publishConfig;
|
|
216
|
+
return typeof directory === "string" && directory.length > 0 && linkDirectory === true;
|
|
217
|
+
}
|
|
218
|
+
/**
|
|
219
|
+
* Build the dependency auto-install block for `hook`.
|
|
220
|
+
*
|
|
221
|
+
* @param hook - Which hook the section is destined for.
|
|
222
|
+
* @returns A shell `Section` (`commentStyle: hash`) keyed `SAVVY-INSTALL`.
|
|
223
|
+
*
|
|
224
|
+
* @since 7.5.0
|
|
225
|
+
* @public
|
|
226
|
+
*/
|
|
227
|
+
function savvyInstallBlock(hook) {
|
|
228
|
+
return SavvyInstallSection.section(savvyInstallDeps(hook));
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
//#endregion
|
|
232
|
+
export { LIFECYCLE_SCRIPTS_CONFIG_KEY, SavvyInstallSection, publishesBuiltLinkDirectory, savvyInstallBlock, savvyInstallDeps };
|
|
@@ -45,7 +45,13 @@ const KNOWN_REGISTRIES = {
|
|
|
45
45
|
* carries (binding-driven, placeholder, or access-branch fallback).
|
|
46
46
|
*/
|
|
47
47
|
const sameRegistry = (a, b) => trimTrailingSlashes(a) === trimTrailingSlashes(b);
|
|
48
|
-
|
|
48
|
+
/**
|
|
49
|
+
* The package's declared version. `current` is absent for a member whose manifest carries no
|
|
50
|
+
* `version` — legal for a private package and the ordinary shape for a private monorepo root,
|
|
51
|
+
* which `@effected/workspaces` discovers as a member rather than rejecting (its `missingVersion`
|
|
52
|
+
* failure kind was retired in 0.19.0). Such a package has no version to bump, tag or stamp.
|
|
53
|
+
*/
|
|
54
|
+
const WorkspaceVersion = Schema.Struct({ current: Schema.optional(Schema.String) });
|
|
49
55
|
/**
|
|
50
56
|
* A fully analyzed workspace with publish targets, versioning status,
|
|
51
57
|
* and release group membership.
|
|
@@ -101,7 +107,7 @@ var AnalyzedWorkspace = class AnalyzedWorkspace extends Schema.TaggedClass()("An
|
|
|
101
107
|
return Hash.optimize(Hash.combine(Hash.hash(this.name), Hash.hash(this.path)));
|
|
102
108
|
}
|
|
103
109
|
toString() {
|
|
104
|
-
return `${this.name}@${this.version.current}`;
|
|
110
|
+
return this.version.current === void 0 ? this.name : `${this.name}@${this.version.current}`;
|
|
105
111
|
}
|
|
106
112
|
toJSON() {
|
|
107
113
|
return {
|