Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .changeset/fix-cli-bundle-workspace-deps.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@stackwright/cli": patch
---

Bundle internal `@stackwright/*` workspace dependencies into the CLI binary via tsup `noExternal`. This fixes `ERR_PNPM_WORKSPACE_PKG_NOT_FOUND` when installing `@stackwright/cli` via `pnpm dlx` outside a monorepo. Also adds a `prepublishOnly` guard to catch any future `workspace:*` leakage before publish.
31 changes: 31 additions & 0 deletions .changeset/fix-core-dts-zod-compat.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
---
"@stackwright/core": patch
---

fix(core): remove zod internals from published .d.ts

The generated `dist/index.d.ts` previously embedded zod-version-specific
internal types (`z.ZodTypeAny`, `z.core.$strip`, `z.ZodObject` generics)
directly into the exported API surface. This caused TypeScript errors in
consumer projects whose installed zod version differed from the one used
at build time — particularly the zod@3 → zod@4 upgrade — forcing them to
maintain `stackwright-core.d.ts` module-override stubs as workarounds.

Two root causes fixed:

1. `ContentTypeEntry.schema` and the `registerContentType` / `getContentTypeSchema`
signatures now use a local `ZodSchema` structural interface instead of
`z.ZodTypeAny`. Any real Zod schema satisfies `ZodSchema` via duck-typing,
so existing call-sites are unaffected.

2. `siteDefaults.ts` was importing `SiteConfig` via a relative path to the
`@stackwright/types` source file, causing tsup to inline the entire
`siteConfigSchema: z.ZodObject<{..., z.core.$strip}>` declaration into the
bundled d.ts. Changed to `import type { SiteConfig } from '@stackwright/types'`
so tsup treats it as an external package reference.

Additionally, `@stackwright/types`, `@stackwright/themes`, and
`@stackwright/collections` are now listed in tsup's `external` array as a
defensive measure against future inlining regressions.

Consumer projects can now delete any `stackwright-core.d.ts` stub override files.
26 changes: 26 additions & 0 deletions .changeset/fix-scaffold-template-versions.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
---
"@stackwright/cli": patch
---

fix(cli): update stale scaffold template package versions

`buildPackageJson()` in `template-processor.ts` was pinning scaffolded
projects to package versions that were 4+ releases behind:

- `@stackwright/core`: `^0.7.0` → `^0.8.0`
- `@stackwright/nextjs`: `^0.3.1` → `^0.5.0`
- `@stackwright/icons`: `^0.3.0` → `^0.5.0`
- `@stackwright/build-scripts`: `^0.4.0` → `^0.7.0` ← **critical**
- `@stackwright/ui-shadcn`: `^0.1.0` → `^0.1.2`
- `@stackwright/otters`: `^0.2.0-alpha.0` → `^0.2.0`

The `build-scripts` version was the critical failure: the plugin API
(`PrebuildPlugin`, `beforeBuild`, `contentItemSchemas`) was introduced in
0.5.0, but scaffolded projects installed 0.4.0 — a version that has no
plugin system at all. This caused Pro plugin hooks to silently fail or
crash in freshly scaffolded projects.

Also adds `scripts/sync-versions.mjs` — a Node ESM utility that reads
workspace `package.json` versions and rewrites the VERSIONS constant
automatically. Run `node scripts/sync-versions.mjs` before cutting releases
to prevent version drift.
19 changes: 19 additions & 0 deletions .changeset/fix-types-prebuild-plugin-zod-compat.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
---
"@stackwright/types": patch
---

fix(types): remove zod internals from PrebuildPlugin public interface

`PrebuildPlugin.configSchema` was typed as `z.ZodSchema` and
`contentItemSchemas` as `z.ZodTypeAny[]`. These zod-version-specific
types bled into the published `.d.ts`, causing TypeScript errors in Pro
packages that implemented `PrebuildPlugin` when their installed zod version
differed from what `@stackwright/types` was built with.

Both fields now use a local structural `ZodLike` interface
(`{ safeParse(data: unknown): { success: boolean; error?: unknown } }`)
which any real Zod schema satisfies via duck-typing. Existing plugin
implementations are unaffected.

This is the same fix applied to `@stackwright/core`'s `ContentTypeEntry`
in the companion changeset.
31 changes: 31 additions & 0 deletions .changeset/pre.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
{
"mode": "pre",
"tag": "alpha",
"initialVersions": {
"stackwright-docs": "0.1.3",
"@stackwright/build-scripts": "0.6.0",
"@stackwright/cli": "0.8.2",
"@stackwright/collections": "0.1.0",
"@stackwright/core": "0.8.1",
"@stackwright/e2e": "0.3.0",
"@stackwright/hooks-registry": "0.1.0",
"@stackwright/icons": "0.5.1",
"launch-stackwright": "0.2.2",
"@stackwright/maplibre": "2.0.1",
"@stackwright/mcp": "0.4.2",
"@stackwright/nextjs": "0.5.0",
"@stackwright/otters": "0.2.0",
"@stackwright/sbom-generator": "0.2.0",
"@stackwright/scaffold-core": "0.3.0",
"@stackwright/themes": "0.5.2",
"@stackwright/types": "1.3.0",
"@stackwright/ui-shadcn": "0.1.2"
},
"changesets": [
"fix-cli-bundle-workspace-deps",
"fix-core-dts-zod-compat",
"fix-scaffold-template-versions",
"fix-types-prebuild-plugin-zod-compat",
"zodlike-export-path-fix"
]
}
5 changes: 5 additions & 0 deletions .changeset/zodlike-export-path-fix.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@stackwright/types": patch
---

Export `ZodLike` from `@stackwright/types` so plugin authors can reference it by name without index-access workarounds. Also widens `ZodLike.issues[].path` from `(string | number)[]` to `PropertyKey[]` to match Zod v4's actual `$ZodIssue.path` type, fixing a nominal TypeScript incompatibility where real Zod schemas did not satisfy `ZodLike` at the type level.
16 changes: 12 additions & 4 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -126,14 +126,22 @@ jobs:
- name: Back-merge into dev
if: steps.check.outputs.skip != 'true'
run: |
git fetch origin dev
git checkout dev
git pull origin dev
# -X theirs: main's graduated versions win over dev's stale alphas
git merge main -X theirs --no-edit -m "chore: back-merge main after release [skip ci]"
# Re-enter prerelease mode so the next dev push produces alphas
# Rebase dev's unique commits onto main for clean, linear history.
# Using rebase (instead of merge) prevents phantom commits from
# accumulating in dev's ancestry — which previously caused dev→main
# PRs to show dozens of already-released commits.
#
# -X ours: when conflicts arise (e.g. version numbers in package.json),
# prefer main's graduated stable versions over dev's stale alpha versions.
git rebase origin/main -X ours
# Re-enter prerelease mode so the next dev push produces alphas.
if [ ! -f ".changeset/pre.json" ]; then
pnpm changeset pre enter alpha
git add .changeset/pre.json
git commit -m "chore: re-enter prerelease mode after back-merge [skip ci]"
fi
git push origin dev
# Force push is required after a rebase to rewrite dev's remote history.
git push origin dev --force-with-lease
15 changes: 15 additions & 0 deletions examples/stackwright-docs/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,20 @@
# stackwright-docs

## 0.1.5-alpha.1

### Patch Changes

- @stackwright/core@0.8.3-alpha.1
- @stackwright/nextjs@0.5.2-alpha.1

## 0.1.5-alpha.0

### Patch Changes

- Updated dependencies [5cfa88e]
- @stackwright/core@0.8.3-alpha.0
- @stackwright/nextjs@0.5.2-alpha.0

## 0.1.4

### Patch Changes
Expand Down
2 changes: 1 addition & 1 deletion examples/stackwright-docs/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "stackwright-docs",
"version": "0.1.4",
"version": "0.1.5-alpha.1",
"private": true,
"scripts": {
"prebuild": "stackwright-prebuild",
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,7 @@
"next": ">=16.1.7",
"hono": ">=4.12.14",
"@hono/node-server": ">=1.19.10",
"basic-ftp": ">=5.3.0",
"basic-ftp": ">=5.3.1",
"express-rate-limit": ">=8.2.2",
"uuid": ">=14.0.0"
},
Expand Down
14 changes: 14 additions & 0 deletions packages/build-scripts/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,19 @@
# @stackwright/build-scripts

## 0.7.1-alpha.1

### Patch Changes

- Updated dependencies [21ed937]
- @stackwright/types@1.4.1-alpha.1

## 0.7.1-alpha.0

### Patch Changes

- Updated dependencies [5cfa88e]
- @stackwright/types@1.4.1-alpha.0

## 0.7.0

### Minor Changes
Expand Down
5 changes: 3 additions & 2 deletions packages/build-scripts/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@stackwright/build-scripts",
"version": "0.7.0",
"version": "0.7.1-alpha.1",
"description": "Build-time scripts for Stackwright projects (prebuild image processing, YAML compilation)",
"license": "MIT",
"repository": {
Expand Down Expand Up @@ -31,7 +31,8 @@
"dependencies": {
"@stackwright/sbom-generator": "workspace:*",
"@stackwright/types": "workspace:*",
"js-yaml": "^4.1.0"
"js-yaml": "^4.1.0",
"zod": "^4.3.6"
},
"devDependencies": {
"@types/js-yaml": "^4.0",
Expand Down
5 changes: 4 additions & 1 deletion packages/build-scripts/src/prebuild.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
import fs from 'fs';
import path from 'path';
import yaml from 'js-yaml';
import { z } from 'zod';
import {
siteConfigSchema,
validatePageContent,
Expand Down Expand Up @@ -1019,7 +1020,9 @@ export async function runPrebuild(options?: string | PrebuildOptions): Promise<v
: 'error';

// Collect extra content schemas and known type keys from all plugins
const extraContentSchemas = plugins.flatMap((p) => p.contentItemSchemas ?? []);
// Cast from ZodLike[] to ZodTypeAny[] — plugins always supply real Zod schemas;
// ZodLike is used only in the public API surface to avoid d.ts version coupling.
const extraContentSchemas = plugins.flatMap((p) => p.contentItemSchemas ?? []) as z.ZodTypeAny[];
const pluginKnownTypes = plugins.flatMap((p) => p.knownContentTypeKeys ?? []);

const pagesDir = path.join(projectRoot, 'pages');
Expand Down
27 changes: 27 additions & 0 deletions packages/cli/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,32 @@
# @stackwright/cli

## 0.8.4-alpha.0

### Patch Changes

- f756476: Bundle internal `@stackwright/*` workspace dependencies into the CLI binary via tsup `noExternal`. This fixes `ERR_PNPM_WORKSPACE_PKG_NOT_FOUND` when installing `@stackwright/cli` via `pnpm dlx` outside a monorepo. Also adds a `prepublishOnly` guard to catch any future `workspace:*` leakage before publish.
- 5cfa88e: fix(cli): update stale scaffold template package versions

`buildPackageJson()` in `template-processor.ts` was pinning scaffolded
projects to package versions that were 4+ releases behind:
- `@stackwright/core`: `^0.7.0` → `^0.8.0`
- `@stackwright/nextjs`: `^0.3.1` → `^0.5.0`
- `@stackwright/icons`: `^0.3.0` → `^0.5.0`
- `@stackwright/build-scripts`: `^0.4.0` → `^0.7.0` ← **critical**
- `@stackwright/ui-shadcn`: `^0.1.0` → `^0.1.2`
- `@stackwright/otters`: `^0.2.0-alpha.0` → `^0.2.0`

The `build-scripts` version was the critical failure: the plugin API
(`PrebuildPlugin`, `beforeBuild`, `contentItemSchemas`) was introduced in
0.5.0, but scaffolded projects installed 0.4.0 — a version that has no
plugin system at all. This caused Pro plugin hooks to silently fail or
crash in freshly scaffolded projects.

Also adds `scripts/sync-versions.mjs` — a Node ESM utility that reads
workspace `package.json` versions and rewrites the VERSIONS constant
automatically. Run `node scripts/sync-versions.mjs` before cutting releases
to prevent version drift.

## 0.8.3

### Patch Changes
Expand Down
15 changes: 8 additions & 7 deletions packages/cli/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@stackwright/cli",
"version": "0.8.3",
"version": "0.8.4-alpha.0",
"description": "CLI for Stackwright framework",
"license": "MIT",
"repository": {
Expand Down Expand Up @@ -28,15 +28,11 @@
"build": "tsup",
"dev": "tsup --watch",
"test": "vitest run",
"test:coverage": "vitest run --coverage"
"test:coverage": "vitest run --coverage",
"prepublishOnly": "node -e \"const p=require('./package.json');const fields=[...Object.values(p.dependencies||{}),...Object.values(p.peerDependencies||{})];const bad=fields.filter(v=>String(v).includes('workspace:'));if(bad.length){console.error('ERR: workspace: specifiers found in publishable dep fields:',bad);process.exit(1)}\""
},
"dependencies": {
"@inquirer/prompts": "^8.3.0",
"@stackwright/build-scripts": "workspace:*",
"@stackwright/sbom-generator": "workspace:*",
"@stackwright/scaffold-core": "workspace:*",
"@stackwright/themes": "workspace:*",
"@stackwright/types": "workspace:*",
"chalk": "^5.6.2",
"commander": "^14.0.3",
"fs-extra": "^11.3",
Expand All @@ -52,6 +48,11 @@
}
},
"devDependencies": {
"@stackwright/build-scripts": "workspace:*",
"@stackwright/sbom-generator": "workspace:*",
"@stackwright/scaffold-core": "workspace:*",
"@stackwright/themes": "workspace:*",
"@stackwright/types": "workspace:*",
"@types/fs-extra": "^11.0",
"@types/js-yaml": "^4.0",
"@types/node": "^25.4",
Expand Down
7 changes: 1 addition & 6 deletions packages/cli/src/commands/prebuild.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { Command } from 'commander';
import { runPrebuild } from '@stackwright/build-scripts';
import { outputResult, outputError } from '../utils/json-output';

// ---------------------------------------------------------------------------
Expand All @@ -14,12 +15,6 @@ export interface PrebuildResult {
}

export function runPrebuildCommand(projectRoot = process.cwd()): PrebuildResult {
// Import here to avoid triggering the auto-invoke guard at module load time.
// The guard `if (require.main === module)` in prebuild.ts prevents auto-run,
// but we keep the import lazy for clarity.
const { runPrebuild } = require('@stackwright/build-scripts') as {
runPrebuild: (root?: string) => void;
};
runPrebuild(projectRoot);
return { success: true, processed: -1, images: -1 };
}
Expand Down
15 changes: 7 additions & 8 deletions packages/cli/src/commands/sbom.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,12 @@
import { Command } from 'commander';
import path from 'path';
import fs from 'fs';
import {
createSBOM,
validateSPDX,
validateCycloneDX,
validateBuildManifest,
} from '@stackwright/sbom-generator';
import { outputResult, outputError } from '../utils/json-output';

/**
Expand Down Expand Up @@ -33,8 +39,6 @@ export interface SBOMGenerateResult {
async function generateSBOM(options: SBOMGenerateOptions = {}): Promise<SBOMGenerateResult> {
const projectRoot = options.projectRoot ?? process.cwd();

const { createSBOM } = await import('@stackwright/sbom-generator');

const formats = (options.formats as ('spdx' | 'cyclonedx' | 'build-manifest')[]) ?? [
'spdx',
'cyclonedx',
Expand Down Expand Up @@ -78,9 +82,6 @@ export interface SBOMValidateResult {
}

async function validateSBOM(options: SBOMValidateOptions): Promise<SBOMValidateResult> {
const { validateSPDX, validateCycloneDX, validateBuildManifest } =
await import('@stackwright/sbom-generator');

const inputPath = path.resolve(options.inputFile);

if (!fs.existsSync(inputPath)) {
Expand Down Expand Up @@ -139,9 +140,7 @@ export interface SBOMDiffResult {
changed: string[];
}

async function diffSBOM(_options: SBOMDiffOptions): Promise<SBOMDiffResult> {
void (await import('@stackwright/sbom-generator'));

async function diffSBOM(options: SBOMDiffOptions): Promise<SBOMDiffResult> {
const oldPath = path.resolve(options.oldFile);
const newPath = path.resolve(options.newFile);

Expand Down
12 changes: 6 additions & 6 deletions packages/cli/src/utils/template-processor.ts
Original file line number Diff line number Diff line change
Expand Up @@ -223,13 +223,13 @@ async function collectFiles(dir: string, base: string = ''): Promise<string[]> {
export function buildPackageJson(projectName: string, useWorkspaceDeps: boolean = false): object {
const VERSIONS = {
tailwindcss: '^4.1.11',
// Stackwright packages — pinned to current stable for reproducibility
swCore: '^0.7.0',
swNextjs: '^0.3.1',
swIcons: '^0.3.0',
swBuildScripts: '^0.4.0',
// Stackwright packages — keep in sync with workspace via scripts/sync-versions.mjs
swCore: '^0.8.0',
swNextjs: '^0.5.0',
swIcons: '^0.5.0',
swBuildScripts: '^0.7.0',
swUiShadcn: '^0.1.0',
swOtters: '^0.2.0-alpha.0',
swOtters: '^0.2.0',
// Third-party
jsYaml: '^4.1.1',
next: '^16.1.6',
Expand Down
Loading
Loading