chore: fix monorepo build pipeline and migrate shared to built package (#1056)

* chore: fix monorepo build pipeline and migrate shared to built package

- Root package.json: add workspace scripts (dev, build, test, test:cov, test:e2e)
  that delegate to actual scripts in shared/server/client workspaces
- shared: add tsup build step (CJS + ESM dual output, .d.ts); consumers now import
  from the built dist instead of raw TS source via path aliases
- server: replace tsc-alias with tsconfig-paths (tsc-alias mangled node_modules
  paths); fix MCP SDK path aliases to point to root node_modules (../node_modules)
- server/scripts/dev.mjs: delay node --watch until tsc -w signals first-pass done,
  eliminating the spurious restart on every dev startup
- client/vite.config.js + vitest.config.ts: remove @trek/shared path alias (no longer
  needed now that shared is a proper package)
- Consolidate package-lock.json at the workspace root; drop per-workspace lock files

* chore: fix test script to reflect root package.json

* chore: add missing lint and prettier script in root package.json

* fix(ci): build shared before tests; fix vitest MCP SDK alias paths

vitest.config.ts aliases pointed at ./node_modules/ (server-local) but
packages are hoisted to the root node_modules/ in the npm workspace —
changed to ../node_modules/.

CI jobs now install and build shared before running server/client tests
so that @trek/shared's dist/ exists when vitest resolves the package.

* fix(docker): update Dockerfile and CI for monorepo workspace structure

Dockerfile:
- Add shared-builder stage that produces @trek/shared dist before
  client and server stages need it
- Each build stage carries root package.json + package-lock.json so npm
  can resolve @trek/shared as a workspace dependency
- Production stage installs via workspace context (npm ci --workspace=server
  --omit=dev) so node_modules/@trek/shared symlinks to shared/dist correctly
- Copy server/tsconfig.json into the image so tsconfig-paths/register can
  find the MCP SDK path aliases at runtime
- CMD cds into /app/server before starting node so tsconfig-paths baseUrl
  resolves and ../node_modules points to /app/node_modules
- Remove mkdir for /app/server (now a real dir); keep symlinks for uploads/data

docker.yml version-bump:
- Replace manual per-workspace cd+npm-version calls with single:
  npm version --workspaces --include-workspace-root --no-git-tag-version
  (mirrors the version:* scripts in root package.json)
- git add now references root package-lock.json; adds shared/package.json

.dockerignore: add shared/dist
package.json: fix version:prerelease preid (alpha → pre)

* fix(tests): use in-memory SQLite per worker in test mode

vitest pool:forks spawns parallel worker processes that all called
initDb() on the same data/travel.db, causing SQLite "database is locked"
and "duplicate column name" races.

When NODE_ENV=test each fork now gets an isolated :memory: DB so migrations
run independently with no file contention.

* chore(ci): add ACT guards to skip DockerHub steps in local act runs

act sets ACT=true automatically. Guards added:
- docker login: if: ${{ !env.ACT }}
- build outputs: type=docker (local load) when ACT, push-by-digest when CI
- digest export/upload: if: ${{ !env.ACT }}
- merge job: if: ${{ !env.ACT }}
- release-helm job (docker.yml): if: ${{ !env.ACT }}
- version-bump git push (docker.yml): wrapped in [ -z "$ACT" ] shell guard

Run locally with:
  ./bin/act -j build -W .github/workflows/docker.yml \
    -P ubuntu-latest=catthehacker/ubuntu:act-latest

* fix(ci): move ACT guards to step level; add guards to security.yml

env context is invalid in job-level if conditions — moved all ACT
guards down to individual steps. Also guards docker login + scout
in security.yml so act can run the build-only part of that workflow.

* fix(ci): skip git fetch and tag logic in act (no remote access in local containers)

* Revert "fix(ci): skip git fetch and tag logic in act (no remote access in local containers)"

This reverts commit 67cf290cda.

* Revert "fix(ci): move ACT guards to step level; add guards to security.yml"

This reverts commit f92b95e054.

* Revert "chore(ci): add ACT guards to skip DockerHub steps in local act runs"

This reverts commit 797183de08.

* fix(docker): add musl optional deps so alpine builds find native rollup/sharp binaries

npm prunes libc-constrained optional deps to the host libc (glibc) when
generating the lockfile, leaving no musl entry for Alpine containers.
Declaring the x64/arm64 musl variants as explicit root optionalDependencies
forces them into the lockfile so npm ci on Alpine can install them.

Covers shared-builder (tsup/rollup) and client-builder (vite/rollup + sharp
icon generation) for both linux/amd64 and linux/arm64 CI targets.

* fix(docker): copy client dist into server/public so the server resolves static files correctly

The server runs from /app/server and serves static files relative to that
directory, so the client build output must land at /app/server/public, not /app/public.
This commit is contained in:
Julien G.
2026-05-25 21:44:58 +02:00
committed by GitHub
parent db5c403239
commit c130ed41be
25 changed files with 19782 additions and 20159 deletions
+1
View File
@@ -2,6 +2,7 @@ node_modules
client/node_modules
server/node_modules
client/dist
shared/dist
data
uploads
.git
+3 -4
View File
@@ -102,16 +102,15 @@ jobs:
echo "VERSION=$NEW_VERSION" >> $GITHUB_OUTPUT
echo "$STABLE → $NEW_VERSION ($BUMP)"
# Update package.json files and Helm chart
cd server && npm version "$NEW_VERSION" --no-git-tag-version && cd ..
cd client && npm version "$NEW_VERSION" --no-git-tag-version && cd ..
# Update all workspace + root package.json files and the root lockfile in one shot
npm version "$NEW_VERSION" --workspaces --include-workspace-root --no-git-tag-version
sed -i "s/^version: .*/version: $NEW_VERSION/" charts/trek/Chart.yaml
sed -i "s/^appVersion: .*/appVersion: \"$NEW_VERSION\"/" charts/trek/Chart.yaml
# Commit and tag
git config user.name "github-actions[bot]"
git config user.email "github-actions[bot]@users.noreply.github.com"
git add server/package.json server/package-lock.json client/package.json client/package-lock.json charts/trek/Chart.yaml
git add package.json package-lock.json server/package.json client/package.json shared/package.json charts/trek/Chart.yaml
git commit -m "chore: bump version to $NEW_VERSION [skip ci]"
git tag "v$NEW_VERSION"
git push origin main --follow-tags
+18 -12
View File
@@ -22,12 +22,12 @@ jobs:
- uses: actions/setup-node@v6
with:
node-version: 22
node-version: 24
cache: npm
cache-dependency-path: shared/package-lock.json
cache-dependency-path: package-lock.json
- name: Install dependencies
run: cd shared && npm ci
run: npm ci --workspace shared
- name: Typecheck
run: cd shared && npm run typecheck
@@ -44,19 +44,22 @@ jobs:
- uses: actions/setup-node@v6
with:
node-version: 22
node-version: 24
cache: npm
cache-dependency-path: server/package-lock.json
cache-dependency-path: package-lock.json
- name: Install dependencies
run: cd server && npm ci
run: npm ci --workspace shared && npm ci --workspace server
- name: Build (tsc + tsc-alias -> dist)
- name: Build shared
run: npm run build --workspace=shared
- name: Build server (tsc -> dist)
run: cd server && npm run build
- name: Typecheck (informational)
# Legacy code still has pre-existing type errors; this surfaces them
# without blocking the migration. Ratchet to blocking once cleaned up.
# Pre-existing type errors in the NestJS rewrite; surfaces them without
# blocking CI. Ratchet to blocking once the legacy code is cleaned up.
continue-on-error: true
run: cd server && npm run typecheck
@@ -80,12 +83,15 @@ jobs:
- uses: actions/setup-node@v6
with:
node-version: 22
node-version: 24
cache: npm
cache-dependency-path: client/package-lock.json
cache-dependency-path: package-lock.json
- name: Install dependencies
run: cd client && npm ci
run: npm ci --workspace shared && npm ci --workspace client
- name: Build shared
run: npm run build --workspace=shared
- name: Run tests
run: cd client && npm run test:coverage
+1
View File
@@ -4,6 +4,7 @@ node_modules/
# Build output
client/dist/
server/dist/
shared/dist/
server/public/*
!server/public/.gitkeep
+46 -26
View File
@@ -1,41 +1,60 @@
# Stage 1: Build React client
FROM node:24-alpine AS client-builder
WORKDIR /app/client
COPY client/package*.json ./
RUN npm ci
COPY client/ ./
RUN npm run build
# ── Stage 1: shared ──────────────────────────────────────────────────────────
FROM node:24-alpine AS shared-builder
WORKDIR /app
COPY package.json package-lock.json ./
COPY shared/package.json ./shared/
RUN npm ci --workspace=shared
COPY shared/ ./shared/
RUN npm run build --workspace=shared
# Stage 2: Build server (TypeScript -> dist via tsc + tsc-alias)
# --ignore-scripts: tsc only transpiles, so we skip native builds (better-sqlite3)
# here; the production stage builds the native module.
# ── Stage 2: client ──────────────────────────────────────────────────────────
FROM node:24-alpine AS client-builder
WORKDIR /app
COPY package.json package-lock.json ./
COPY shared/package.json ./shared/
COPY client/package.json ./client/
RUN npm ci --workspace=client
COPY --from=shared-builder /app/shared/dist ./shared/dist
COPY client/ ./client/
RUN npm run build --workspace=client
# ── Stage 3: server ──────────────────────────────────────────────────────────
# --ignore-scripts skips native builds (better-sqlite3); they happen in the production stage.
FROM node:24-alpine AS server-builder
WORKDIR /app
COPY server/package*.json ./
RUN npm ci --ignore-scripts
COPY server/ ./
RUN npm run build
COPY package.json package-lock.json ./
COPY shared/package.json ./shared/
COPY server/package.json ./server/
RUN npm ci --workspace=server --ignore-scripts
COPY --from=shared-builder /app/shared/dist ./shared/dist
COPY server/ ./server/
RUN npm run build --workspace=server
# Stage 3: Production server (runs the compiled JS — NestJS DI needs the
# decorator metadata that tsc emits; the old tsx runtime did not).
# ── Stage 4: production runtime ──────────────────────────────────────────────
FROM node:24-alpine
WORKDIR /app
# Timezone support + native deps (better-sqlite3 needs build tools)
COPY server/package*.json ./
# Workspace manifests only — source never enters this stage.
COPY package.json package-lock.json ./
COPY shared/package.json ./shared/
COPY server/package.json ./server/
# better-sqlite3 native addon requires build tools; purged after install.
RUN apk add --no-cache tzdata dumb-init su-exec python3 make g++ && \
npm ci --production && \
rm package-lock.json && \
npm ci --workspace=server --omit=dev && \
apk del python3 make g++ && \
rm -rf /usr/local/lib/node_modules/npm /usr/local/bin/npm /usr/local/bin/npx
COPY --from=server-builder /app/dist ./dist
COPY --from=client-builder /app/client/dist ./public
COPY --from=client-builder /app/client/public/fonts ./public/fonts
COPY --from=server-builder /app/server/dist ./server/dist
# tsconfig-paths/register reads this at runtime to resolve MCP SDK paths.
COPY server/tsconfig.json ./server/
COPY --from=shared-builder /app/shared/dist ./shared/dist
COPY --from=client-builder /app/client/dist ./server/public
COPY --from=client-builder /app/client/public/fonts ./server/public/fonts
RUN mkdir -p /app/data/logs /app/uploads/files /app/uploads/covers /app/uploads/avatars /app/uploads/photos && \
mkdir -p /app/server && ln -s /app/uploads /app/server/uploads && ln -s /app/data /app/server/data && \
ln -s /app/uploads /app/server/uploads && \
ln -s /app/data /app/server/data && \
chown -R node:node /app
ENV NODE_ENV=production
@@ -49,4 +68,5 @@ HEALTHCHECK --interval=30s --timeout=5s --start-period=15s --retries=3 \
CMD wget -qO- http://localhost:3000/api/health || exit 1
ENTRYPOINT ["dumb-init", "--"]
CMD ["sh", "-c", "chown -R node:node /app/data /app/uploads 2>/dev/null || true; exec su-exec node node dist/index.js"]
# cd into server/ so tsconfig-paths/register finds tsconfig.json and ../node_modules resolves correctly.
CMD ["sh", "-c", "chown -R node:node /app/data /app/uploads 2>/dev/null || true; cd /app/server && exec su-exec node node --require tsconfig-paths/register dist/index.js"]
+27
View File
@@ -0,0 +1,27 @@
{
"printWidth": 120,
"useTabs": false,
"tabWidth": 2,
"trailingComma": "es5",
"semi": true,
"singleQuote": true,
"bracketSpacing": true,
"arrowParens": "always",
"jsxSingleQuote": false,
"bracketSameLine": false,
"endOfLine": "lf",
"plugins": [
"prettier-plugin-organize-imports",
"@trivago/prettier-plugin-sort-imports",
"prettier-plugin-tailwindcss"
],
"importOrder": [
"^[a-zA-Z]",
"^@/.*"
],
"importOrderSeparation": true,
"importOrderParserPlugins": [
"typescript",
"decorators-legacy"
]
}
-11021
View File
File diff suppressed because it is too large Load Diff
+15 -3
View File
@@ -1,5 +1,5 @@
{
"name": "trek-client",
"name": "@trek/client",
"version": "3.0.22",
"private": true,
"type": "module",
@@ -12,9 +12,13 @@
"test:unit": "vitest run tests/unit",
"test:integration": "vitest run tests/integration src/**/*.test.{ts,tsx}",
"test:watch": "vitest",
"test:coverage": "vitest run --coverage"
"test:coverage": "vitest run --coverage",
"lint": "eslint .",
"format": "prettier --write \"src/**/*.tsx\" \"src/**/*.css\"",
"format:check": "prettier --check \"src/**/*.tsx\" \"src/**/*.css\""
},
"dependencies": {
"@trek/shared": "*",
"@react-pdf/renderer": "^4.3.2",
"axios": "^1.6.7",
"dexie": "^4.4.2",
@@ -58,6 +62,14 @@
"typescript": "^6.0.2",
"vite": "^5.1.4",
"vite-plugin-pwa": "^0.21.0",
"vitest": "^3.2.4"
"vitest": "^3.2.4",
"@trivago/prettier-plugin-sort-imports": "^6.0.2",
"prettier": "^3.8.3",
"prettier-plugin-organize-imports": "^4.3.0",
"prettier-plugin-tailwindcss": "^0.8.0",
"eslint": "^10.2.1",
"eslint-config-flat-gitignore": "^2.3.0",
"eslint-plugin-react-hooks": "^7.1.1",
"eslint-plugin-react-refresh": "^0.5.2"
}
}
-10
View File
@@ -1,7 +1,6 @@
import { defineConfig } from 'vite'
import react from '@vitejs/plugin-react'
import { VitePWA } from 'vite-plugin-pwa'
import { fileURLToPath } from 'node:url'
export default defineConfig({
plugins: [
@@ -89,15 +88,6 @@ export default defineConfig({
},
}),
],
resolve: {
alias: {
// @trek/shared — Zod contract package (dev: resolved to TS source).
'@trek/shared': fileURLToPath(new URL('../shared/src/index.ts', import.meta.url)),
},
// @trek/shared imports zod from its own source; it lives outside this root,
// so pin zod to the client's copy (one instance, resolvable from anywhere).
dedupe: ['zod'],
},
build: {
sourcemap: false,
modulePreload: { polyfill: true },
-11
View File
@@ -1,19 +1,8 @@
import { defineConfig } from 'vitest/config';
import react from '@vitejs/plugin-react';
import { fileURLToPath } from 'node:url';
export default defineConfig({
plugins: [react()],
resolve: {
alias: {
// @trek/shared — Zod contract package (tests resolve it to TS source,
// mirroring the alias in vite.config.js used by the dev server / build).
'@trek/shared': fileURLToPath(new URL('../shared/src/index.ts', import.meta.url)),
},
// Mirror vite.config.js: keep a single zod instance resolvable from the
// shared source, which lives outside this project root.
dedupe: ['zod'],
},
test: {
root: '.',
globals: true,
+19492
View File
File diff suppressed because it is too large Load Diff
+36
View File
@@ -0,0 +1,36 @@
{
"name": "@trek/root",
"private": true,
"version": "3.0.22",
"workspaces": [
"client",
"server",
"shared"
],
"scripts": {
"version:major": "npm version major --workspaces --include-workspace-root --no-git-tag-version",
"version:minor": "npm version minor --workspaces --include-workspace-root --no-git-tag-version",
"version:patch": "npm version patch --workspaces --include-workspace-root --no-git-tag-version",
"version:premajor": "npm version premajor --preid=rc --workspaces --include-workspace-root --no-git-tag-version",
"version:preminor": "npm version preminor --preid=beta --workspaces --include-workspace-root --no-git-tag-version",
"version:prepatch": "npm version prepatch --preid=alpha --workspaces --include-workspace-root --no-git-tag-version",
"version:prerelease": "npm version prerelease --preid=pre --workspaces --include-workspace-root --no-git-tag-version",
"dev": "npm run build --workspace=shared && concurrently --names shared,server,client \"npm run build:watch --workspace=shared\" \"npm run dev --workspace=server\" \"npm run dev --workspace=client\"",
"build": "npm run build --workspace=shared && npm run build --workspace=server && npm run build --workspace=client",
"test": "npm run test --workspace=shared && npm run test --workspace=server && npm run test --workspace=client",
"test:cov": "npm run test:coverage --workspace=server && npm run test:coverage --workspace=client",
"test:e2e": "npm run test:e2e --workspace=server",
"lint": "npm run lint --workspace=shared && npm run lint --workspace=server && npm run lint --workspace=client",
"format": "npm run format --workspace=shared && npm run format --workspace=server && npm run format --workspace=client",
"format:check": "npm run format:check --workspace=shared && npm run format:check --workspace=server && npm run format:check --workspace=client"
},
"devDependencies": {
"concurrently": "^9.2.1"
},
"optionalDependencies": {
"@rollup/rollup-linux-x64-musl": "4.60.4",
"@rollup/rollup-linux-arm64-musl": "4.60.4",
"@img/sharp-linuxmusl-x64": "0.33.5",
"@img/sharp-linuxmusl-arm64": "0.33.5"
}
}
+18
View File
@@ -0,0 +1,18 @@
{
"printWidth": 120,
"singleQuote": true,
"trailingComma": "all",
"plugins": [
"prettier-plugin-organize-imports",
"@trivago/prettier-plugin-sort-imports"
],
"importOrder": [
"^[a-zA-Z]",
"^@/.*"
],
"importOrderSeparation": true,
"importOrderParserPlugins": [
"typescript",
"decorators-legacy"
]
}
-7389
View File
File diff suppressed because it is too large Load Diff
+16 -5
View File
@@ -1,13 +1,16 @@
{
"name": "trek-server",
"name": "@trek/server",
"version": "3.0.22",
"main": "src/index.ts",
"scripts": {
"start": "node dist/index.js",
"start": "node --require tsconfig-paths/register dist/index.js",
"dev": "node scripts/dev.mjs",
"build": "node scripts/build.mjs",
"start:prod": "node dist/index.js",
"typecheck": "tsc -p tsconfig.build.json --noEmit",
"start:prod": "node --require tsconfig-paths/register dist/index.js",
"typecheck": "tsc --noEmit",
"format": "prettier --write \"src/**/*.ts\" \"test/**/*.ts\"",
"format:check": "prettier --check \"src/**/*.ts\" \"test/**/*.ts\"",
"lint": "eslint \"{src,apps,libs,test}/**/*.ts\" --fix",
"test": "vitest run",
"test:watch": "vitest",
"test:unit": "vitest run tests/unit",
@@ -18,6 +21,8 @@
"test:coverage": "vitest run --coverage"
},
"dependencies": {
"@trek/shared": "*",
"tsconfig-paths": "^4.2.0",
"@modelcontextprotocol/sdk": "^1.28.0",
"@nestjs/common": "^11.1.24",
"@nestjs/core": "^11.1.24",
@@ -60,6 +65,13 @@
"file-type": "^21.3.4"
},
"devDependencies": {
"@trivago/prettier-plugin-sort-imports": "^6.0.2",
"eslint-config-prettier": "^10.0.1",
"eslint-plugin-prettier": "^5.2.2",
"prettier": "^3.8.3",
"prettier-plugin-organize-imports": "^4.3.0",
"eslint": "^9.18.0",
"eslint-config-flat-gitignore": "^2.3.0",
"@nestjs/testing": "^11.1.24",
"@swc/core": "^1.15.40",
"@types/archiver": "^7.0.0",
@@ -82,7 +94,6 @@
"@vitest/coverage-v8": "^3.2.4",
"nodemon": "^3.1.0",
"supertest": "^7.2.2",
"tsc-alias": "^1.8.17",
"tz-lookup": "^6.1.25",
"unplugin-swc": "^1.5.9",
"vitest": "^3.2.4"
+1 -6
View File
@@ -1,14 +1,9 @@
import { execSync } from 'node:child_process';
// tsc emits JS even with type errors (noEmitOnError:false), but still exits
// non-zero to report them. We must run tsc-alias regardless, so run tsc in a
// try/catch and always proceed to the path-rewrite step.
// Type correctness is enforced separately via `npm run typecheck`.
try {
execSync('tsc -p tsconfig.build.json', { stdio: 'inherit' });
} catch {
console.warn('[build] tsc reported type errors — emitting anyway (gated by `npm run typecheck`).');
}
execSync('tsc-alias -p tsconfig.build.json', { stdio: 'inherit' });
console.log('[build] dist ready (path aliases rewritten).');
console.log('[build] dist ready.');
+24 -14
View File
@@ -1,22 +1,32 @@
import { execSync, spawn } from 'node:child_process';
// Dev runtime for the co-hosted NestJS + legacy Express server.
// NestJS DI needs decorator metadata, which the old tsx/esbuild runtime does not
// emit — so dev runs the tsc build with watchers (same toolchain as prod `dist`).
// Initial build first so `node --watch dist/index.js` has something to start.
console.log('[dev] initial build...');
execSync('node scripts/build.mjs', { stdio: 'inherit' });
const watchers = [
['npx', ['tsc', '-w', '-p', 'tsconfig.build.json', '--preserveWatchOutput']],
['npx', ['tsc-alias', '-w', '-p', 'tsconfig.build.json']],
['node', ['--watch', 'dist/index.js']],
];
const children = watchers.map(([cmd, args]) =>
spawn(cmd, args, { stdio: 'inherit', shell: true }),
);
const children = [];
const stop = () => { children.forEach((c) => { try { c.kill(); } catch {} }); process.exit(0); };
process.on('SIGINT', stop);
process.on('SIGTERM', stop);
// Start tsc -w and wait for its first "Watching for file changes." before launching
// node --watch, so the initial tsc compilation doesn't trigger a spurious restart.
const tsc = spawn('npx', ['tsc', '-w', '-p', 'tsconfig.build.json', '--preserveWatchOutput'], {
stdio: ['ignore', 'pipe', 'inherit'],
shell: true,
});
children.push(tsc);
let nodeProc = null;
let ready = false;
tsc.stdout.on('data', (chunk) => {
process.stdout.write(chunk);
if (!ready && chunk.toString().includes('Watching for file changes')) {
ready = true;
nodeProc = spawn('node', ['--require', 'tsconfig-paths/register', '--watch', 'dist/index.js'], {
stdio: 'inherit',
shell: true,
});
children.push(nodeProc);
}
});
+13 -5
View File
@@ -6,12 +6,20 @@ import { runMigrations } from './migrations';
import { runSeeds } from './seeds';
import { Place, Tag } from '../types';
const dataDir = path.join(__dirname, '../../data');
if (!fs.existsSync(dataDir)) {
fs.mkdirSync(dataDir, { recursive: true });
}
// In test mode each vitest worker gets an isolated in-memory DB so that
// parallel forks can't race on the same file or share migration state.
const isTest = process.env.NODE_ENV === 'test';
const dbPath = path.join(dataDir, 'travel.db');
let dbPath: string;
if (isTest) {
dbPath = ':memory:';
} else {
const dataDir = path.join(__dirname, '../../data');
if (!fs.existsSync(dataDir)) {
fs.mkdirSync(dataDir, { recursive: true });
}
dbPath = path.join(dataDir, 'travel.db');
}
let _db: Database.Database | null = null;
+11 -12
View File
@@ -18,22 +18,21 @@
"allowJs": true,
"noUnusedLocals": false,
"noUnusedParameters": false,
"ignoreDeprecations": "6.0",
// The MCP SDK's package.json uses a wildcard exports pattern with extension-less targets
// (e.g. "./*": "./dist/esm/*") which TypeScript cannot resolve — it only strips .js suffixes.
// These paths manually redirect to the CJS dist until the SDK fixes its exports map.
"paths": {
"@trek/shared": ["../shared/src/index.ts"],
"@trek/shared/*": ["../shared/src/*"],
"@modelcontextprotocol/sdk/server/mcp": ["./node_modules/@modelcontextprotocol/sdk/dist/cjs/server/mcp.js"],
"@modelcontextprotocol/sdk/server/streamableHttp": ["./node_modules/@modelcontextprotocol/sdk/dist/cjs/server/streamableHttp.js"],
"@modelcontextprotocol/sdk/server/auth/router": ["./node_modules/@modelcontextprotocol/sdk/dist/cjs/server/auth/router.js"],
"@modelcontextprotocol/sdk/server/auth/handlers/authorize": ["./node_modules/@modelcontextprotocol/sdk/dist/cjs/server/auth/handlers/authorize.js"],
"@modelcontextprotocol/sdk/server/auth/handlers/register": ["./node_modules/@modelcontextprotocol/sdk/dist/cjs/server/auth/handlers/register.js"],
"@modelcontextprotocol/sdk/server/auth/provider": ["./node_modules/@modelcontextprotocol/sdk/dist/cjs/server/auth/provider.js"],
"@modelcontextprotocol/sdk/server/auth/clients": ["./node_modules/@modelcontextprotocol/sdk/dist/cjs/server/auth/clients.js"],
"@modelcontextprotocol/sdk/server/auth/errors": ["./node_modules/@modelcontextprotocol/sdk/dist/cjs/server/auth/errors.js"],
"@modelcontextprotocol/sdk/server/auth/types": ["./node_modules/@modelcontextprotocol/sdk/dist/cjs/server/auth/types.js"],
"@modelcontextprotocol/sdk/shared/auth": ["./node_modules/@modelcontextprotocol/sdk/dist/cjs/shared/auth.js"]
"@modelcontextprotocol/sdk/server/mcp": ["../node_modules/@modelcontextprotocol/sdk/dist/cjs/server/mcp.js"],
"@modelcontextprotocol/sdk/server/streamableHttp": ["../node_modules/@modelcontextprotocol/sdk/dist/cjs/server/streamableHttp.js"],
"@modelcontextprotocol/sdk/server/auth/router": ["../node_modules/@modelcontextprotocol/sdk/dist/cjs/server/auth/router.js"],
"@modelcontextprotocol/sdk/server/auth/handlers/authorize": ["../node_modules/@modelcontextprotocol/sdk/dist/cjs/server/auth/handlers/authorize.js"],
"@modelcontextprotocol/sdk/server/auth/handlers/register": ["../node_modules/@modelcontextprotocol/sdk/dist/cjs/server/auth/handlers/register.js"],
"@modelcontextprotocol/sdk/server/auth/provider": ["../node_modules/@modelcontextprotocol/sdk/dist/cjs/server/auth/provider.js"],
"@modelcontextprotocol/sdk/server/auth/clients": ["../node_modules/@modelcontextprotocol/sdk/dist/cjs/server/auth/clients.js"],
"@modelcontextprotocol/sdk/server/auth/errors": ["../node_modules/@modelcontextprotocol/sdk/dist/cjs/server/auth/errors.js"],
"@modelcontextprotocol/sdk/server/auth/types": ["../node_modules/@modelcontextprotocol/sdk/dist/cjs/server/auth/types.js"],
"@modelcontextprotocol/sdk/shared/auth": ["../node_modules/@modelcontextprotocol/sdk/dist/cjs/shared/auth.js"]
}
},
"include": ["src"],
+7 -14
View File
@@ -38,32 +38,25 @@ export default defineConfig({
},
resolve: {
alias: {
// @trek/shared — Zod contract package (tests resolve it to TS source,
// mirroring the tsconfig `paths` the tsx runtime uses).
'@trek/shared': new URL('../shared/src/index.ts', import.meta.url).pathname,
// MCP SDK's exports map uses extension-less wildcard targets that neither
// Node nor Vite can resolve. Point directly at the CJS dist files.
// Paths are relative to the monorepo root (packages are hoisted there).
'@modelcontextprotocol/sdk/server/mcp': new URL(
'./node_modules/@modelcontextprotocol/sdk/dist/cjs/server/mcp.js',
'../node_modules/@modelcontextprotocol/sdk/dist/cjs/server/mcp.js',
import.meta.url
).pathname,
'@modelcontextprotocol/sdk/server/streamableHttp': new URL(
'./node_modules/@modelcontextprotocol/sdk/dist/cjs/server/streamableHttp.js',
'../node_modules/@modelcontextprotocol/sdk/dist/cjs/server/streamableHttp.js',
import.meta.url
).pathname,
'@modelcontextprotocol/sdk/inMemory': new URL(
'./node_modules/@modelcontextprotocol/sdk/dist/cjs/inMemory.js',
'../node_modules/@modelcontextprotocol/sdk/dist/cjs/inMemory.js',
import.meta.url
).pathname,
'@modelcontextprotocol/sdk/client/index': new URL(
'./node_modules/@modelcontextprotocol/sdk/dist/cjs/client/index.js',
'../node_modules/@modelcontextprotocol/sdk/dist/cjs/client/index.js',
import.meta.url
).pathname,
},
// The server build emits @trek/shared next to its source (shared/src/*.js,
// needed by the prod dist via tsc-alias). Vite's default extension order
// prefers .js over .ts, so after a build the tests would load that compiled
// CJS instead of the source — and its `require('zod')` is unresolvable from
// the shared/ dir on CI (only server deps are installed there). Resolve .ts
// first so tests always run the source, whose zod import resolves via Vite.
extensions: ['.ts', '.mts', '.mjs', '.js', '.cts', '.cjs', '.tsx', '.jsx', '.json'],
},
});
+17
View File
@@ -0,0 +1,17 @@
{
"singleQuote": true,
"trailingComma": "all",
"plugins": [
"prettier-plugin-organize-imports",
"@trivago/prettier-plugin-sort-imports"
],
"importOrder": [
"^[a-zA-Z]",
"^@/.*"
],
"importOrderSeparation": true,
"importOrderParserPlugins": [
"typescript",
"decorators-legacy"
]
}
-1619
View File
File diff suppressed because it is too large Load Diff
+25 -7
View File
@@ -1,25 +1,43 @@
{
"name": "@trek/shared",
"version": "0.0.0",
"version": "3.0.22",
"private": true,
"description": "Shared API contracts (Zod schemas) — single source of truth for TREK server and client.",
"type": "module",
"main": "./src/index.ts",
"types": "./src/index.ts",
"main": "./dist/index.cjs",
"module": "./dist/index.js",
"types": "./dist/index.d.ts",
"exports": {
".": "./src/index.ts",
"./*": "./src/*.ts"
".": {
"types": "./dist/index.d.ts",
"import": "./dist/index.js",
"require": "./dist/index.cjs"
}
},
"scripts": {
"build": "tsup",
"build:watch": "tsup --watch",
"test": "vitest run",
"test:watch": "vitest",
"typecheck": "tsc --noEmit"
"typecheck": "tsc --noEmit",
"format": "prettier --write \"src/**/*.ts\"",
"format:check": "prettier --check \"src/**/*.ts\"",
"lint": "eslint --fix \"src/**/*.ts\""
},
"dependencies": {
"zod": "^4.3.6"
},
"devDependencies": {
"tsup": "^8.5.1",
"typescript": "^6.0.2",
"vitest": "^3.2.4"
"vitest": "^3.2.4",
"@eslint/js": "^10.0.1",
"@trivago/prettier-plugin-sort-imports": "^6.0.2",
"eslint": "^10.3.0",
"eslint-config-flat-gitignore": "^2.3.0",
"eslint-config-prettier": "^10.1.8",
"eslint-plugin-prettier": "^5.5.5",
"prettier": "3.8.3",
"prettier-plugin-organize-imports": "^4.3.0"
}
}
+2 -1
View File
@@ -10,7 +10,8 @@
"esModuleInterop": true,
"skipLibCheck": true,
"forceConsistentCasingInFileNames": true,
"noEmit": true
"noEmit": true,
"ignoreDeprecations": "6.0"
},
"include": ["src"]
}
+9
View File
@@ -0,0 +1,9 @@
import { defineConfig } from 'tsup'
export default defineConfig({
entry: ['src/index.ts'],
format: ['cjs', 'esm'],
dts: true,
clean: true,
external: ['zod'],
})