@savvy-web/silk-effects 7.4.0 → 7.5.1
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/index.d.ts +167 -25
- package/index.js +2 -1
- package/package.json +16 -16
- package/schemas/SavvyInstallSection.js +232 -0
|
@@ -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
|
|
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
|
*
|
|
@@ -3680,7 +3680,7 @@ declare const ChangesetConfig_base: Context.ServiceClass<ChangesetConfig, "@savv
|
|
|
3680
3680
|
* @since 0.4.0
|
|
3681
3681
|
* @public
|
|
3682
3682
|
*/
|
|
3683
|
-
declare class ChangesetConfig extends ChangesetConfig_base {
|
|
3683
|
+
export declare class ChangesetConfig extends ChangesetConfig_base {
|
|
3684
3684
|
/**
|
|
3685
3685
|
* The one ignore matcher: exact name match, or `@scope/*` wildcard.
|
|
3686
3686
|
*
|
|
@@ -6811,7 +6811,7 @@ declare const BiomeSyncError_base: new <A extends Record<string, any> = {}>(args
|
|
|
6811
6811
|
* @since 0.1.0
|
|
6812
6812
|
* @public
|
|
6813
6813
|
*/
|
|
6814
|
-
declare class BiomeSyncError extends BiomeSyncError_base<{
|
|
6814
|
+
export declare class BiomeSyncError extends BiomeSyncError_base<{
|
|
6815
6815
|
readonly path: string;
|
|
6816
6816
|
readonly reason: string;
|
|
6817
6817
|
}> {
|
|
@@ -6833,7 +6833,7 @@ declare const ConfigNotFoundError_base: new <A extends Record<string, any> = {}>
|
|
|
6833
6833
|
* @since 0.1.0
|
|
6834
6834
|
* @public
|
|
6835
6835
|
*/
|
|
6836
|
-
declare class ConfigNotFoundError extends ConfigNotFoundError_base<{
|
|
6836
|
+
export declare class ConfigNotFoundError extends ConfigNotFoundError_base<{
|
|
6837
6837
|
readonly name: string;
|
|
6838
6838
|
readonly searchedPaths: ReadonlyArray<string>;
|
|
6839
6839
|
}> {
|
|
@@ -6863,7 +6863,7 @@ declare const PublishTargetBindingError_base: new <A extends Record<string, any>
|
|
|
6863
6863
|
* @since 3.1.0
|
|
6864
6864
|
* @public
|
|
6865
6865
|
*/
|
|
6866
|
-
declare class PublishTargetBindingError extends PublishTargetBindingError_base<{
|
|
6866
|
+
export declare class PublishTargetBindingError extends PublishTargetBindingError_base<{
|
|
6867
6867
|
/** The package whose targets were being resolved. */
|
|
6868
6868
|
readonly pkg: string;
|
|
6869
6869
|
/** The directory detection selected, relative to the package root. */
|
|
@@ -6889,7 +6889,7 @@ declare const WorkspaceAnalysisError_base: new <A extends Record<string, any> =
|
|
|
6889
6889
|
* @since 0.2.0
|
|
6890
6890
|
* @public
|
|
6891
6891
|
*/
|
|
6892
|
-
declare class WorkspaceAnalysisError extends WorkspaceAnalysisError_base<{
|
|
6892
|
+
export declare class WorkspaceAnalysisError extends WorkspaceAnalysisError_base<{
|
|
6893
6893
|
readonly root: string;
|
|
6894
6894
|
readonly reason: string;
|
|
6895
6895
|
}> {
|
|
@@ -9842,6 +9842,148 @@ declare const ConfigDiscoveryOptions: Schema.Struct<{
|
|
|
9842
9842
|
*/
|
|
9843
9843
|
type ConfigDiscoveryOptions = typeof ConfigDiscoveryOptions.Type;
|
|
9844
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
|
|
9845
9987
|
//#region src/schemas/SavvySections.d.ts
|
|
9846
9988
|
/**
|
|
9847
9989
|
* Section identity for the shared package-manager preamble.
|
|
@@ -9856,7 +9998,7 @@ type ConfigDiscoveryOptions = typeof ConfigDiscoveryOptions.Type;
|
|
|
9856
9998
|
* @since 0.5.0
|
|
9857
9999
|
* @public
|
|
9858
10000
|
*/
|
|
9859
|
-
declare const SavvyBaseSection: SectionId;
|
|
10001
|
+
export declare const SavvyBaseSection: SectionId;
|
|
9860
10002
|
/**
|
|
9861
10003
|
* Section identity for the shared repo-hygiene block.
|
|
9862
10004
|
*
|
|
@@ -9865,7 +10007,7 @@ declare const SavvyBaseSection: SectionId;
|
|
|
9865
10007
|
* @since 0.5.0
|
|
9866
10008
|
* @public
|
|
9867
10009
|
*/
|
|
9868
|
-
declare const SavvyHooksSection: SectionId;
|
|
10010
|
+
export declare const SavvyHooksSection: SectionId;
|
|
9869
10011
|
/**
|
|
9870
10012
|
* Package-manager detection preamble shared across Silk Suite hook files.
|
|
9871
10013
|
*
|
|
@@ -9880,7 +10022,7 @@ declare const SavvyHooksSection: SectionId;
|
|
|
9880
10022
|
* @since 0.5.0
|
|
9881
10023
|
* @public
|
|
9882
10024
|
*/
|
|
9883
|
-
declare function savvyBasePreamble(): string;
|
|
10025
|
+
export declare function savvyBasePreamble(): string;
|
|
9884
10026
|
/**
|
|
9885
10027
|
* Repo-hygiene block shared across Silk Suite hook files.
|
|
9886
10028
|
*
|
|
@@ -9893,7 +10035,7 @@ declare function savvyBasePreamble(): string;
|
|
|
9893
10035
|
* @since 0.5.0
|
|
9894
10036
|
* @public
|
|
9895
10037
|
*/
|
|
9896
|
-
declare function savvyHooksHygiene(): string;
|
|
10038
|
+
export declare function savvyHooksHygiene(): string;
|
|
9897
10039
|
/**
|
|
9898
10040
|
* Build a consumer's one-line tool section so every consumer calls the shared base
|
|
9899
10041
|
* helpers identically.
|
|
@@ -9922,7 +10064,7 @@ declare function savvyHooksHygiene(): string;
|
|
|
9922
10064
|
* @since 0.5.0
|
|
9923
10065
|
* @public
|
|
9924
10066
|
*/
|
|
9925
|
-
declare function savvyToolSection(toolName: string, command: string): Section;
|
|
10067
|
+
export declare function savvyToolSection(toolName: string, command: string): Section;
|
|
9926
10068
|
/**
|
|
9927
10069
|
* Section identity for the package-manager toolchain drift check.
|
|
9928
10070
|
*
|
|
@@ -9931,7 +10073,7 @@ declare function savvyToolSection(toolName: string, command: string): Section;
|
|
|
9931
10073
|
* @since 7.3.0
|
|
9932
10074
|
* @public
|
|
9933
10075
|
*/
|
|
9934
|
-
declare const SavvyToolchainSection: SectionId;
|
|
10076
|
+
export declare const SavvyToolchainSection: SectionId;
|
|
9935
10077
|
/**
|
|
9936
10078
|
* Package-manager drift check shared across Silk Suite hook files.
|
|
9937
10079
|
*
|
|
@@ -9959,7 +10101,7 @@ declare const SavvyToolchainSection: SectionId;
|
|
|
9959
10101
|
* @since 7.3.0
|
|
9960
10102
|
* @public
|
|
9961
10103
|
*/
|
|
9962
|
-
declare function savvyToolchainCheck(): string;
|
|
10104
|
+
export declare function savvyToolchainCheck(): string;
|
|
9963
10105
|
//#endregion
|
|
9964
10106
|
//#region src/schemas/WorkspaceAnalysisSchemas.d.ts
|
|
9965
10107
|
declare const SilkPublishConfig_base: Schema.Class<SilkPublishConfig, Schema.Struct<{
|
|
@@ -9989,7 +10131,7 @@ declare const SilkPublishConfig_base: Schema.Class<SilkPublishConfig, Schema.Str
|
|
|
9989
10131
|
* @since 0.2.0
|
|
9990
10132
|
* @public
|
|
9991
10133
|
*/
|
|
9992
|
-
declare class SilkPublishConfig extends SilkPublishConfig_base {}
|
|
10134
|
+
export declare class SilkPublishConfig extends SilkPublishConfig_base {}
|
|
9993
10135
|
declare const AnalyzedWorkspace_base: Schema.Class<AnalyzedWorkspace, Schema.TaggedStruct<"AnalyzedWorkspace", {
|
|
9994
10136
|
readonly name: Schema.String;
|
|
9995
10137
|
readonly version: Schema.Struct<{
|
|
@@ -10013,7 +10155,7 @@ declare const AnalyzedWorkspace_base: Schema.Class<AnalyzedWorkspace, Schema.Tag
|
|
|
10013
10155
|
* @since 0.2.0
|
|
10014
10156
|
* @public
|
|
10015
10157
|
*/
|
|
10016
|
-
declare class AnalyzedWorkspace extends AnalyzedWorkspace_base {
|
|
10158
|
+
export declare class AnalyzedWorkspace extends AnalyzedWorkspace_base {
|
|
10017
10159
|
get isRoot(): boolean;
|
|
10018
10160
|
get isPublishable(): boolean;
|
|
10019
10161
|
get isReleasable(): boolean;
|
|
@@ -10095,7 +10237,7 @@ declare const WorkspaceAnalysis_base: Schema.Class<WorkspaceAnalysis, Schema.Tag
|
|
|
10095
10237
|
* @since 0.2.0
|
|
10096
10238
|
* @public
|
|
10097
10239
|
*/
|
|
10098
|
-
declare class WorkspaceAnalysis extends WorkspaceAnalysis_base {
|
|
10240
|
+
export declare class WorkspaceAnalysis extends WorkspaceAnalysis_base {
|
|
10099
10241
|
findWorkspace(name: string): Option.Option<AnalyzedWorkspace>;
|
|
10100
10242
|
get rootWorkspace(): Option.Option<AnalyzedWorkspace>;
|
|
10101
10243
|
get publishableWorkspaces(): ReadonlyArray<AnalyzedWorkspace>;
|
|
@@ -10121,7 +10263,7 @@ declare class WorkspaceAnalysis extends WorkspaceAnalysis_base {
|
|
|
10121
10263
|
* @since 0.1.0
|
|
10122
10264
|
* @public
|
|
10123
10265
|
*/
|
|
10124
|
-
declare function extractSemver(version: string): string;
|
|
10266
|
+
export declare function extractSemver(version: string): string;
|
|
10125
10267
|
/**
|
|
10126
10268
|
* Build the expected Biome JSON schema URL for a given version.
|
|
10127
10269
|
*
|
|
@@ -10131,7 +10273,7 @@ declare function extractSemver(version: string): string;
|
|
|
10131
10273
|
* @since 0.1.0
|
|
10132
10274
|
* @public
|
|
10133
10275
|
*/
|
|
10134
|
-
declare function buildSchemaUrl(version: string): string;
|
|
10276
|
+
export declare function buildSchemaUrl(version: string): string;
|
|
10135
10277
|
/**
|
|
10136
10278
|
* The {@link BiomeSchemaSync} service shape.
|
|
10137
10279
|
*
|
|
@@ -10192,7 +10334,7 @@ declare const BiomeSchemaSync_base: Context.ServiceClass<BiomeSchemaSync, "@savv
|
|
|
10192
10334
|
* @since 0.1.0
|
|
10193
10335
|
* @public
|
|
10194
10336
|
*/
|
|
10195
|
-
declare class BiomeSchemaSync extends BiomeSchemaSync_base {
|
|
10337
|
+
export declare class BiomeSchemaSync extends BiomeSchemaSync_base {
|
|
10196
10338
|
/**
|
|
10197
10339
|
* Production implementation of {@link BiomeSchemaSync}.
|
|
10198
10340
|
*
|
|
@@ -10268,7 +10410,7 @@ declare const ConfigDiscovery_base: Context.ServiceClass<ConfigDiscovery, "@savv
|
|
|
10268
10410
|
* @since 0.1.0
|
|
10269
10411
|
* @public
|
|
10270
10412
|
*/
|
|
10271
|
-
declare class ConfigDiscovery extends ConfigDiscovery_base {
|
|
10413
|
+
export declare class ConfigDiscovery extends ConfigDiscovery_base {
|
|
10272
10414
|
/**
|
|
10273
10415
|
* Production implementation of {@link ConfigDiscovery}.
|
|
10274
10416
|
*
|
|
@@ -10396,7 +10538,7 @@ interface PublishablePackage {
|
|
|
10396
10538
|
* @since 0.4.0
|
|
10397
10539
|
* @public
|
|
10398
10540
|
*/
|
|
10399
|
-
declare class SilkPublishability {
|
|
10541
|
+
export declare class SilkPublishability {
|
|
10400
10542
|
/**
|
|
10401
10543
|
* Apply silk publishability rules to a raw `package.json` and the bundler's resolved
|
|
10402
10544
|
* target binding. Targets-first precedence:
|
|
@@ -10479,7 +10621,7 @@ declare class SilkPublishability {
|
|
|
10479
10621
|
* @since 1.0.0
|
|
10480
10622
|
* @public
|
|
10481
10623
|
*/
|
|
10482
|
-
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>;
|
|
10483
10625
|
//#endregion
|
|
10484
10626
|
//#region src/services/SilkWorkspaceAnalyzer.d.ts
|
|
10485
10627
|
/**
|
|
@@ -10530,7 +10672,7 @@ declare const SilkWorkspaceAnalyzer_base: Context.ServiceClass<SilkWorkspaceAnal
|
|
|
10530
10672
|
* @since 0.2.0
|
|
10531
10673
|
* @public
|
|
10532
10674
|
*/
|
|
10533
|
-
declare class SilkWorkspaceAnalyzer extends SilkWorkspaceAnalyzer_base {
|
|
10675
|
+
export declare class SilkWorkspaceAnalyzer extends SilkWorkspaceAnalyzer_base {
|
|
10534
10676
|
/**
|
|
10535
10677
|
* Production implementation of {@link SilkWorkspaceAnalyzer}.
|
|
10536
10678
|
*
|
|
@@ -10900,5 +11042,5 @@ declare namespace index_d_exports$5 {
|
|
|
10900
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 };
|
|
10901
11043
|
}
|
|
10902
11044
|
//#endregion
|
|
10903
|
-
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 };
|
|
10904
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.1",
|
|
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.1",
|
|
41
|
+
"@effected/package-json": "^0.14.0",
|
|
42
|
+
"@effected/templates": "^0.5.0",
|
|
43
|
+
"@effected/walker": "^0.7.0",
|
|
44
|
+
"@effected/yaml": "^0.14.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.12.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 };
|