@savvy-web/silk 1.0.0 → 1.1.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-changelog.cjs +75 -35
- package/changesets-markdownlint.cjs +75 -35
- package/lint.d.ts +7 -3
- package/package.json +6 -4
- package/packages/silk-effects/dist/dev/pkg/changesets/services/config-inspector.cjs +24 -17
- package/packages/silk-effects/dist/dev/pkg/changesets/services/config-inspector.js +24 -17
- package/packages/silk-effects/dist/dev/pkg/services/SilkPublishability.cjs +51 -18
- package/packages/silk-effects/dist/dev/pkg/services/SilkPublishability.js +51 -18
- package/public/biome/silk.jsonc +3 -2
- package/public/tsconfig/node/root.json +35 -0
- package/public/tsconfig/rspress/website.json +28 -0
package/changesets-changelog.cjs
CHANGED
|
@@ -74158,6 +74158,26 @@ const DEFAULT_REGISTRIES = {
|
|
|
74158
74158
|
github: "https://npm.pkg.github.com"
|
|
74159
74159
|
};
|
|
74160
74160
|
/**
|
|
74161
|
+
* Whether a registry endpoint participates in npm-style SLSA provenance.
|
|
74162
|
+
*
|
|
74163
|
+
* @remarks
|
|
74164
|
+
* The npm public registry and GitHub Packages both accept provenance attestations through the
|
|
74165
|
+
* Sigstore/OIDC trusted-publishing flow, so a {@link PublishTarget} bound to either is marked
|
|
74166
|
+
* `provenance: true` by default — this is what gates the release action's attestation step. JSR
|
|
74167
|
+
* and custom registries do not participate and resolve to `false`. Matching is endpoint-based
|
|
74168
|
+
* (not target-key based) so a custom key pointed at one of these registries still opts in.
|
|
74169
|
+
*/
|
|
74170
|
+
const provenanceForRegistry = (registry) => {
|
|
74171
|
+
const normalized = /^[a-z]+:\/\//i.test(registry) ? registry : `https://${registry}`;
|
|
74172
|
+
let hostname;
|
|
74173
|
+
try {
|
|
74174
|
+
hostname = new URL(normalized).hostname.toLowerCase();
|
|
74175
|
+
} catch {
|
|
74176
|
+
return false;
|
|
74177
|
+
}
|
|
74178
|
+
return hostname === "registry.npmjs.org" || hostname === "npm.pkg.github.com";
|
|
74179
|
+
};
|
|
74180
|
+
/**
|
|
74161
74181
|
* Silk publishability rules over `workspaces-effect`'s {@link PublishTarget}.
|
|
74162
74182
|
*
|
|
74163
74183
|
* @remarks
|
|
@@ -74199,28 +74219,41 @@ var SilkPublishability = class {
|
|
|
74199
74219
|
name: t.name,
|
|
74200
74220
|
registry: t.registry,
|
|
74201
74221
|
directory: dirByGroup.get(t.group) ?? `dist/prod/${t.group}/pkg`,
|
|
74202
|
-
access
|
|
74222
|
+
access,
|
|
74223
|
+
provenance: provenanceForRegistry(t.registry)
|
|
74203
74224
|
}));
|
|
74204
74225
|
}
|
|
74205
|
-
return Object.
|
|
74226
|
+
return Object.entries(targets).map(([id, target]) => {
|
|
74227
|
+
const registry = typeof target === "object" && target !== null && typeof target.registry === "string" ? target.registry : DEFAULT_REGISTRIES[id] ?? pc?.registry ?? NPM_DEFAULT;
|
|
74228
|
+
return new PublishTarget({
|
|
74229
|
+
name: pkgName,
|
|
74230
|
+
registry,
|
|
74231
|
+
directory: `dist/prod/${id}/pkg`,
|
|
74232
|
+
access,
|
|
74233
|
+
provenance: provenanceForRegistry(registry)
|
|
74234
|
+
});
|
|
74235
|
+
});
|
|
74236
|
+
}
|
|
74237
|
+
if (pc && (pc.access === "public" || pc.access === "restricted")) {
|
|
74238
|
+
const registry = pc.registry ?? NPM_DEFAULT;
|
|
74239
|
+
return [new PublishTarget({
|
|
74206
74240
|
name: pkgName,
|
|
74207
|
-
registry
|
|
74208
|
-
directory:
|
|
74209
|
-
access
|
|
74210
|
-
|
|
74241
|
+
registry,
|
|
74242
|
+
directory: pc.directory ?? ".",
|
|
74243
|
+
access: pc.access,
|
|
74244
|
+
provenance: provenanceForRegistry(registry)
|
|
74245
|
+
})];
|
|
74246
|
+
}
|
|
74247
|
+
if (raw.private !== true) {
|
|
74248
|
+
const registry = pc?.registry ?? NPM_DEFAULT;
|
|
74249
|
+
return [new PublishTarget({
|
|
74250
|
+
name: pkgName,
|
|
74251
|
+
registry,
|
|
74252
|
+
directory: pc?.directory ?? ".",
|
|
74253
|
+
access: pc?.access ?? "public",
|
|
74254
|
+
provenance: provenanceForRegistry(registry)
|
|
74255
|
+
})];
|
|
74211
74256
|
}
|
|
74212
|
-
if (pc && (pc.access === "public" || pc.access === "restricted")) return [new PublishTarget({
|
|
74213
|
-
name: pkgName,
|
|
74214
|
-
registry: pc.registry ?? NPM_DEFAULT,
|
|
74215
|
-
directory: pc.directory ?? ".",
|
|
74216
|
-
access: pc.access
|
|
74217
|
-
})];
|
|
74218
|
-
if (raw.private !== true) return [new PublishTarget({
|
|
74219
|
-
name: pkgName,
|
|
74220
|
-
registry: pc?.registry ?? NPM_DEFAULT,
|
|
74221
|
-
directory: pc?.directory ?? ".",
|
|
74222
|
-
access: pc?.access ?? "public"
|
|
74223
|
-
})];
|
|
74224
74257
|
return [];
|
|
74225
74258
|
}
|
|
74226
74259
|
/**
|
|
@@ -77211,10 +77244,12 @@ function readRawPackageJson(fs, pkgDir) {
|
|
|
77211
77244
|
/**
|
|
77212
77245
|
* Build resolved scopes from the discovered workspace packages, keeping only
|
|
77213
77246
|
* those that are a release surface (declare publishConfig that yields at least
|
|
77214
|
-
* one publish target). Used when `.changeset/config.json` declares no
|
|
77215
|
-
* `packages` record
|
|
77216
|
-
*
|
|
77217
|
-
*
|
|
77247
|
+
* one publish target). Used both when `.changeset/config.json` declares no
|
|
77248
|
+
* explicit `packages` record AND to augment an explicit record with the
|
|
77249
|
+
* remaining workspace packages it does not list (so the record annotates the
|
|
77250
|
+
* listed packages without shrinking the release surface). The changeset
|
|
77251
|
+
* `ignore` list is intentionally NOT consulted here — an ignored package still
|
|
77252
|
+
* declares publishConfig and remains a valid changeset target.
|
|
77218
77253
|
*/
|
|
77219
77254
|
function buildFallbackScopes(fs, workspaces) {
|
|
77220
77255
|
return effect.Effect.forEach(workspaces, (ws) => effect.Effect.gen(function* () {
|
|
@@ -77328,19 +77363,24 @@ function makeShape$2(reader, discovery, fs) {
|
|
|
77328
77363
|
}));
|
|
77329
77364
|
const hasExplicitPackages = Object.keys(decodedOptions.packages ?? {}).length > 0;
|
|
77330
77365
|
let scopes;
|
|
77331
|
-
if (hasExplicitPackages)
|
|
77332
|
-
|
|
77333
|
-
|
|
77334
|
-
|
|
77335
|
-
|
|
77336
|
-
|
|
77337
|
-
|
|
77338
|
-
|
|
77339
|
-
|
|
77340
|
-
|
|
77341
|
-
|
|
77342
|
-
|
|
77343
|
-
|
|
77366
|
+
if (hasExplicitPackages) {
|
|
77367
|
+
let explicitScopes;
|
|
77368
|
+
try {
|
|
77369
|
+
explicitScopes = buildResolvedScopes({
|
|
77370
|
+
options: decodedOptions,
|
|
77371
|
+
workspaces,
|
|
77372
|
+
projectDir,
|
|
77373
|
+
configPath
|
|
77374
|
+
});
|
|
77375
|
+
checkConflicts(explicitScopes, workspaces, projectDir, configPath);
|
|
77376
|
+
} catch (e) {
|
|
77377
|
+
if (e instanceof ConfigurationError) return yield* effect.Effect.fail(e);
|
|
77378
|
+
throw e;
|
|
77379
|
+
}
|
|
77380
|
+
const explicitNames = new Set(explicitScopes.map((s) => s.name));
|
|
77381
|
+
const discoveredScopes = yield* buildFallbackScopes(fs, workspaces.filter((w) => !explicitNames.has(w.name)));
|
|
77382
|
+
scopes = [...explicitScopes, ...discoveredScopes];
|
|
77383
|
+
} else scopes = yield* buildFallbackScopes(fs, workspaces);
|
|
77344
77384
|
const inspected = {
|
|
77345
77385
|
configPath,
|
|
77346
77386
|
projectDir,
|
|
@@ -74162,6 +74162,26 @@ const DEFAULT_REGISTRIES = {
|
|
|
74162
74162
|
github: "https://npm.pkg.github.com"
|
|
74163
74163
|
};
|
|
74164
74164
|
/**
|
|
74165
|
+
* Whether a registry endpoint participates in npm-style SLSA provenance.
|
|
74166
|
+
*
|
|
74167
|
+
* @remarks
|
|
74168
|
+
* The npm public registry and GitHub Packages both accept provenance attestations through the
|
|
74169
|
+
* Sigstore/OIDC trusted-publishing flow, so a {@link PublishTarget} bound to either is marked
|
|
74170
|
+
* `provenance: true` by default — this is what gates the release action's attestation step. JSR
|
|
74171
|
+
* and custom registries do not participate and resolve to `false`. Matching is endpoint-based
|
|
74172
|
+
* (not target-key based) so a custom key pointed at one of these registries still opts in.
|
|
74173
|
+
*/
|
|
74174
|
+
const provenanceForRegistry = (registry) => {
|
|
74175
|
+
const normalized = /^[a-z]+:\/\//i.test(registry) ? registry : `https://${registry}`;
|
|
74176
|
+
let hostname;
|
|
74177
|
+
try {
|
|
74178
|
+
hostname = new URL(normalized).hostname.toLowerCase();
|
|
74179
|
+
} catch {
|
|
74180
|
+
return false;
|
|
74181
|
+
}
|
|
74182
|
+
return hostname === "registry.npmjs.org" || hostname === "npm.pkg.github.com";
|
|
74183
|
+
};
|
|
74184
|
+
/**
|
|
74165
74185
|
* Silk publishability rules over `workspaces-effect`'s {@link PublishTarget}.
|
|
74166
74186
|
*
|
|
74167
74187
|
* @remarks
|
|
@@ -74203,28 +74223,41 @@ var SilkPublishability = class {
|
|
|
74203
74223
|
name: t.name,
|
|
74204
74224
|
registry: t.registry,
|
|
74205
74225
|
directory: dirByGroup.get(t.group) ?? `dist/prod/${t.group}/pkg`,
|
|
74206
|
-
access
|
|
74226
|
+
access,
|
|
74227
|
+
provenance: provenanceForRegistry(t.registry)
|
|
74207
74228
|
}));
|
|
74208
74229
|
}
|
|
74209
|
-
return Object.
|
|
74230
|
+
return Object.entries(targets).map(([id, target]) => {
|
|
74231
|
+
const registry = typeof target === "object" && target !== null && typeof target.registry === "string" ? target.registry : DEFAULT_REGISTRIES[id] ?? pc?.registry ?? NPM_DEFAULT;
|
|
74232
|
+
return new PublishTarget({
|
|
74233
|
+
name: pkgName,
|
|
74234
|
+
registry,
|
|
74235
|
+
directory: `dist/prod/${id}/pkg`,
|
|
74236
|
+
access,
|
|
74237
|
+
provenance: provenanceForRegistry(registry)
|
|
74238
|
+
});
|
|
74239
|
+
});
|
|
74240
|
+
}
|
|
74241
|
+
if (pc && (pc.access === "public" || pc.access === "restricted")) {
|
|
74242
|
+
const registry = pc.registry ?? NPM_DEFAULT;
|
|
74243
|
+
return [new PublishTarget({
|
|
74210
74244
|
name: pkgName,
|
|
74211
|
-
registry
|
|
74212
|
-
directory:
|
|
74213
|
-
access
|
|
74214
|
-
|
|
74245
|
+
registry,
|
|
74246
|
+
directory: pc.directory ?? ".",
|
|
74247
|
+
access: pc.access,
|
|
74248
|
+
provenance: provenanceForRegistry(registry)
|
|
74249
|
+
})];
|
|
74250
|
+
}
|
|
74251
|
+
if (raw.private !== true) {
|
|
74252
|
+
const registry = pc?.registry ?? NPM_DEFAULT;
|
|
74253
|
+
return [new PublishTarget({
|
|
74254
|
+
name: pkgName,
|
|
74255
|
+
registry,
|
|
74256
|
+
directory: pc?.directory ?? ".",
|
|
74257
|
+
access: pc?.access ?? "public",
|
|
74258
|
+
provenance: provenanceForRegistry(registry)
|
|
74259
|
+
})];
|
|
74215
74260
|
}
|
|
74216
|
-
if (pc && (pc.access === "public" || pc.access === "restricted")) return [new PublishTarget({
|
|
74217
|
-
name: pkgName,
|
|
74218
|
-
registry: pc.registry ?? NPM_DEFAULT,
|
|
74219
|
-
directory: pc.directory ?? ".",
|
|
74220
|
-
access: pc.access
|
|
74221
|
-
})];
|
|
74222
|
-
if (raw.private !== true) return [new PublishTarget({
|
|
74223
|
-
name: pkgName,
|
|
74224
|
-
registry: pc?.registry ?? NPM_DEFAULT,
|
|
74225
|
-
directory: pc?.directory ?? ".",
|
|
74226
|
-
access: pc?.access ?? "public"
|
|
74227
|
-
})];
|
|
74228
74261
|
return [];
|
|
74229
74262
|
}
|
|
74230
74263
|
/**
|
|
@@ -77215,10 +77248,12 @@ function readRawPackageJson(fs, pkgDir) {
|
|
|
77215
77248
|
/**
|
|
77216
77249
|
* Build resolved scopes from the discovered workspace packages, keeping only
|
|
77217
77250
|
* those that are a release surface (declare publishConfig that yields at least
|
|
77218
|
-
* one publish target). Used when `.changeset/config.json` declares no
|
|
77219
|
-
* `packages` record
|
|
77220
|
-
*
|
|
77221
|
-
*
|
|
77251
|
+
* one publish target). Used both when `.changeset/config.json` declares no
|
|
77252
|
+
* explicit `packages` record AND to augment an explicit record with the
|
|
77253
|
+
* remaining workspace packages it does not list (so the record annotates the
|
|
77254
|
+
* listed packages without shrinking the release surface). The changeset
|
|
77255
|
+
* `ignore` list is intentionally NOT consulted here — an ignored package still
|
|
77256
|
+
* declares publishConfig and remains a valid changeset target.
|
|
77222
77257
|
*/
|
|
77223
77258
|
function buildFallbackScopes(fs, workspaces) {
|
|
77224
77259
|
return effect.Effect.forEach(workspaces, (ws) => effect.Effect.gen(function* () {
|
|
@@ -77332,19 +77367,24 @@ function makeShape$2(reader, discovery, fs) {
|
|
|
77332
77367
|
}));
|
|
77333
77368
|
const hasExplicitPackages = Object.keys(decodedOptions.packages ?? {}).length > 0;
|
|
77334
77369
|
let scopes;
|
|
77335
|
-
if (hasExplicitPackages)
|
|
77336
|
-
|
|
77337
|
-
|
|
77338
|
-
|
|
77339
|
-
|
|
77340
|
-
|
|
77341
|
-
|
|
77342
|
-
|
|
77343
|
-
|
|
77344
|
-
|
|
77345
|
-
|
|
77346
|
-
|
|
77347
|
-
|
|
77370
|
+
if (hasExplicitPackages) {
|
|
77371
|
+
let explicitScopes;
|
|
77372
|
+
try {
|
|
77373
|
+
explicitScopes = buildResolvedScopes({
|
|
77374
|
+
options: decodedOptions,
|
|
77375
|
+
workspaces,
|
|
77376
|
+
projectDir,
|
|
77377
|
+
configPath
|
|
77378
|
+
});
|
|
77379
|
+
checkConflicts(explicitScopes, workspaces, projectDir, configPath);
|
|
77380
|
+
} catch (e) {
|
|
77381
|
+
if (e instanceof ConfigurationError) return yield* effect.Effect.fail(e);
|
|
77382
|
+
throw e;
|
|
77383
|
+
}
|
|
77384
|
+
const explicitNames = new Set(explicitScopes.map((s) => s.name));
|
|
77385
|
+
const discoveredScopes = yield* buildFallbackScopes(fs, workspaces.filter((w) => !explicitNames.has(w.name)));
|
|
77386
|
+
scopes = [...explicitScopes, ...discoveredScopes];
|
|
77387
|
+
} else scopes = yield* buildFallbackScopes(fs, workspaces);
|
|
77348
77388
|
const inspected = {
|
|
77349
77389
|
configPath,
|
|
77350
77390
|
projectDir,
|
package/lint.d.ts
CHANGED
|
@@ -88,7 +88,9 @@ declare const MARKDOWNLINT_CONFIG: {
|
|
|
88
88
|
readonly MD024: {
|
|
89
89
|
readonly siblings_only: true;
|
|
90
90
|
};
|
|
91
|
-
readonly MD025:
|
|
91
|
+
readonly MD025: {
|
|
92
|
+
readonly front_matter_title: "";
|
|
93
|
+
};
|
|
92
94
|
readonly MD026: true;
|
|
93
95
|
readonly MD027: true;
|
|
94
96
|
readonly MD028: true;
|
|
@@ -141,7 +143,7 @@ declare const MARKDOWNLINT_TEMPLATE: {
|
|
|
141
143
|
readonly fix: true;
|
|
142
144
|
readonly gitignore: true;
|
|
143
145
|
readonly noBanner: true;
|
|
144
|
-
readonly ignores: readonly ["**/node_modules", "**/.cache", "**/coverage", "**/.coverage", "**/dist", "**/CHANGELOG.md", "**/.claude/plans", "**/docs/superpowers"];
|
|
146
|
+
readonly ignores: readonly ["**/node_modules", "**/.cache", "**/coverage", "**/.coverage", "**/dist", "**/CHANGELOG.md", "**/.claude/plans", "**/docs/superpowers", "**/__test__/**/fixtures/**", "**/__fixtures__/**"];
|
|
145
147
|
readonly customRules: readonly ["@savvy-web/silk/changesets/markdownlint"];
|
|
146
148
|
readonly config: {
|
|
147
149
|
readonly default: true;
|
|
@@ -171,7 +173,9 @@ declare const MARKDOWNLINT_TEMPLATE: {
|
|
|
171
173
|
readonly MD024: {
|
|
172
174
|
readonly siblings_only: true;
|
|
173
175
|
};
|
|
174
|
-
readonly MD025:
|
|
176
|
+
readonly MD025: {
|
|
177
|
+
readonly front_matter_title: "";
|
|
178
|
+
};
|
|
175
179
|
readonly MD026: true;
|
|
176
180
|
readonly MD027: true;
|
|
177
181
|
readonly MD028: true;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@savvy-web/silk",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.1.1",
|
|
4
4
|
"private": false,
|
|
5
5
|
"description": "The single Silk Suite dev-tooling package — changeset, commitlint, lint, and biome conventions",
|
|
6
6
|
"homepage": "https://github.com/savvy-web/systems/tree/main/packages/silk",
|
|
@@ -60,11 +60,13 @@
|
|
|
60
60
|
"import": "./lint.js"
|
|
61
61
|
},
|
|
62
62
|
"./biome": "./public/biome/silk.jsonc",
|
|
63
|
+
"./tsconfig/node/root.json": "./public/tsconfig/node/root.json",
|
|
64
|
+
"./tsconfig/rspress/website.json": "./public/tsconfig/rspress/website.json",
|
|
63
65
|
"./package.json": "./package.json"
|
|
64
66
|
},
|
|
65
67
|
"dependencies": {
|
|
66
68
|
"@effect/platform": "^0.96.1",
|
|
67
|
-
"@savvy-web/silk-effects": "1.
|
|
69
|
+
"@savvy-web/silk-effects": "1.3.0",
|
|
68
70
|
"effect": "^3.21.3",
|
|
69
71
|
"semver": "^7.8.4"
|
|
70
72
|
},
|
|
@@ -73,8 +75,8 @@
|
|
|
73
75
|
"@changesets/cli": "^2.31.0",
|
|
74
76
|
"@commitlint/cli": "^21.0.1",
|
|
75
77
|
"@commitlint/config-conventional": "^21.0.2",
|
|
76
|
-
"@savvy-web/cli": "1.
|
|
77
|
-
"@savvy-web/mcp": "1.
|
|
78
|
+
"@savvy-web/cli": "1.1.1",
|
|
79
|
+
"@savvy-web/mcp": "1.1.1",
|
|
78
80
|
"@types/node": "^25.9.0",
|
|
79
81
|
"@typescript/native-preview": "^7.0.0-dev.20260513.1",
|
|
80
82
|
"commitizen": "^4.3.0",
|
|
@@ -248,10 +248,12 @@ function readRawPackageJson(fs, pkgDir) {
|
|
|
248
248
|
/**
|
|
249
249
|
* Build resolved scopes from the discovered workspace packages, keeping only
|
|
250
250
|
* those that are a release surface (declare publishConfig that yields at least
|
|
251
|
-
* one publish target). Used when `.changeset/config.json` declares no
|
|
252
|
-
* `packages` record
|
|
253
|
-
*
|
|
254
|
-
*
|
|
251
|
+
* one publish target). Used both when `.changeset/config.json` declares no
|
|
252
|
+
* explicit `packages` record AND to augment an explicit record with the
|
|
253
|
+
* remaining workspace packages it does not list (so the record annotates the
|
|
254
|
+
* listed packages without shrinking the release surface). The changeset
|
|
255
|
+
* `ignore` list is intentionally NOT consulted here — an ignored package still
|
|
256
|
+
* declares publishConfig and remains a valid changeset target.
|
|
255
257
|
*/
|
|
256
258
|
function buildFallbackScopes(fs, workspaces) {
|
|
257
259
|
return effect.Effect.forEach(workspaces, (ws) => effect.Effect.gen(function* () {
|
|
@@ -365,19 +367,24 @@ function makeShape(reader, discovery, fs) {
|
|
|
365
367
|
}));
|
|
366
368
|
const hasExplicitPackages = Object.keys(decodedOptions.packages ?? {}).length > 0;
|
|
367
369
|
let scopes;
|
|
368
|
-
if (hasExplicitPackages)
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
370
|
+
if (hasExplicitPackages) {
|
|
371
|
+
let explicitScopes;
|
|
372
|
+
try {
|
|
373
|
+
explicitScopes = buildResolvedScopes({
|
|
374
|
+
options: decodedOptions,
|
|
375
|
+
workspaces,
|
|
376
|
+
projectDir,
|
|
377
|
+
configPath
|
|
378
|
+
});
|
|
379
|
+
checkConflicts(explicitScopes, workspaces, projectDir, configPath);
|
|
380
|
+
} catch (e) {
|
|
381
|
+
if (e instanceof require_errors.ConfigurationError) return yield* effect.Effect.fail(e);
|
|
382
|
+
throw e;
|
|
383
|
+
}
|
|
384
|
+
const explicitNames = new Set(explicitScopes.map((s) => s.name));
|
|
385
|
+
const discoveredScopes = yield* buildFallbackScopes(fs, workspaces.filter((w) => !explicitNames.has(w.name)));
|
|
386
|
+
scopes = [...explicitScopes, ...discoveredScopes];
|
|
387
|
+
} else scopes = yield* buildFallbackScopes(fs, workspaces);
|
|
381
388
|
const inspected = {
|
|
382
389
|
configPath,
|
|
383
390
|
projectDir,
|
|
@@ -248,10 +248,12 @@ function readRawPackageJson(fs, pkgDir) {
|
|
|
248
248
|
/**
|
|
249
249
|
* Build resolved scopes from the discovered workspace packages, keeping only
|
|
250
250
|
* those that are a release surface (declare publishConfig that yields at least
|
|
251
|
-
* one publish target). Used when `.changeset/config.json` declares no
|
|
252
|
-
* `packages` record
|
|
253
|
-
*
|
|
254
|
-
*
|
|
251
|
+
* one publish target). Used both when `.changeset/config.json` declares no
|
|
252
|
+
* explicit `packages` record AND to augment an explicit record with the
|
|
253
|
+
* remaining workspace packages it does not list (so the record annotates the
|
|
254
|
+
* listed packages without shrinking the release surface). The changeset
|
|
255
|
+
* `ignore` list is intentionally NOT consulted here — an ignored package still
|
|
256
|
+
* declares publishConfig and remains a valid changeset target.
|
|
255
257
|
*/
|
|
256
258
|
function buildFallbackScopes(fs, workspaces) {
|
|
257
259
|
return Effect.forEach(workspaces, (ws) => Effect.gen(function* () {
|
|
@@ -365,19 +367,24 @@ function makeShape(reader, discovery, fs) {
|
|
|
365
367
|
}));
|
|
366
368
|
const hasExplicitPackages = Object.keys(decodedOptions.packages ?? {}).length > 0;
|
|
367
369
|
let scopes;
|
|
368
|
-
if (hasExplicitPackages)
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
370
|
+
if (hasExplicitPackages) {
|
|
371
|
+
let explicitScopes;
|
|
372
|
+
try {
|
|
373
|
+
explicitScopes = buildResolvedScopes({
|
|
374
|
+
options: decodedOptions,
|
|
375
|
+
workspaces,
|
|
376
|
+
projectDir,
|
|
377
|
+
configPath
|
|
378
|
+
});
|
|
379
|
+
checkConflicts(explicitScopes, workspaces, projectDir, configPath);
|
|
380
|
+
} catch (e) {
|
|
381
|
+
if (e instanceof ConfigurationError) return yield* Effect.fail(e);
|
|
382
|
+
throw e;
|
|
383
|
+
}
|
|
384
|
+
const explicitNames = new Set(explicitScopes.map((s) => s.name));
|
|
385
|
+
const discoveredScopes = yield* buildFallbackScopes(fs, workspaces.filter((w) => !explicitNames.has(w.name)));
|
|
386
|
+
scopes = [...explicitScopes, ...discoveredScopes];
|
|
387
|
+
} else scopes = yield* buildFallbackScopes(fs, workspaces);
|
|
381
388
|
const inspected = {
|
|
382
389
|
configPath,
|
|
383
390
|
projectDir,
|
|
@@ -16,6 +16,26 @@ const DEFAULT_REGISTRIES = {
|
|
|
16
16
|
github: "https://npm.pkg.github.com"
|
|
17
17
|
};
|
|
18
18
|
/**
|
|
19
|
+
* Whether a registry endpoint participates in npm-style SLSA provenance.
|
|
20
|
+
*
|
|
21
|
+
* @remarks
|
|
22
|
+
* The npm public registry and GitHub Packages both accept provenance attestations through the
|
|
23
|
+
* Sigstore/OIDC trusted-publishing flow, so a {@link PublishTarget} bound to either is marked
|
|
24
|
+
* `provenance: true` by default — this is what gates the release action's attestation step. JSR
|
|
25
|
+
* and custom registries do not participate and resolve to `false`. Matching is endpoint-based
|
|
26
|
+
* (not target-key based) so a custom key pointed at one of these registries still opts in.
|
|
27
|
+
*/
|
|
28
|
+
const provenanceForRegistry = (registry) => {
|
|
29
|
+
const normalized = /^[a-z]+:\/\//i.test(registry) ? registry : `https://${registry}`;
|
|
30
|
+
let hostname;
|
|
31
|
+
try {
|
|
32
|
+
hostname = new URL(normalized).hostname.toLowerCase();
|
|
33
|
+
} catch {
|
|
34
|
+
return false;
|
|
35
|
+
}
|
|
36
|
+
return hostname === "registry.npmjs.org" || hostname === "npm.pkg.github.com";
|
|
37
|
+
};
|
|
38
|
+
/**
|
|
19
39
|
* Silk publishability rules over `workspaces-effect`'s {@link PublishTarget}.
|
|
20
40
|
*
|
|
21
41
|
* @remarks
|
|
@@ -57,28 +77,41 @@ var SilkPublishability = class {
|
|
|
57
77
|
name: t.name,
|
|
58
78
|
registry: t.registry,
|
|
59
79
|
directory: dirByGroup.get(t.group) ?? `dist/prod/${t.group}/pkg`,
|
|
60
|
-
access
|
|
80
|
+
access,
|
|
81
|
+
provenance: provenanceForRegistry(t.registry)
|
|
61
82
|
}));
|
|
62
83
|
}
|
|
63
|
-
return Object.
|
|
84
|
+
return Object.entries(targets).map(([id, target]) => {
|
|
85
|
+
const registry = typeof target === "object" && target !== null && typeof target.registry === "string" ? target.registry : DEFAULT_REGISTRIES[id] ?? pc?.registry ?? NPM_DEFAULT;
|
|
86
|
+
return new require_index.PublishTarget({
|
|
87
|
+
name: pkgName,
|
|
88
|
+
registry,
|
|
89
|
+
directory: `dist/prod/${id}/pkg`,
|
|
90
|
+
access,
|
|
91
|
+
provenance: provenanceForRegistry(registry)
|
|
92
|
+
});
|
|
93
|
+
});
|
|
94
|
+
}
|
|
95
|
+
if (pc && (pc.access === "public" || pc.access === "restricted")) {
|
|
96
|
+
const registry = pc.registry ?? NPM_DEFAULT;
|
|
97
|
+
return [new require_index.PublishTarget({
|
|
98
|
+
name: pkgName,
|
|
99
|
+
registry,
|
|
100
|
+
directory: pc.directory ?? ".",
|
|
101
|
+
access: pc.access,
|
|
102
|
+
provenance: provenanceForRegistry(registry)
|
|
103
|
+
})];
|
|
104
|
+
}
|
|
105
|
+
if (raw.private !== true) {
|
|
106
|
+
const registry = pc?.registry ?? NPM_DEFAULT;
|
|
107
|
+
return [new require_index.PublishTarget({
|
|
64
108
|
name: pkgName,
|
|
65
|
-
registry
|
|
66
|
-
directory:
|
|
67
|
-
access
|
|
68
|
-
|
|
109
|
+
registry,
|
|
110
|
+
directory: pc?.directory ?? ".",
|
|
111
|
+
access: pc?.access ?? "public",
|
|
112
|
+
provenance: provenanceForRegistry(registry)
|
|
113
|
+
})];
|
|
69
114
|
}
|
|
70
|
-
if (pc && (pc.access === "public" || pc.access === "restricted")) return [new require_index.PublishTarget({
|
|
71
|
-
name: pkgName,
|
|
72
|
-
registry: pc.registry ?? NPM_DEFAULT,
|
|
73
|
-
directory: pc.directory ?? ".",
|
|
74
|
-
access: pc.access
|
|
75
|
-
})];
|
|
76
|
-
if (raw.private !== true) return [new require_index.PublishTarget({
|
|
77
|
-
name: pkgName,
|
|
78
|
-
registry: pc?.registry ?? NPM_DEFAULT,
|
|
79
|
-
directory: pc?.directory ?? ".",
|
|
80
|
-
access: pc?.access ?? "public"
|
|
81
|
-
})];
|
|
82
115
|
return [];
|
|
83
116
|
}
|
|
84
117
|
/**
|
|
@@ -16,6 +16,26 @@ const DEFAULT_REGISTRIES = {
|
|
|
16
16
|
github: "https://npm.pkg.github.com"
|
|
17
17
|
};
|
|
18
18
|
/**
|
|
19
|
+
* Whether a registry endpoint participates in npm-style SLSA provenance.
|
|
20
|
+
*
|
|
21
|
+
* @remarks
|
|
22
|
+
* The npm public registry and GitHub Packages both accept provenance attestations through the
|
|
23
|
+
* Sigstore/OIDC trusted-publishing flow, so a {@link PublishTarget} bound to either is marked
|
|
24
|
+
* `provenance: true` by default — this is what gates the release action's attestation step. JSR
|
|
25
|
+
* and custom registries do not participate and resolve to `false`. Matching is endpoint-based
|
|
26
|
+
* (not target-key based) so a custom key pointed at one of these registries still opts in.
|
|
27
|
+
*/
|
|
28
|
+
const provenanceForRegistry = (registry) => {
|
|
29
|
+
const normalized = /^[a-z]+:\/\//i.test(registry) ? registry : `https://${registry}`;
|
|
30
|
+
let hostname;
|
|
31
|
+
try {
|
|
32
|
+
hostname = new URL(normalized).hostname.toLowerCase();
|
|
33
|
+
} catch {
|
|
34
|
+
return false;
|
|
35
|
+
}
|
|
36
|
+
return hostname === "registry.npmjs.org" || hostname === "npm.pkg.github.com";
|
|
37
|
+
};
|
|
38
|
+
/**
|
|
19
39
|
* Silk publishability rules over `workspaces-effect`'s {@link PublishTarget}.
|
|
20
40
|
*
|
|
21
41
|
* @remarks
|
|
@@ -57,28 +77,41 @@ var SilkPublishability = class {
|
|
|
57
77
|
name: t.name,
|
|
58
78
|
registry: t.registry,
|
|
59
79
|
directory: dirByGroup.get(t.group) ?? `dist/prod/${t.group}/pkg`,
|
|
60
|
-
access
|
|
80
|
+
access,
|
|
81
|
+
provenance: provenanceForRegistry(t.registry)
|
|
61
82
|
}));
|
|
62
83
|
}
|
|
63
|
-
return Object.
|
|
84
|
+
return Object.entries(targets).map(([id, target]) => {
|
|
85
|
+
const registry = typeof target === "object" && target !== null && typeof target.registry === "string" ? target.registry : DEFAULT_REGISTRIES[id] ?? pc?.registry ?? NPM_DEFAULT;
|
|
86
|
+
return new PublishTarget({
|
|
87
|
+
name: pkgName,
|
|
88
|
+
registry,
|
|
89
|
+
directory: `dist/prod/${id}/pkg`,
|
|
90
|
+
access,
|
|
91
|
+
provenance: provenanceForRegistry(registry)
|
|
92
|
+
});
|
|
93
|
+
});
|
|
94
|
+
}
|
|
95
|
+
if (pc && (pc.access === "public" || pc.access === "restricted")) {
|
|
96
|
+
const registry = pc.registry ?? NPM_DEFAULT;
|
|
97
|
+
return [new PublishTarget({
|
|
98
|
+
name: pkgName,
|
|
99
|
+
registry,
|
|
100
|
+
directory: pc.directory ?? ".",
|
|
101
|
+
access: pc.access,
|
|
102
|
+
provenance: provenanceForRegistry(registry)
|
|
103
|
+
})];
|
|
104
|
+
}
|
|
105
|
+
if (raw.private !== true) {
|
|
106
|
+
const registry = pc?.registry ?? NPM_DEFAULT;
|
|
107
|
+
return [new PublishTarget({
|
|
64
108
|
name: pkgName,
|
|
65
|
-
registry
|
|
66
|
-
directory:
|
|
67
|
-
access
|
|
68
|
-
|
|
109
|
+
registry,
|
|
110
|
+
directory: pc?.directory ?? ".",
|
|
111
|
+
access: pc?.access ?? "public",
|
|
112
|
+
provenance: provenanceForRegistry(registry)
|
|
113
|
+
})];
|
|
69
114
|
}
|
|
70
|
-
if (pc && (pc.access === "public" || pc.access === "restricted")) return [new PublishTarget({
|
|
71
|
-
name: pkgName,
|
|
72
|
-
registry: pc.registry ?? NPM_DEFAULT,
|
|
73
|
-
directory: pc.directory ?? ".",
|
|
74
|
-
access: pc.access
|
|
75
|
-
})];
|
|
76
|
-
if (raw.private !== true) return [new PublishTarget({
|
|
77
|
-
name: pkgName,
|
|
78
|
-
registry: pc?.registry ?? NPM_DEFAULT,
|
|
79
|
-
directory: pc?.directory ?? ".",
|
|
80
|
-
access: pc?.access ?? "public"
|
|
81
|
-
})];
|
|
82
115
|
return [];
|
|
83
116
|
}
|
|
84
117
|
/**
|
package/public/biome/silk.jsonc
CHANGED
|
@@ -107,7 +107,7 @@
|
|
|
107
107
|
}
|
|
108
108
|
}
|
|
109
109
|
},
|
|
110
|
-
"includes": ["**/turbo.json", "**/tsconfig.json", "**/tsconfig.*.json"]
|
|
110
|
+
"includes": ["**/turbo.json", "**/tsconfig.json", "**/tsconfig.*.json", "**/public/tsconfig/**/*.json"]
|
|
111
111
|
},
|
|
112
112
|
{
|
|
113
113
|
"includes": ["**/*.test.ts"],
|
|
@@ -138,7 +138,8 @@
|
|
|
138
138
|
"!**/.vitest",
|
|
139
139
|
"!**/.coverage",
|
|
140
140
|
"!coverage",
|
|
141
|
-
"
|
|
141
|
+
"!.claude/worktrees",
|
|
142
|
+
"!**/__test__/**/fixtures",
|
|
142
143
|
"!**/__test__/snapshots",
|
|
143
144
|
"!**/__test__/**/fixtures",
|
|
144
145
|
"!**/__test__/**/snapshots",
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "https://json.schemastore.org/tsconfig",
|
|
3
|
+
"compilerOptions": {
|
|
4
|
+
"composite": true,
|
|
5
|
+
"declaration": true,
|
|
6
|
+
"module": "nodenext",
|
|
7
|
+
"outDir": "dist",
|
|
8
|
+
"resolveJsonModule": true,
|
|
9
|
+
"strict": true,
|
|
10
|
+
"strictNullChecks": true,
|
|
11
|
+
"target": "es2025",
|
|
12
|
+
"types": ["node"]
|
|
13
|
+
},
|
|
14
|
+
"exclude": ["${configDir}/node_modules", "${configDir}/dist/**/*"],
|
|
15
|
+
"include": [
|
|
16
|
+
"${configDir}/types/*.ts",
|
|
17
|
+
"${configDir}/package.json",
|
|
18
|
+
"${configDir}/*.ts",
|
|
19
|
+
"${configDir}/*.cts",
|
|
20
|
+
"${configDir}/*.mts",
|
|
21
|
+
"${configDir}/src/**/*.ts",
|
|
22
|
+
"${configDir}/src/**/*.tsx",
|
|
23
|
+
"${configDir}/src/**/*.cts",
|
|
24
|
+
"${configDir}/src/**/*.mts",
|
|
25
|
+
"${configDir}/lib/**/*.ts",
|
|
26
|
+
"${configDir}/lib/**/*.tsx",
|
|
27
|
+
"${configDir}/lib/**/*.cts",
|
|
28
|
+
"${configDir}/lib/**/*.mts",
|
|
29
|
+
"${configDir}/__test__/**/*.ts",
|
|
30
|
+
"${configDir}/__test__/**/*.tsx",
|
|
31
|
+
"${configDir}/__test__/**/*.cts",
|
|
32
|
+
"${configDir}/__test__/**/*.mts",
|
|
33
|
+
"${configDir}/public/**/*.json"
|
|
34
|
+
]
|
|
35
|
+
}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "https://json.schemastore.org/tsconfig.json",
|
|
3
|
+
"compilerOptions": {
|
|
4
|
+
"allowImportingTsExtensions": true,
|
|
5
|
+
"isolatedModules": true,
|
|
6
|
+
"jsx": "react-jsx",
|
|
7
|
+
"lib": ["dom", "es2023"],
|
|
8
|
+
"module": "esnext",
|
|
9
|
+
"moduleDetection": "force",
|
|
10
|
+
"moduleResolution": "bundler",
|
|
11
|
+
"noEmit": true,
|
|
12
|
+
"noUncheckedSideEffectImports": true,
|
|
13
|
+
"noUnusedLocals": true,
|
|
14
|
+
"noUnusedParameters": true,
|
|
15
|
+
"resolveJsonModule": true,
|
|
16
|
+
"skipLibCheck": true,
|
|
17
|
+
"strict": true,
|
|
18
|
+
"target": "es2023",
|
|
19
|
+
"types": ["node", "react", "react-dom"],
|
|
20
|
+
"useDefineForClassFields": true,
|
|
21
|
+
"verbatimModuleSyntax": true
|
|
22
|
+
},
|
|
23
|
+
"exclude": ["${configDir}/node_modules", "${configDir}/dist", "${configDir}/.rspress"],
|
|
24
|
+
"include": ["${configDir}/docs", "${configDir}/theme", "${configDir}/rspress.config.ts", "${configDir}/types/*.d.ts"],
|
|
25
|
+
"mdx": {
|
|
26
|
+
"checkMdx": true
|
|
27
|
+
}
|
|
28
|
+
}
|