@savvy-web/silk-effects 0.6.0 → 1.0.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/README.md +48 -17
- package/_virtual/_rolldown/runtime.js +18 -0
- package/changesets/api/categories.js +247 -0
- package/changesets/api/changelog.js +134 -0
- package/changesets/api/dependency-table.js +163 -0
- package/changesets/api/linter.js +168 -0
- package/changesets/api/transformer.js +140 -0
- package/changesets/categories/index.js +299 -0
- package/changesets/categories/types.js +66 -0
- package/changesets/changelog/formatting.js +119 -0
- package/changesets/changelog/getDependencyReleaseLine.js +114 -0
- package/changesets/changelog/getReleaseLine.js +122 -0
- package/changesets/changelog/index.js +99 -0
- package/changesets/constants.js +43 -0
- package/changesets/errors.js +305 -0
- package/changesets/index.js +146 -0
- package/changesets/markdownlint/index.js +29 -0
- package/changesets/markdownlint/rules/content-structure.js +98 -0
- package/changesets/markdownlint/rules/dependency-table-format.js +170 -0
- package/changesets/markdownlint/rules/heading-hierarchy.js +61 -0
- package/changesets/markdownlint/rules/required-sections.js +54 -0
- package/changesets/markdownlint/rules/uncategorized-content.js +54 -0
- package/changesets/markdownlint/rules/utils.js +30 -0
- package/changesets/remark/plugins/aggregate-dependency-tables.js +47 -0
- package/changesets/remark/plugins/contributor-footnotes.js +123 -0
- package/changesets/remark/plugins/deduplicate-items.js +30 -0
- package/changesets/remark/plugins/issue-link-refs.js +58 -0
- package/changesets/remark/plugins/merge-sections.js +43 -0
- package/changesets/remark/plugins/normalize-format.js +47 -0
- package/changesets/remark/plugins/reorder-sections.js +34 -0
- package/changesets/remark/presets.js +119 -0
- package/changesets/remark/rules/content-structure.js +22 -0
- package/changesets/remark/rules/dependency-table-format.js +40 -0
- package/changesets/remark/rules/heading-hierarchy.js +19 -0
- package/changesets/remark/rules/required-sections.js +17 -0
- package/changesets/remark/rules/uncategorized-content.js +31 -0
- package/changesets/schemas/changeset.js +146 -0
- package/changesets/schemas/dependency-table.js +189 -0
- package/changesets/schemas/git.js +69 -0
- package/changesets/schemas/github.js +175 -0
- package/changesets/schemas/options.js +182 -0
- package/changesets/schemas/package-scope.js +128 -0
- package/changesets/schemas/primitives.js +72 -0
- package/changesets/schemas/version-files.js +151 -0
- package/changesets/services/branch-analyzer.js +278 -0
- package/changesets/services/changelog.js +50 -0
- package/changesets/services/config-inspector.js +390 -0
- package/changesets/services/github.js +178 -0
- package/changesets/services/markdown.js +106 -0
- package/changesets/services/workspace-snapshot.js +182 -0
- package/changesets/utils/commit-parser.js +80 -0
- package/changesets/utils/dep-diff.js +77 -0
- package/changesets/utils/dependency-table.js +347 -0
- package/changesets/utils/issue-refs.js +101 -0
- package/changesets/utils/jsonpath.js +175 -0
- package/changesets/utils/logger.js +50 -0
- package/changesets/utils/markdown-link.js +57 -0
- package/changesets/utils/publishability.js +39 -0
- package/changesets/utils/remark-pipeline.js +79 -0
- package/changesets/utils/section-parser.js +94 -0
- package/changesets/utils/strip-frontmatter.js +46 -0
- package/changesets/utils/version-blocks.js +108 -0
- package/changesets/utils/version-files.js +336 -0
- package/changesets/utils/worktree-snapshot.js +142 -0
- package/changesets/vendor/github-info.js +55 -0
- package/commitlint/config/factory.js +69 -0
- package/commitlint/config/plugins.js +227 -0
- package/commitlint/config/rules.js +155 -0
- package/commitlint/config/schema.js +46 -0
- package/commitlint/detection/dco.js +53 -0
- package/commitlint/detection/scopes.js +45 -0
- package/commitlint/formatter/format.js +85 -0
- package/commitlint/formatter/messages.js +79 -0
- package/commitlint/hook/diagnostics/branch.js +36 -0
- package/commitlint/hook/diagnostics/cache.js +37 -0
- package/commitlint/hook/diagnostics/commitlint-config.js +36 -0
- package/commitlint/hook/diagnostics/open-issues.js +56 -0
- package/commitlint/hook/diagnostics/package-manager.js +51 -0
- package/commitlint/hook/diagnostics/signing.js +107 -0
- package/commitlint/hook/envelope.js +46 -0
- package/commitlint/hook/output.js +45 -0
- package/commitlint/hook/parse-bash-command.js +105 -0
- package/commitlint/hook/rules/closes-trailer.js +31 -0
- package/commitlint/hook/rules/forbidden-content.js +32 -0
- package/commitlint/hook/rules/plan-leakage.js +36 -0
- package/commitlint/hook/rules/signing-flag-conflict.js +25 -0
- package/commitlint/hook/rules/soft-wrap.js +37 -0
- package/commitlint/hook/rules/types.js +14 -0
- package/commitlint/hook/rules/verbosity.js +31 -0
- package/commitlint/hook/silence-logger.js +39 -0
- package/commitlint/index.js +146 -0
- package/commitlint/prompt/config.js +91 -0
- package/commitlint/prompt/emojis.js +74 -0
- package/commitlint/prompt/prompter.js +135 -0
- package/commitlint/static.js +73 -0
- package/errors/BiomeSyncError.js +21 -0
- package/errors/ChangesetConfigError.js +20 -0
- package/errors/ConfigNotFoundError.js +21 -0
- package/errors/SectionParseError.js +16 -0
- package/errors/SectionValidationError.js +16 -0
- package/errors/SectionWriteError.js +16 -0
- package/errors/TagFormatError.js +20 -0
- package/errors/ToolNotFoundError.js +11 -0
- package/errors/ToolResolutionError.js +11 -0
- package/errors/ToolVersionMismatchError.js +11 -0
- package/errors/VersioningDetectionError.js +20 -0
- package/errors/WorkspaceAnalysisError.js +21 -0
- package/index.d.ts +9743 -8380
- package/index.js +36 -6657
- package/lint/Handler.js +39 -0
- package/lint/cli/sections.js +65 -0
- package/lint/cli/templates/markdownlint.gen.js +183 -0
- package/lint/config/Preset.js +152 -0
- package/lint/config/createConfig.js +89 -0
- package/lint/handlers/Biome.js +179 -0
- package/lint/handlers/Markdown.js +139 -0
- package/lint/handlers/PackageJson.js +130 -0
- package/lint/handlers/PnpmWorkspace.js +141 -0
- package/lint/handlers/ShellScripts.js +58 -0
- package/lint/handlers/TypeScript.js +134 -0
- package/lint/handlers/Yaml.js +167 -0
- package/lint/index.js +52 -0
- package/lint/utils/Command.js +285 -0
- package/lint/utils/Filter.js +100 -0
- package/lint/utils/Workspace.js +86 -0
- package/package.json +52 -63
- package/schemas/CommentStyle.js +16 -0
- package/schemas/ResolvedTool.js +63 -0
- package/schemas/SavvySections.js +113 -0
- package/schemas/SectionBlock.js +70 -0
- package/schemas/SectionDefinition.js +121 -0
- package/schemas/SectionResults.js +12 -0
- package/schemas/TagStrategySchemas.js +18 -0
- package/schemas/ToolDefinition.js +39 -0
- package/schemas/ToolResults.js +14 -0
- package/schemas/VersioningSchemas.js +95 -0
- package/schemas/WorkspaceAnalysisSchemas.js +190 -0
- package/services/BiomeSchemaSync.js +133 -0
- package/services/ChangesetConfig.js +78 -0
- package/services/ChangesetConfigReader.js +106 -0
- package/services/ConfigDiscovery.js +71 -0
- package/services/ManagedSection.js +288 -0
- package/services/SilkPublishability.js +193 -0
- package/services/SilkWorkspaceAnalyzer.js +213 -0
- package/services/TagStrategy.js +54 -0
- package/services/ToolDiscovery.js +229 -0
- package/services/VersioningStrategy.js +67 -0
- package/tsdoc-metadata.json +11 -11
- package/turbo/digest.js +127 -0
- package/turbo/errors.js +48 -0
- package/turbo/index.js +32 -0
- package/turbo/schemas/DryRun.js +57 -0
- package/turbo/schemas/results.js +61 -0
- package/turbo/services/TurboInspector.js +100 -0
- package/utils/ToolCommand.js +40 -0
package/package.json
CHANGED
|
@@ -1,65 +1,54 @@
|
|
|
1
1
|
{
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
"files": [
|
|
55
|
-
"!silk-effects.api.json",
|
|
56
|
-
"!tsconfig.json",
|
|
57
|
-
"!tsdoc.json",
|
|
58
|
-
"LICENSE",
|
|
59
|
-
"README.md",
|
|
60
|
-
"index.d.ts",
|
|
61
|
-
"index.js",
|
|
62
|
-
"package.json",
|
|
63
|
-
"tsdoc-metadata.json"
|
|
64
|
-
]
|
|
2
|
+
"name": "@savvy-web/silk-effects",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"private": false,
|
|
5
|
+
"description": "Shared Effect library for Silk Suite conventions",
|
|
6
|
+
"homepage": "https://github.com/savvy-web/systems/tree/main/packages/silk-effects",
|
|
7
|
+
"bugs": {
|
|
8
|
+
"url": "https://github.com/savvy-web/systems/issues"
|
|
9
|
+
},
|
|
10
|
+
"repository": {
|
|
11
|
+
"type": "git",
|
|
12
|
+
"url": "git+https://github.com/savvy-web/systems.git",
|
|
13
|
+
"directory": "packages/silk-effects"
|
|
14
|
+
},
|
|
15
|
+
"license": "MIT",
|
|
16
|
+
"author": {
|
|
17
|
+
"name": "C. Spencer Beggs",
|
|
18
|
+
"email": "spencer@savvyweb.systems",
|
|
19
|
+
"url": "https://savvyweb.systems"
|
|
20
|
+
},
|
|
21
|
+
"sideEffects": false,
|
|
22
|
+
"type": "module",
|
|
23
|
+
"exports": {
|
|
24
|
+
".": {
|
|
25
|
+
"types": "./index.d.ts",
|
|
26
|
+
"import": "./index.js"
|
|
27
|
+
}
|
|
28
|
+
},
|
|
29
|
+
"dependencies": {
|
|
30
|
+
"@changesets/get-github-info": "^0.8.0",
|
|
31
|
+
"jsonc-effect": "^0.2.1",
|
|
32
|
+
"mdast-util-heading-range": "^4.0.0",
|
|
33
|
+
"mdast-util-to-string": "^4.0.0",
|
|
34
|
+
"prettier": "^3.8.3",
|
|
35
|
+
"remark-gfm": "^4.0.1",
|
|
36
|
+
"remark-parse": "^11.0.0",
|
|
37
|
+
"remark-stringify": "^11.0.0",
|
|
38
|
+
"semver-effect": "^0.2.1",
|
|
39
|
+
"shell-quote": "^1.8.4",
|
|
40
|
+
"sort-package-json": "^3.6.1",
|
|
41
|
+
"tinyglobby": "^0.2.16",
|
|
42
|
+
"unified": "^11.0.5",
|
|
43
|
+
"unified-lint-rule": "^3.0.1",
|
|
44
|
+
"unist-util-visit": "^5.1.0",
|
|
45
|
+
"workspaces-effect": "^1.1.0",
|
|
46
|
+
"yaml": "^2.9.0",
|
|
47
|
+
"yaml-effect": "^0.6.0",
|
|
48
|
+
"yaml-lint": "^1.7.0"
|
|
49
|
+
},
|
|
50
|
+
"peerDependencies": {
|
|
51
|
+
"@effect/platform": ">=0.96.0",
|
|
52
|
+
"effect": ">=3.21.0"
|
|
53
|
+
}
|
|
65
54
|
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { Schema } from "effect";
|
|
2
|
+
|
|
3
|
+
//#region src/schemas/CommentStyle.ts
|
|
4
|
+
/**
|
|
5
|
+
* Comment syntax used to write managed section markers.
|
|
6
|
+
*
|
|
7
|
+
* @remarks
|
|
8
|
+
* - `"#"` — shell/YAML style, suitable for hook scripts and `.env` files.
|
|
9
|
+
* - `"//"` — C-style, suitable for JavaScript/TypeScript files.
|
|
10
|
+
*
|
|
11
|
+
* @since 0.1.0
|
|
12
|
+
*/
|
|
13
|
+
const CommentStyle = Schema.Literal("#", "//");
|
|
14
|
+
|
|
15
|
+
//#endregion
|
|
16
|
+
export { CommentStyle };
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
import { ToolCommand } from "../utils/ToolCommand.js";
|
|
2
|
+
import { ToolSource } from "./ToolResults.js";
|
|
3
|
+
import { Equal, Hash, Schema } from "effect";
|
|
4
|
+
import { Command } from "@effect/platform";
|
|
5
|
+
|
|
6
|
+
//#region src/schemas/ResolvedTool.ts
|
|
7
|
+
const PackageManager = Schema.Literal("npm", "pnpm", "yarn", "bun");
|
|
8
|
+
/**
|
|
9
|
+
* Result of resolving a {@link ToolDefinition}.
|
|
10
|
+
*
|
|
11
|
+
* Provides {@link exec} and {@link dlx} to build commands for the resolved tool.
|
|
12
|
+
*
|
|
13
|
+
* @since 0.2.0
|
|
14
|
+
*/
|
|
15
|
+
var ResolvedTool = class ResolvedTool extends Schema.TaggedClass()("ResolvedTool", {
|
|
16
|
+
name: Schema.String,
|
|
17
|
+
source: ToolSource,
|
|
18
|
+
version: Schema.OptionFromSelf(Schema.String),
|
|
19
|
+
globalVersion: Schema.OptionFromSelf(Schema.String),
|
|
20
|
+
localVersion: Schema.OptionFromSelf(Schema.String),
|
|
21
|
+
packageManager: PackageManager,
|
|
22
|
+
mismatch: Schema.Boolean
|
|
23
|
+
}) {
|
|
24
|
+
get isGlobal() {
|
|
25
|
+
return this.source === "global";
|
|
26
|
+
}
|
|
27
|
+
get isLocal() {
|
|
28
|
+
return this.source === "local";
|
|
29
|
+
}
|
|
30
|
+
get hasVersionMismatch() {
|
|
31
|
+
return this.mismatch;
|
|
32
|
+
}
|
|
33
|
+
exec(...args) {
|
|
34
|
+
if (this.source === "global") return new ToolCommand(Command.make(this.name, ...args));
|
|
35
|
+
switch (this.packageManager) {
|
|
36
|
+
case "pnpm": return new ToolCommand(Command.make("pnpm", "exec", this.name, ...args));
|
|
37
|
+
case "npm": return new ToolCommand(Command.make("npx", "--no", "--", this.name, ...args));
|
|
38
|
+
case "yarn": return new ToolCommand(Command.make("yarn", "exec", this.name, ...args));
|
|
39
|
+
case "bun": return new ToolCommand(Command.make("bun", "x", "--no-install", this.name, ...args));
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
dlx(...args) {
|
|
43
|
+
switch (this.packageManager) {
|
|
44
|
+
case "pnpm": return new ToolCommand(Command.make("pnpm", "dlx", this.name, ...args));
|
|
45
|
+
case "npm": return new ToolCommand(Command.make("npx", this.name, ...args));
|
|
46
|
+
case "yarn": return new ToolCommand(Command.make("yarn", "dlx", this.name, ...args));
|
|
47
|
+
case "bun": return new ToolCommand(Command.make("bun", "x", this.name, ...args));
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
[Equal.symbol](that) {
|
|
51
|
+
if (!(that instanceof ResolvedTool)) return false;
|
|
52
|
+
return this.name === that.name && this.source === that.source && Equal.equals(this.version, that.version);
|
|
53
|
+
}
|
|
54
|
+
[Hash.symbol]() {
|
|
55
|
+
let h = Hash.hash(this.name);
|
|
56
|
+
h = Hash.combine(h)(Hash.hash(this.source));
|
|
57
|
+
h = Hash.combine(h)(Hash.hash(this.version));
|
|
58
|
+
return Hash.cached(this)(h);
|
|
59
|
+
}
|
|
60
|
+
};
|
|
61
|
+
|
|
62
|
+
//#endregion
|
|
63
|
+
export { ResolvedTool };
|
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
import { ShellSectionDefinition } from "./SectionDefinition.js";
|
|
2
|
+
|
|
3
|
+
//#region src/schemas/SavvySections.ts
|
|
4
|
+
/**
|
|
5
|
+
* Section identity for the shared package-manager preamble.
|
|
6
|
+
*
|
|
7
|
+
* `toolName` is `"savvy-base"`; pair with {@link savvyBasePreamble} to build the block:
|
|
8
|
+
*
|
|
9
|
+
* @example
|
|
10
|
+
* ```ts
|
|
11
|
+
* const block = SavvyBaseSection.block(savvyBasePreamble());
|
|
12
|
+
* ```
|
|
13
|
+
*
|
|
14
|
+
* @since 0.5.0
|
|
15
|
+
*/
|
|
16
|
+
const SavvyBaseSection = ShellSectionDefinition.make({ toolName: "savvy-base" });
|
|
17
|
+
/**
|
|
18
|
+
* Section identity for the shared repo-hygiene block.
|
|
19
|
+
*
|
|
20
|
+
* `toolName` is `"savvy-hooks"`; pair with {@link savvyHooksHygiene}.
|
|
21
|
+
*
|
|
22
|
+
* @since 0.5.0
|
|
23
|
+
*/
|
|
24
|
+
const SavvyHooksSection = ShellSectionDefinition.make({ toolName: "savvy-hooks" });
|
|
25
|
+
/**
|
|
26
|
+
* Package-manager detection preamble shared across Silk Suite hook files.
|
|
27
|
+
*
|
|
28
|
+
* @remarks
|
|
29
|
+
* Side-effect-free definitions meant to run unconditionally — no markers, no outer CI
|
|
30
|
+
* guard. Defines `ROOT`, the `in_ci` predicate, `PM` (via `detect_pm`), and `pm_exec`.
|
|
31
|
+
* `pm_exec` uses local/exec semantics for every package manager and `bun x` (space form),
|
|
32
|
+
* which works regardless of how bun was installed (the `bunx` shim is not always on PATH).
|
|
33
|
+
*
|
|
34
|
+
* @returns The preamble shell, with no surrounding markers or trailing newline.
|
|
35
|
+
*
|
|
36
|
+
* @since 0.5.0
|
|
37
|
+
*/
|
|
38
|
+
function savvyBasePreamble() {
|
|
39
|
+
return `ROOT=$(git rev-parse --show-toplevel)
|
|
40
|
+
|
|
41
|
+
in_ci() { [ -n "$CI" ] || [ -n "$GITHUB_ACTIONS" ]; }
|
|
42
|
+
|
|
43
|
+
detect_pm() {
|
|
44
|
+
if [ -f "$ROOT/package.json" ]; then
|
|
45
|
+
pm=$(jq -r '.packageManager // empty' "$ROOT/package.json" 2>/dev/null | cut -d'@' -f1)
|
|
46
|
+
if [ -n "$pm" ]; then echo "$pm"; return; fi
|
|
47
|
+
fi
|
|
48
|
+
if [ -f "$ROOT/pnpm-lock.yaml" ]; then echo "pnpm"
|
|
49
|
+
elif [ -f "$ROOT/yarn.lock" ]; then echo "yarn"
|
|
50
|
+
elif [ -f "$ROOT/bun.lock" ]; then echo "bun"
|
|
51
|
+
else echo "npm"; fi
|
|
52
|
+
}
|
|
53
|
+
PM=$(detect_pm)
|
|
54
|
+
|
|
55
|
+
pm_exec() {
|
|
56
|
+
case "$PM" in
|
|
57
|
+
pnpm) pnpm exec "$@" ;;
|
|
58
|
+
yarn) yarn exec "$@" ;;
|
|
59
|
+
bun) bun x "$@" ;;
|
|
60
|
+
*) npx --no -- "$@" ;;
|
|
61
|
+
esac
|
|
62
|
+
}`;
|
|
63
|
+
}
|
|
64
|
+
/**
|
|
65
|
+
* Repo-hygiene block shared across Silk Suite hook files.
|
|
66
|
+
*
|
|
67
|
+
* @remarks
|
|
68
|
+
* Self-guarded against CI and needs no package manager: disables Git's `core.fileMode`
|
|
69
|
+
* tracking and marks tracked shell scripts executable.
|
|
70
|
+
*
|
|
71
|
+
* @returns The hygiene shell, with no surrounding markers or trailing newline.
|
|
72
|
+
*
|
|
73
|
+
* @since 0.5.0
|
|
74
|
+
*/
|
|
75
|
+
function savvyHooksHygiene() {
|
|
76
|
+
return `if ! { [ -n "$CI" ] || [ -n "$GITHUB_ACTIONS" ]; }; then
|
|
77
|
+
git config core.fileMode false
|
|
78
|
+
git ls-files -z '*.sh' | xargs -0 chmod +x 2>/dev/null || true
|
|
79
|
+
fi`;
|
|
80
|
+
}
|
|
81
|
+
/**
|
|
82
|
+
* Build a consumer's one-line tool section so every consumer calls the shared base
|
|
83
|
+
* helpers identically.
|
|
84
|
+
*
|
|
85
|
+
* @remarks
|
|
86
|
+
* The returned block's content is exactly `in_ci || pm_exec <command>` with `command`
|
|
87
|
+
* appended verbatim — it is not parsed, quoted, or interpolated, so shell tokens like
|
|
88
|
+
* `$ROOT` and `$1` survive into the generated literal.
|
|
89
|
+
*
|
|
90
|
+
* **Precondition:** a {@link SavvyBaseSection} block must precede this section in the same
|
|
91
|
+
* hook file so `in_ci` and `pm_exec` are defined. Consumers guarantee this by passing both
|
|
92
|
+
* to {@link ManagedSection.syncMany | ManagedSection.syncMany} in order:
|
|
93
|
+
*
|
|
94
|
+
* @example
|
|
95
|
+
* ```ts
|
|
96
|
+
* yield* ManagedSection.syncMany(".husky/commit-msg", [
|
|
97
|
+
* SavvyBaseSection.block(savvyBasePreamble()),
|
|
98
|
+
* savvyToolSection("savvy-commit", 'commitlint --config "$ROOT/lib/configs/commitlint.config.ts" --edit "$1"'),
|
|
99
|
+
* ]);
|
|
100
|
+
* ```
|
|
101
|
+
*
|
|
102
|
+
* @param toolName - Section identity; also drives the marker names (uppercased).
|
|
103
|
+
* @param command - The command passed verbatim to `pm_exec`, run only outside CI.
|
|
104
|
+
* @returns A shell {@link SectionBlock} (`commentStyle: "#"`) for `toolName`.
|
|
105
|
+
*
|
|
106
|
+
* @since 0.5.0
|
|
107
|
+
*/
|
|
108
|
+
function savvyToolSection(toolName, command) {
|
|
109
|
+
return ShellSectionDefinition.make({ toolName }).block(`in_ci || pm_exec ${command}`);
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
//#endregion
|
|
113
|
+
export { SavvyBaseSection, SavvyHooksSection, savvyBasePreamble, savvyHooksHygiene, savvyToolSection };
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
import { CommentStyle } from "./CommentStyle.js";
|
|
2
|
+
import { SectionDiff } from "./SectionResults.js";
|
|
3
|
+
import { Equal, Function, Hash, Schema } from "effect";
|
|
4
|
+
|
|
5
|
+
//#region src/schemas/SectionBlock.ts
|
|
6
|
+
/**
|
|
7
|
+
* The content between managed section markers.
|
|
8
|
+
*
|
|
9
|
+
* {@link Equal} compares normalized content only (trimmed, whitespace-collapsed).
|
|
10
|
+
* Use {@link SectionBlock.diff | diff} to compute line-level differences.
|
|
11
|
+
*
|
|
12
|
+
* @since 0.2.0
|
|
13
|
+
*/
|
|
14
|
+
var SectionBlock = class SectionBlock extends Schema.TaggedClass()("SectionBlock", {
|
|
15
|
+
toolName: Schema.String,
|
|
16
|
+
commentStyle: CommentStyle,
|
|
17
|
+
content: Schema.String
|
|
18
|
+
}) {
|
|
19
|
+
static diff = Function.dual(2, (self, that) => self.diff(that));
|
|
20
|
+
static prepend = Function.dual(2, (self, lines) => self.prepend(lines));
|
|
21
|
+
static append = Function.dual(2, (self, lines) => self.append(lines));
|
|
22
|
+
get text() {
|
|
23
|
+
return this.content;
|
|
24
|
+
}
|
|
25
|
+
get normalized() {
|
|
26
|
+
return this.content.trim().replace(/\s+/g, " ");
|
|
27
|
+
}
|
|
28
|
+
get rendered() {
|
|
29
|
+
const begin = `${this.commentStyle} --- BEGIN ${this.toolName.toUpperCase()} MANAGED SECTION ---`;
|
|
30
|
+
const end = `${this.commentStyle} --- END ${this.toolName.toUpperCase()} MANAGED SECTION ---`;
|
|
31
|
+
return `${begin}\n${this.content}\n${end}`;
|
|
32
|
+
}
|
|
33
|
+
prepend(lines) {
|
|
34
|
+
return SectionBlock.make({
|
|
35
|
+
toolName: this.toolName,
|
|
36
|
+
commentStyle: this.commentStyle,
|
|
37
|
+
content: `${lines}\n${this.content}`
|
|
38
|
+
});
|
|
39
|
+
}
|
|
40
|
+
append(lines) {
|
|
41
|
+
return SectionBlock.make({
|
|
42
|
+
toolName: this.toolName,
|
|
43
|
+
commentStyle: this.commentStyle,
|
|
44
|
+
content: `${this.content}\n${lines}`
|
|
45
|
+
});
|
|
46
|
+
}
|
|
47
|
+
diff(that) {
|
|
48
|
+
if (this.normalized === that.normalized) return SectionDiff.Unchanged();
|
|
49
|
+
const selfLines = this.content.trim().split("\n");
|
|
50
|
+
const thatLines = that.content.trim().split("\n");
|
|
51
|
+
const selfSet = new Set(selfLines);
|
|
52
|
+
const thatSet = new Set(thatLines);
|
|
53
|
+
const removed = selfLines.filter((line) => !thatSet.has(line));
|
|
54
|
+
const added = thatLines.filter((line) => !selfSet.has(line));
|
|
55
|
+
return SectionDiff.Changed({
|
|
56
|
+
added,
|
|
57
|
+
removed
|
|
58
|
+
});
|
|
59
|
+
}
|
|
60
|
+
[Equal.symbol](that) {
|
|
61
|
+
if (!(that instanceof SectionBlock)) return false;
|
|
62
|
+
return this.normalized === that.normalized;
|
|
63
|
+
}
|
|
64
|
+
[Hash.symbol]() {
|
|
65
|
+
return Hash.cached(this)(Hash.hash(this.normalized));
|
|
66
|
+
}
|
|
67
|
+
};
|
|
68
|
+
|
|
69
|
+
//#endregion
|
|
70
|
+
export { SectionBlock };
|
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
import { SectionValidationError } from "../errors/SectionValidationError.js";
|
|
2
|
+
import { CommentStyle } from "./CommentStyle.js";
|
|
3
|
+
import { SectionDiff } from "./SectionResults.js";
|
|
4
|
+
import { SectionBlock } from "./SectionBlock.js";
|
|
5
|
+
import { Effect, Equal, Function, Hash, Schema } from "effect";
|
|
6
|
+
|
|
7
|
+
//#region src/schemas/SectionDefinition.ts
|
|
8
|
+
/**
|
|
9
|
+
* Identity envelope for a managed section type.
|
|
10
|
+
*
|
|
11
|
+
* {@link Equal} compares on `toolName` + `commentStyle`.
|
|
12
|
+
* Use {@link SectionDefinition.block | block()} to create a {@link SectionBlock},
|
|
13
|
+
* or {@link SectionDefinition.generate | generate()} for a typed factory.
|
|
14
|
+
*
|
|
15
|
+
* @since 0.2.0
|
|
16
|
+
*/
|
|
17
|
+
var SectionDefinition = class SectionDefinition extends Schema.TaggedClass()("SectionDefinition", {
|
|
18
|
+
toolName: Schema.String,
|
|
19
|
+
commentStyle: Schema.optionalWith(CommentStyle, { default: () => "#" })
|
|
20
|
+
}) {
|
|
21
|
+
_validate;
|
|
22
|
+
static generate = Function.dual(2, (self, fn) => {
|
|
23
|
+
return (config) => self.block(fn(config));
|
|
24
|
+
});
|
|
25
|
+
static generateEffect = Function.dual(2, (self, fn) => {
|
|
26
|
+
return (config) => Effect.flatMap(fn(config), (content) => {
|
|
27
|
+
try {
|
|
28
|
+
return Effect.succeed(self.block(content));
|
|
29
|
+
} catch (e) {
|
|
30
|
+
return Effect.fail(e);
|
|
31
|
+
}
|
|
32
|
+
});
|
|
33
|
+
});
|
|
34
|
+
static withValidation = Function.dual(2, (self, fn) => {
|
|
35
|
+
const copy = SectionDefinition.make({
|
|
36
|
+
toolName: self.toolName,
|
|
37
|
+
commentStyle: self.commentStyle
|
|
38
|
+
});
|
|
39
|
+
copy._validate = fn;
|
|
40
|
+
return copy;
|
|
41
|
+
});
|
|
42
|
+
static diff = Function.dual(2, (self, that) => self.diff(that));
|
|
43
|
+
block(content) {
|
|
44
|
+
const block = SectionBlock.make({
|
|
45
|
+
toolName: this.toolName,
|
|
46
|
+
commentStyle: this.commentStyle,
|
|
47
|
+
content
|
|
48
|
+
});
|
|
49
|
+
if (this._validate && !this._validate(block)) throw new SectionValidationError({
|
|
50
|
+
toolName: this.toolName,
|
|
51
|
+
reason: "Content failed validation"
|
|
52
|
+
});
|
|
53
|
+
return block;
|
|
54
|
+
}
|
|
55
|
+
generate(fn) {
|
|
56
|
+
return (config) => this.block(fn(config));
|
|
57
|
+
}
|
|
58
|
+
generateEffect(fn) {
|
|
59
|
+
return (config) => Effect.flatMap(fn(config), (content) => {
|
|
60
|
+
try {
|
|
61
|
+
return Effect.succeed(this.block(content));
|
|
62
|
+
} catch (e) {
|
|
63
|
+
return Effect.fail(e);
|
|
64
|
+
}
|
|
65
|
+
});
|
|
66
|
+
}
|
|
67
|
+
diff(that) {
|
|
68
|
+
if (Equal.equals(this, that)) return SectionDiff.Unchanged();
|
|
69
|
+
return SectionDiff.Changed({
|
|
70
|
+
added: [that.toolName !== this.toolName ? `toolName: ${that.toolName}` : "", that.commentStyle !== this.commentStyle ? `commentStyle: ${that.commentStyle}` : ""].filter(Boolean),
|
|
71
|
+
removed: [that.toolName !== this.toolName ? `toolName: ${this.toolName}` : "", that.commentStyle !== this.commentStyle ? `commentStyle: ${this.commentStyle}` : ""].filter(Boolean)
|
|
72
|
+
});
|
|
73
|
+
}
|
|
74
|
+
get beginMarker() {
|
|
75
|
+
return `${this.commentStyle} --- BEGIN ${this.toolName.toUpperCase()} MANAGED SECTION ---`;
|
|
76
|
+
}
|
|
77
|
+
get endMarker() {
|
|
78
|
+
return `${this.commentStyle} --- END ${this.toolName.toUpperCase()} MANAGED SECTION ---`;
|
|
79
|
+
}
|
|
80
|
+
[Equal.symbol](that) {
|
|
81
|
+
if (!(that instanceof SectionDefinition)) return false;
|
|
82
|
+
return this.toolName === that.toolName && this.commentStyle === that.commentStyle;
|
|
83
|
+
}
|
|
84
|
+
[Hash.symbol]() {
|
|
85
|
+
return Hash.cached(this)(Hash.combine(Hash.hash(this.toolName))(Hash.hash(this.commentStyle)));
|
|
86
|
+
}
|
|
87
|
+
};
|
|
88
|
+
/**
|
|
89
|
+
* Convenience section definition for shell hooks.
|
|
90
|
+
*
|
|
91
|
+
* `commentStyle` is always `"#"` — only `toolName` is required.
|
|
92
|
+
*
|
|
93
|
+
* @since 0.2.0
|
|
94
|
+
*/
|
|
95
|
+
var ShellSectionDefinition = class extends Schema.TaggedClass()("ShellSectionDefinition", { toolName: Schema.String }) {
|
|
96
|
+
get commentStyle() {
|
|
97
|
+
return "#";
|
|
98
|
+
}
|
|
99
|
+
block(content) {
|
|
100
|
+
return SectionBlock.make({
|
|
101
|
+
toolName: this.toolName,
|
|
102
|
+
commentStyle: "#",
|
|
103
|
+
content
|
|
104
|
+
});
|
|
105
|
+
}
|
|
106
|
+
generate(fn) {
|
|
107
|
+
return (config) => this.block(fn(config));
|
|
108
|
+
}
|
|
109
|
+
generateEffect(fn) {
|
|
110
|
+
return (config) => Effect.map(fn(config), (content) => this.block(content));
|
|
111
|
+
}
|
|
112
|
+
get beginMarker() {
|
|
113
|
+
return `# --- BEGIN ${this.toolName.toUpperCase()} MANAGED SECTION ---`;
|
|
114
|
+
}
|
|
115
|
+
get endMarker() {
|
|
116
|
+
return `# --- END ${this.toolName.toUpperCase()} MANAGED SECTION ---`;
|
|
117
|
+
}
|
|
118
|
+
};
|
|
119
|
+
|
|
120
|
+
//#endregion
|
|
121
|
+
export { SectionDefinition, ShellSectionDefinition };
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { Data } from "effect";
|
|
2
|
+
|
|
3
|
+
//#region src/schemas/SectionResults.ts
|
|
4
|
+
/** @since 0.2.0 */
|
|
5
|
+
const SectionDiff = Data.taggedEnum();
|
|
6
|
+
/** @since 0.2.0 */
|
|
7
|
+
const SyncResult = Data.taggedEnum();
|
|
8
|
+
/** @since 0.2.0 */
|
|
9
|
+
const CheckResult = Data.taggedEnum();
|
|
10
|
+
|
|
11
|
+
//#endregion
|
|
12
|
+
export { CheckResult, SectionDiff, SyncResult };
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { Schema } from "effect";
|
|
2
|
+
|
|
3
|
+
//#region src/schemas/TagStrategySchemas.ts
|
|
4
|
+
/**
|
|
5
|
+
* Git tag naming strategy for a workspace.
|
|
6
|
+
*
|
|
7
|
+
* @remarks
|
|
8
|
+
* - `"single"` — one shared tag for the entire release (e.g. `1.2.3`).
|
|
9
|
+
* - `"scoped"` — a per-package tag that includes the package name (e.g. `@my-org/pkg@1.2.3`).
|
|
10
|
+
*
|
|
11
|
+
* Determined by {@link TagStrategy.determine} based on the {@link VersioningStrategyResult}.
|
|
12
|
+
*
|
|
13
|
+
* @since 0.1.0
|
|
14
|
+
*/
|
|
15
|
+
const TagStrategyType = Schema.Literal("single", "scoped");
|
|
16
|
+
|
|
17
|
+
//#endregion
|
|
18
|
+
export { TagStrategyType };
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { ResolutionPolicy, SourceRequirement, VersionExtractor } from "./ToolResults.js";
|
|
2
|
+
import { Equal, Hash, Schema } from "effect";
|
|
3
|
+
|
|
4
|
+
//#region src/schemas/ToolDefinition.ts
|
|
5
|
+
const NameSchema = Schema.Struct({ name: Schema.String });
|
|
6
|
+
/**
|
|
7
|
+
* Declares a CLI tool's identity and resolution constraints.
|
|
8
|
+
*
|
|
9
|
+
* {@link Equal} compares on `name` only (identity).
|
|
10
|
+
*
|
|
11
|
+
* @since 0.2.0
|
|
12
|
+
*/
|
|
13
|
+
var ToolDefinition = class ToolDefinition {
|
|
14
|
+
_tag = "ToolDefinition";
|
|
15
|
+
name;
|
|
16
|
+
versionExtractor;
|
|
17
|
+
policy;
|
|
18
|
+
source;
|
|
19
|
+
constructor(name, versionExtractor, policy, source) {
|
|
20
|
+
this.name = name;
|
|
21
|
+
this.versionExtractor = versionExtractor;
|
|
22
|
+
this.policy = policy;
|
|
23
|
+
this.source = source;
|
|
24
|
+
}
|
|
25
|
+
static make(options) {
|
|
26
|
+
Schema.decodeUnknownSync(NameSchema)({ name: options.name });
|
|
27
|
+
return new ToolDefinition(options.name, options.versionExtractor ?? VersionExtractor.Flag({ flag: "--version" }), options.policy ?? ResolutionPolicy.Report(), options.source ?? SourceRequirement.Any());
|
|
28
|
+
}
|
|
29
|
+
[Equal.symbol](that) {
|
|
30
|
+
if (!(that instanceof ToolDefinition)) return false;
|
|
31
|
+
return this.name === that.name;
|
|
32
|
+
}
|
|
33
|
+
[Hash.symbol]() {
|
|
34
|
+
return Hash.cached(this)(Hash.hash(this.name));
|
|
35
|
+
}
|
|
36
|
+
};
|
|
37
|
+
|
|
38
|
+
//#endregion
|
|
39
|
+
export { ToolDefinition };
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { Data, Schema } from "effect";
|
|
2
|
+
|
|
3
|
+
//#region src/schemas/ToolResults.ts
|
|
4
|
+
/** Where a tool was resolved from. @since 0.2.0 */
|
|
5
|
+
const ToolSource = Schema.Literal("global", "local");
|
|
6
|
+
/** @since 0.2.0 */
|
|
7
|
+
const VersionExtractor = Data.taggedEnum();
|
|
8
|
+
/** @since 0.2.0 */
|
|
9
|
+
const ResolutionPolicy = Data.taggedEnum();
|
|
10
|
+
/** @since 0.2.0 */
|
|
11
|
+
const SourceRequirement = Data.taggedEnum();
|
|
12
|
+
|
|
13
|
+
//#endregion
|
|
14
|
+
export { ResolutionPolicy, SourceRequirement, ToolSource, VersionExtractor };
|