From 7a8d4d30226fde117d21d2c8d31402d34ba36f7e Mon Sep 17 00:00:00 2001 From: sjungwon03 Date: Mon, 3 Aug 2026 16:51:43 +0900 Subject: [PATCH] fix: add CJS declarations for public exports --- README.md | 2 +- docs/README.md | 2 +- docs/api/decorator-api.md | 8 ++- docs/guides/agent-builder.md | 4 +- docs/guides/composition-selection.md | 8 +-- docs/guides/core-concepts.md | 2 +- docs/guides/getting-started.md | 6 +- docs/guides/langchain-integration.md | 4 +- .../guides/petstore-policy-and-composition.md | 6 +- docs/guides/petstore-typechain-foundation.md | 4 +- docs/guides/petstore-walkthrough.md | 8 +-- docs/guides/policy.md | 4 +- docs/guides/tools-and-definitions.md | 4 +- docs/guides/typemcp-bridge.md | 4 +- package-lock.json | 12 ++-- package.json | 50 ++++++++++----- scripts/verify-legacy-consumer.mjs | 10 ++- scripts/verify-package.mjs | 62 +++++++++++++------ .../reference-documentation-contract.test.mjs | 4 +- test/release-workflow-contract.test.mjs | 7 ++- 20 files changed, 136 insertions(+), 75 deletions(-) diff --git a/README.md b/README.md index c2f8132..d6d8ee0 100644 --- a/README.md +++ b/README.md @@ -42,7 +42,7 @@ npm ci npm run verify ``` -For a consuming TypeScript application, use a Node-aware compiler configuration and do **not** enable TypeScript's legacy `experimentalDecorators` mode for these root Stage 3 examples. CommonJS legacy decorator consumers must import from `@theorvane/type-chain/legacy`, use Node16 module resolution, and await its LangChain adapters; see the [Decorator API contract](docs/api/decorator-api.md#legacy-cjs-decorators). +For a consuming TypeScript application, use a Node-aware compiler configuration and do **not** enable TypeScript's legacy `experimentalDecorators` mode for these root Stage 3 examples. CommonJS consumers can use Node16 module resolution with static imports of the root, `/langchain`, `/agent`, and `/typemcp` subpaths; the package selects matching CJS `.d.cts` declarations and `.cjs` runtime exports. CommonJS legacy decorator consumers must import decorators from `@theorvane/type-chain/legacy` and await its LangChain adapters; see the [Decorator API contract](docs/api/decorator-api.md#legacy-cjs-decorators). ```json { diff --git a/docs/README.md b/docs/README.md index 2e2fdc7..4372d7d 100644 --- a/docs/README.md +++ b/docs/README.md @@ -1,6 +1,6 @@ # TypeChain documentation -TypeChain is a decorator-first authoring layer for typed LangChain JS tools and agents. The published package is [`@theorvane/type-chain@0.2.0`](https://www.npmjs.com/package/@theorvane/type-chain). +TypeChain is a decorator-first authoring layer for typed LangChain JS tools and agents. The published package is [`@theorvane/type-chain@0.2.1`](https://www.npmjs.com/package/@theorvane/type-chain). > **Published boundary:** TypeChain provides Stage 3 tool and policy declarations, immutable definitions, LangChain adaptation, an agent builder, and an in-process TypeMCP bridge. Applications retain ownership of **models, credentials, policy enforcement, state, hosting, deployment, and cross-process MCP transport**. diff --git a/docs/api/decorator-api.md b/docs/api/decorator-api.md index 65c099c..4b52208 100644 --- a/docs/api/decorator-api.md +++ b/docs/api/decorator-api.md @@ -1,6 +1,6 @@ # Decorator API contract -`@theorvane/type-chain@0.2.0` is the current public TypeChain release. It supports standard TypeScript Stage 3 decorators and explicit runtime schemas. It does not infer schemas from TypeScript parameter types or use legacy `reflect-metadata` behavior. +`@theorvane/type-chain@0.2.1` is the current public TypeChain release. It supports standard TypeScript Stage 3 decorators and explicit runtime schemas. It does not infer schemas from TypeScript parameter types or use legacy `reflect-metadata` behavior. ## Root package @@ -144,7 +144,11 @@ class LegacyTools { ``` Use `"module": "Node16"`, `"moduleResolution": "Node16"`, and -`"experimentalDecorators": true` for CommonJS consumers. Legacy support is +`"experimentalDecorators": true` for CommonJS consumers. In the same Node16 +compilation, static imports of the root, `/langchain`, `/agent`, and `/typemcp` +subpaths select their CJS `.d.cts` declarations and `.cjs` runtime exports. +Install the relevant optional peers (`@langchain/core`, `langchain`, and/or +`@theorvane/type-mcp`) for any subpath you import. Legacy support is limited to public instance methods with string names; parameter, accessor, field, private, and symbol-named decorators are excluded. Do not mix Stage 3 and legacy decorators in one TypeScript compilation unit. diff --git a/docs/guides/agent-builder.md b/docs/guides/agent-builder.md index 39f8daf..1766e22 100644 --- a/docs/guides/agent-builder.md +++ b/docs/guides/agent-builder.md @@ -1,6 +1,6 @@ # Agent builder -The published `@theorvane/type-chain@0.2.0` `/agent` subpath provides a narrow decorator-first bridge to LangChain's `createAgent()`. The application provides the model and retains ownership of the lifecycle and all runtime controls. +The published `@theorvane/type-chain@0.2.1` `/agent` subpath provides a narrow decorator-first bridge to LangChain's `createAgent()`. The application provides the model and retains ownership of the lifecycle and all runtime controls. ## Prerequisites @@ -11,7 +11,7 @@ The published `@theorvane/type-chain@0.2.0` `/agent` subpath provides a narrow d ## Install ```bash -npm install @theorvane/type-chain@0.2.0 @langchain/core langchain zod +npm install @theorvane/type-chain@0.2.1 @langchain/core langchain zod ``` `/agent` is optional. Import the root package alone when tool metadata is sufficient. diff --git a/docs/guides/composition-selection.md b/docs/guides/composition-selection.md index 2e8fc2f..6ed4271 100644 --- a/docs/guides/composition-selection.md +++ b/docs/guides/composition-selection.md @@ -1,6 +1,6 @@ # Choose a TypeChain composition boundary -> **Release status:** This guide documents the published `@theorvane/type-chain@0.2.0` package. Every optional integration stays behind a dedicated subpath, so importing the root metadata package does not load LangChain or TypeMCP peers. +> **Release status:** This guide documents the published `@theorvane/type-chain@0.2.1` package. Every optional integration stays behind a dedicated subpath, so importing the root metadata package does not load LangChain or TypeMCP peers. TypeChain makes tool and policy declarations explicit, then adapts those declarations at a boundary selected by the application. Start with the narrowest import that reaches the behavior you need. The application keeps ownership of models, credentials, authorization, enforcement, state, persistence, streaming, hosting, and deployment. @@ -19,7 +19,7 @@ This is the routing chapter after an inspected root definition. It is not a seco Install the root package first: ```bash -npm install @theorvane/type-chain@0.2.0 +npm install @theorvane/type-chain@0.2.1 ``` | Need | Import | Use it when | Keep in the application | @@ -33,10 +33,10 @@ The root package has no required optional peer imports. Install only the peers f ```bash # Standard LangChain tool or agent composition -npm install @theorvane/type-chain@0.2.0 @langchain/core langchain zod +npm install @theorvane/type-chain@0.2.1 @langchain/core langchain zod # In-process TypeMCP composition -npm install @theorvane/type-chain@0.2.0 @theorvane/type-mcp@0.3.0 @langchain/core langchain zod +npm install @theorvane/type-chain@0.2.1 @theorvane/type-mcp@0.3.1 @langchain/core langchain zod ``` ## Begin with one declared tool diff --git a/docs/guides/core-concepts.md b/docs/guides/core-concepts.md index 70f4fea..63ab44f 100644 --- a/docs/guides/core-concepts.md +++ b/docs/guides/core-concepts.md @@ -1,6 +1,6 @@ # Core concepts -This page explains the published [`@theorvane/type-chain@0.2.0`](https://www.npmjs.com/package/@theorvane/type-chain) model before you select an optional integration. +This page explains the published [`@theorvane/type-chain@0.2.1`](https://www.npmjs.com/package/@theorvane/type-chain) model before you select an optional integration. > **Responsibility boundary:** TypeChain records declarations and adapts them at explicit boundaries. Applications retain ownership of **models, credentials, policy enforcement, state, hosting, deployment, and cross-process MCP transport**. diff --git a/docs/guides/getting-started.md b/docs/guides/getting-started.md index 3fe4575..84f14b0 100644 --- a/docs/guides/getting-started.md +++ b/docs/guides/getting-started.md @@ -1,8 +1,8 @@ -# Getting started with @theorvane/type-chain@0.2.0 +# Getting started with @theorvane/type-chain@0.2.1 TypeChain is a decorator-first, type-safe authoring layer for LangChain JS tools and agents. It records explicit tool metadata, adapts it to standard LangChain tools, and leaves model choice, credentials, authorization, retries, timeouts, persistence, redaction, and audit policy to your application. -This guide installs the published package `@theorvane/type-chain@0.2.0`, configures Stage 3 decorators, and declares a first tool. +This guide installs the published package `@theorvane/type-chain@0.2.1`, configures Stage 3 decorators, and declares a first tool. ## Requirements @@ -12,7 +12,7 @@ This guide installs the published package `@theorvane/type-chain@0.2.0`, configu ## Install ```bash -npm install @theorvane/type-chain@0.2.0 +npm install @theorvane/type-chain@0.2.1 ``` The root package has no required optional peers and can be imported on its own. LangChain and TypeMCP integrations live behind dedicated subpaths (`@theorvane/type-chain/langchain`, `/agent`, `/typemcp`) and only load their respective peers when you import them. diff --git a/docs/guides/langchain-integration.md b/docs/guides/langchain-integration.md index 011049e..eb563f0 100644 --- a/docs/guides/langchain-integration.md +++ b/docs/guides/langchain-integration.md @@ -1,6 +1,6 @@ # LangChain integration -`@theorvane/type-chain@0.2.0` exposes a dedicated `/langchain` subpath that turns decorated methods into standard LangChain structured tools. LangChain owns schema parsing and validation; TypeChain preserves the explicit name, description, schema, and receiver-bound invocation. +`@theorvane/type-chain@0.2.1` exposes a dedicated `/langchain` subpath that turns decorated methods into standard LangChain structured tools. LangChain owns schema parsing and validation; TypeChain preserves the explicit name, description, schema, and receiver-bound invocation. ## Prerequisites @@ -11,7 +11,7 @@ ## Install ```bash -npm install @theorvane/type-chain@0.2.0 @langchain/core langchain zod +npm install @theorvane/type-chain@0.2.1 @langchain/core langchain zod ``` The root package remains independent of optional peers. Import `/langchain` only where the application needs this adapter. diff --git a/docs/guides/petstore-policy-and-composition.md b/docs/guides/petstore-policy-and-composition.md index 185f394..7edbad1 100644 --- a/docs/guides/petstore-policy-and-composition.md +++ b/docs/guides/petstore-policy-and-composition.md @@ -5,7 +5,7 @@ This chapter continues the [Petstore TypeChain foundation](petstore-typechain-fo ## Before you start - Complete [Petstore TypeChain foundation](petstore-typechain-foundation.md) and confirm `npm run check` and `npm run inspect-tools` work. -- Node.js 20 or later with `@theorvane/type-chain@0.2.0` and `zod` installed. +- Node.js 20 or later with `@theorvane/type-chain@0.2.1` and `zod` installed. - Select **one** optional route only after the root declaration is useful: `/langchain`, `/agent`, or `/typemcp`. ## Workspace checkpoint @@ -26,7 +26,7 @@ Optional routes can add `langchain-tools.ts`, `petstore-agent.ts`, or `typemcp-t The policy metadata itself needs only the root package and Zod: ```bash -npm install @theorvane/type-chain@0.2.0 zod +npm install @theorvane/type-chain@0.2.1 zod npm run check ``` @@ -37,7 +37,7 @@ Install optional peers only when selecting one route: npm install @langchain/core langchain # In-process TypeMCP bridge -npm install @theorvane/type-mcp@0.3.0 @langchain/core langchain +npm install @theorvane/type-mcp@0.3.1 @langchain/core langchain ``` ## Record policy intent diff --git a/docs/guides/petstore-typechain-foundation.md b/docs/guides/petstore-typechain-foundation.md index e1bd0fb..556e483 100644 --- a/docs/guides/petstore-typechain-foundation.md +++ b/docs/guides/petstore-typechain-foundation.md @@ -2,7 +2,7 @@ This chapter continues a strict TypeScript Petstore workspace with one TypeChain tool. It records explicit runtime metadata, inspects immutable definitions, and leaves real domain dependencies and execution ownership in the application. -> **Published version:** The examples target [`@theorvane/type-chain@0.2.0`](https://www.npmjs.com/package/@theorvane/type-chain). They use standard TypeScript decorators rather than legacy `experimentalDecorators`. +> **Published version:** The examples target [`@theorvane/type-chain@0.2.1`](https://www.npmjs.com/package/@theorvane/type-chain). They use standard TypeScript decorators rather than legacy `experimentalDecorators`. ## Before you start @@ -31,7 +31,7 @@ The project can print the `find_product` definition. It does not create a model, From the workspace root, install the root package, a runtime schema, and local TypeScript runner if they are not already present: ```bash -npm install @theorvane/type-chain@0.2.0 zod +npm install @theorvane/type-chain@0.2.1 zod npm install --save-dev typescript tsx @types/node npm pkg set type=module npm pkg set scripts.check="tsc --noEmit" diff --git a/docs/guides/petstore-walkthrough.md b/docs/guides/petstore-walkthrough.md index d449a58..886f156 100644 --- a/docs/guides/petstore-walkthrough.md +++ b/docs/guides/petstore-walkthrough.md @@ -1,6 +1,6 @@ # Petstore walkthrough: typed tools at the boundary you own -This walkthrough uses one Petstore catalog tool to show the published [`@theorvane/type-chain@0.2.0`](https://www.npmjs.com/package/@theorvane/type-chain) flow: declare an explicit tool, optionally attach policy intent, then choose a LangChain, agent, or in-process TypeMCP boundary. +This walkthrough uses one Petstore catalog tool to show the published [`@theorvane/type-chain@0.2.1`](https://www.npmjs.com/package/@theorvane/type-chain) flow: declare an explicit tool, optionally attach policy intent, then choose a LangChain, agent, or in-process TypeMCP boundary. > **What this does not do:** TypeChain does not choose models, credentials, policy enforcement, state, hosting, deployment, or cross-process MCP transport. Your application supplies those decisions. @@ -19,7 +19,7 @@ For a project-starting route, complete [Petstore TypeChain foundation](petstore- Install the root package and Zod: ```bash -npm install @theorvane/type-chain@0.2.0 zod +npm install @theorvane/type-chain@0.2.1 zod ``` Use Node-aware TypeScript configuration: @@ -89,7 +89,7 @@ This records intent. It does not enforce authorization or write an audit event a Install optional peers only for this path: ```bash -npm install @theorvane/type-chain@0.2.0 @langchain/core langchain zod +npm install @theorvane/type-chain@0.2.1 @langchain/core langchain zod ``` Create `src/langchain-tools.ts`: @@ -129,7 +129,7 @@ export const agent = buildAgent(new PetstoreAgent(), { When a TypeMCP-decorated Petstore server and the LangChain application live in the same Node.js process, install the bridge peers: ```bash -npm install @theorvane/type-chain@0.2.0 @theorvane/type-mcp@0.3.0 @langchain/core langchain zod +npm install @theorvane/type-chain@0.2.1 @theorvane/type-mcp@0.3.1 @langchain/core langchain zod ``` Create `src/petstore-server.ts`: diff --git a/docs/guides/policy.md b/docs/guides/policy.md index 4c7b122..35e809f 100644 --- a/docs/guides/policy.md +++ b/docs/guides/policy.md @@ -1,6 +1,6 @@ # Declarative policy and application-owned guards -The published `@theorvane/type-chain@0.2.0` package lets a tool declare policy intent. It does not provide a default allow/deny decision or enforce authorization, approvals, retries, timeouts, idempotency, auditing, or redaction. +The published `@theorvane/type-chain@0.2.1` package lets a tool declare policy intent. It does not provide a default allow/deny decision or enforce authorization, approvals, retries, timeouts, idempotency, auditing, or redaction. ## Prerequisites @@ -11,7 +11,7 @@ The published `@theorvane/type-chain@0.2.0` package lets a tool declare policy i ## Install ```bash -npm install @theorvane/type-chain@0.2.0 zod +npm install @theorvane/type-chain@0.2.1 zod ``` Use the `/langchain` optional subpath only if the application later adapts guarded tools to LangChain. diff --git a/docs/guides/tools-and-definitions.md b/docs/guides/tools-and-definitions.md index bf58e46..2210b80 100644 --- a/docs/guides/tools-and-definitions.md +++ b/docs/guides/tools-and-definitions.md @@ -1,6 +1,6 @@ # Tools and definitions -This guide uses the published `@theorvane/type-chain@0.2.0` root surface to record explicit tool metadata and inspect immutable, receiver-bound definitions. TypeChain does not infer runtime schemas from TypeScript types or start a transport. +This guide uses the published `@theorvane/type-chain@0.2.1` root surface to record explicit tool metadata and inspect immutable, receiver-bound definitions. TypeChain does not infer runtime schemas from TypeScript types or start a transport. ## Prerequisites @@ -11,7 +11,7 @@ This guide uses the published `@theorvane/type-chain@0.2.0` root surface to reco ## Install ```bash -npm install @theorvane/type-chain@0.2.0 zod +npm install @theorvane/type-chain@0.2.1 zod ``` The root metadata package has no required optional peer. Add `/langchain`, `/agent`, or `/typemcp` only when your application chooses that integration boundary. diff --git a/docs/guides/typemcp-bridge.md b/docs/guides/typemcp-bridge.md index 4df5919..c29776f 100644 --- a/docs/guides/typemcp-bridge.md +++ b/docs/guides/typemcp-bridge.md @@ -1,6 +1,6 @@ # TypeMCP in-process bridge -The published `@theorvane/type-chain@0.2.0` `/typemcp` subpath composes a TypeMCP-decorated server into native LangChain tools in the same Node.js process. TypeMCP owns declaration validation and instance resolution; LangChain owns agent construction; the application owns models, policies, dependencies, and deployment. +The published `@theorvane/type-chain@0.2.1` `/typemcp` subpath composes a TypeMCP-decorated server into native LangChain tools in the same Node.js process. TypeMCP owns declaration validation and instance resolution; LangChain owns agent construction; the application owns models, policies, dependencies, and deployment. ## Prerequisites @@ -12,7 +12,7 @@ The published `@theorvane/type-chain@0.2.0` `/typemcp` subpath composes a TypeMC ## Install ```bash -npm install @theorvane/type-chain@0.2.0 @theorvane/type-mcp@0.3.0 @langchain/core langchain zod +npm install @theorvane/type-chain@0.2.1 @theorvane/type-mcp@0.3.1 @langchain/core langchain zod ``` This is an optional integration boundary; the root TypeChain package does not import TypeMCP or LangChain peers. diff --git a/package-lock.json b/package-lock.json index f5dc2a0..b14460b 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,17 +1,17 @@ { "name": "@theorvane/type-chain", - "version": "0.2.0", + "version": "0.2.1", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "@theorvane/type-chain", - "version": "0.2.0", + "version": "0.2.1", "license": "MIT", "devDependencies": { "@biomejs/biome": "^2.5.5", "@langchain/core": "1.2.3", - "@theorvane/type-mcp": "0.3.0", + "@theorvane/type-mcp": "0.3.1", "langchain": "1.5.4", "tsup": "^8.5.1", "typescript": "^5.9.3", @@ -1248,9 +1248,9 @@ "license": "MIT" }, "node_modules/@theorvane/type-mcp": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/@theorvane/type-mcp/-/type-mcp-0.3.0.tgz", - "integrity": "sha512-xeBq/vM6KgEmgp+i/Pb0xf/C9hIZwwZjZBbKynxqiccr1VRXHiRCB7GAFfwmAmG8bhKTaSdTDhrP6oEwPzUb7Q==", + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/@theorvane/type-mcp/-/type-mcp-0.3.1.tgz", + "integrity": "sha512-GKzld+JQNpornITGBLH5UyaodzCooSzTUDFbY8nqYtnuzvWFJbwkaIp/jiejW+AtRZ9IlBu3HOBnKAk72xTjow==", "dev": true, "license": "MIT", "dependencies": { diff --git a/package.json b/package.json index 4b3ccab..209a64b 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@theorvane/type-chain", - "version": "0.2.0", + "version": "0.2.1", "description": "Decorator-first, type-safe authoring layer for LangChain JS tools and agents.", "license": "MIT", "type": "module", @@ -12,24 +12,44 @@ ], "exports": { ".": { - "types": "./dist/index.d.ts", - "import": "./dist/index.js", - "default": "./dist/index.js" + "import": { + "types": "./dist/index.d.ts", + "default": "./dist/index.js" + }, + "require": { + "types": "./dist/index.d.cts", + "default": "./dist/index.cjs" + } }, "./langchain": { - "types": "./dist/langchain.d.ts", - "import": "./dist/langchain.js", - "default": "./dist/langchain.js" + "import": { + "types": "./dist/langchain.d.ts", + "default": "./dist/langchain.js" + }, + "require": { + "types": "./dist/langchain.d.cts", + "default": "./dist/langchain.cjs" + } }, "./agent": { - "types": "./dist/agent.d.ts", - "import": "./dist/agent.js", - "default": "./dist/agent.js" + "import": { + "types": "./dist/agent.d.ts", + "default": "./dist/agent.js" + }, + "require": { + "types": "./dist/agent.d.cts", + "default": "./dist/agent.cjs" + } }, "./typemcp": { - "types": "./dist/typemcp.d.ts", - "import": "./dist/typemcp.js", - "default": "./dist/typemcp.js" + "import": { + "types": "./dist/typemcp.d.ts", + "default": "./dist/typemcp.js" + }, + "require": { + "types": "./dist/typemcp.d.cts", + "default": "./dist/typemcp.cjs" + } }, "./legacy": { "import": { @@ -52,7 +72,7 @@ "access": "public" }, "scripts": { - "build": "tsc --project tsconfig.build.json && tsup src/legacy.ts --format esm,cjs --dts --out-dir dist --clean=false", + "build": "tsc --project tsconfig.build.json && tsup src/index.ts src/langchain.ts src/agent.ts src/typemcp.ts src/legacy.ts --format cjs --dts --out-dir dist --clean=false && tsup src/legacy.ts --format esm --out-dir dist --clean=false", "lint": "biome check .", "format:check": "biome format .", "typecheck": "tsc --noEmit", @@ -100,7 +120,7 @@ "devDependencies": { "@biomejs/biome": "^2.5.5", "@langchain/core": "1.2.3", - "@theorvane/type-mcp": "0.3.0", + "@theorvane/type-mcp": "0.3.1", "langchain": "1.5.4", "tsup": "^8.5.1", "typescript": "^5.9.3", diff --git a/scripts/verify-legacy-consumer.mjs b/scripts/verify-legacy-consumer.mjs index 1921a63..a3dfa63 100644 --- a/scripts/verify-legacy-consumer.mjs +++ b/scripts/verify-legacy-consumer.mjs @@ -35,6 +35,9 @@ try { "--no-audit", "--no-fund", tarballPath, + "@langchain/core@1.2.3", + "@theorvane/type-mcp@0.3.1", + "langchain@1.5.4", "@types/node", ], consumer, @@ -52,7 +55,7 @@ try { skipLibCheck: true, outDir: "dist", }, - include: ["tools.ts"], + include: ["tools.ts", "imports.ts"], }, null, 2, @@ -62,12 +65,17 @@ try { join(consumer, "tools.ts"), `import { Agent, getToolDefinitions, Policy, Tool } from "@theorvane/type-chain/legacy";\n\n@Agent({ systemPrompt: "Use legacy tools." })\nclass LegacyTools {\n @Tool({ name: "search_issues", description: "Searches issues.", schema: { type: "object" } })\n @Policy({ authorization: "required" })\n search({ query }: { readonly query: string }) { return \`legacy:\${query}\`; }\n}\n\nconst definition = getToolDefinitions(new LegacyTools())[0];\nif (definition?.invoke({ query: "123" }) !== "legacy:123") throw new Error("Legacy tool was not registered.");\n`, ); + writeFileSync( + join(consumer, "imports.ts"), + `import { getToolDefinitions } from "@theorvane/type-chain";\nimport { toLangChainTools } from "@theorvane/type-chain/langchain";\nimport { buildAgent } from "@theorvane/type-chain/agent";\nimport { createTypeMcpLangChainTools } from "@theorvane/type-chain/typemcp";\nvoid getToolDefinitions;\nvoid toLangChainTools;\nvoid buildAgent;\nvoid createTypeMcpLangChainTools;\n`, + ); run( resolve(packageRoot, "node_modules/typescript/bin/tsc"), ["--project", "tsconfig.json"], consumer, ); run("node", ["dist/tools.js"], consumer); + run("node", ["dist/imports.js"], consumer); console.log( "Verified packed CommonJS consumer with legacy TypeScript decorators.", ); diff --git a/scripts/verify-package.mjs b/scripts/verify-package.mjs index 5e00f78..ea1ea08 100644 --- a/scripts/verify-package.mjs +++ b/scripts/verify-package.mjs @@ -2,13 +2,21 @@ import { existsSync, readFileSync } from "node:fs"; const required = [ "dist/index.js", + "dist/index.cjs", "dist/index.d.ts", + "dist/index.d.cts", "dist/langchain.js", + "dist/langchain.cjs", "dist/langchain.d.ts", + "dist/langchain.d.cts", "dist/agent.js", + "dist/agent.cjs", "dist/agent.d.ts", + "dist/agent.d.cts", "dist/typemcp.js", + "dist/typemcp.cjs", "dist/typemcp.d.ts", + "dist/typemcp.d.cts", "dist/legacy.js", "dist/legacy.cjs", "dist/legacy.d.ts", @@ -20,30 +28,46 @@ if (missing.length > 0) throw new Error(`Package contract is incomplete: ${missing.join(", ")}`); const packageJson = JSON.parse(readFileSync("package.json", "utf8")); -const langChainExport = packageJson.exports?.["./langchain"]; +const rootExport = packageJson.exports?.["."]; if ( - langChainExport?.types !== "./dist/langchain.d.ts" || - langChainExport?.import !== "./dist/langchain.js" + JSON.stringify(rootExport) !== + JSON.stringify({ + import: { types: "./dist/index.d.ts", default: "./dist/index.js" }, + require: { types: "./dist/index.d.cts", default: "./dist/index.cjs" }, + }) ) { - throw new Error( - "Package contract is missing the type-chain/langchain export.", - ); + throw new Error("Package contract is missing the type-chain root export."); } -const agentExport = packageJson.exports?.["./agent"]; -if ( - agentExport?.types !== "./dist/agent.d.ts" || - agentExport?.import !== "./dist/agent.js" -) { - throw new Error("Package contract is missing the type-chain/agent export."); -} +const subpathExports = { + "./langchain": { + import: { types: "./dist/langchain.d.ts", default: "./dist/langchain.js" }, + require: { + types: "./dist/langchain.d.cts", + default: "./dist/langchain.cjs", + }, + }, + "./agent": { + import: { types: "./dist/agent.d.ts", default: "./dist/agent.js" }, + require: { types: "./dist/agent.d.cts", default: "./dist/agent.cjs" }, + }, + "./typemcp": { + import: { types: "./dist/typemcp.d.ts", default: "./dist/typemcp.js" }, + require: { + types: "./dist/typemcp.d.cts", + default: "./dist/typemcp.cjs", + }, + }, +}; -const bridgeExport = packageJson.exports?.["./typemcp"]; -if ( - bridgeExport?.types !== "./dist/typemcp.d.ts" || - bridgeExport?.import !== "./dist/typemcp.js" -) { - throw new Error("Package contract is missing the type-chain/typemcp export."); +for (const [subpath, expected] of Object.entries(subpathExports)) { + if ( + JSON.stringify(packageJson.exports?.[subpath]) !== JSON.stringify(expected) + ) { + throw new Error( + `Package contract is missing the type-chain${subpath} export.`, + ); + } } const legacyExport = packageJson.exports?.["./legacy"]; diff --git a/test/reference-documentation-contract.test.mjs b/test/reference-documentation-contract.test.mjs index 85e1e30..47452d5 100644 --- a/test/reference-documentation-contract.test.mjs +++ b/test/reference-documentation-contract.test.mjs @@ -21,7 +21,7 @@ test("reference-first TypeChain documentation routes Petstore readers without cl await Promise.all(documents.map((path) => readFile(path, "utf8"))) ).join("\n"); - assert.match(content, /@theorvane\/type-chain@0\.2\.0/); + assert.match(content, /@theorvane\/type-chain@0\.2\.1/); for (const entryPoint of [ "Define tools", "Enforce a policy", @@ -113,7 +113,7 @@ test("requires the project-starting TypeChain curriculum to preserve optional in assert.match(content, /## Next steps/, path); } - assert.match(allContent, /@theorvane\/type-chain@0\.2\.0/); + assert.match(allContent, /@theorvane\/type-chain@0\.2\.1/); assert.doesNotMatch(allContent, /npm install @theorvane\/type-chain(?:\s|$)/); assert.match(consumerScript, /packed consumers: root without optional peers/); assert.match( diff --git a/test/release-workflow-contract.test.mjs b/test/release-workflow-contract.test.mjs index 21ee917..b3ecd83 100644 --- a/test/release-workflow-contract.test.mjs +++ b/test/release-workflow-contract.test.mjs @@ -41,6 +41,11 @@ test("publish readiness verifies an installed packed consumer", async () => { assert.match(script, /"npm", \["pack", "--json", "--ignore-scripts"\]/); assert.match(script, /getPackedTarballFilename/); assert.match(legacyScript, /getPackedTarballFilename/); + assert.match(legacyScript, /@theorvane\/type-mcp@0\.3\.1/); + assert.match(legacyScript, /@theorvane\/type-chain\/langchain/); + assert.match(legacyScript, /@theorvane\/type-chain\/agent/); + assert.match(legacyScript, /@theorvane\/type-chain\/typemcp/); + assert.match(legacyScript, /dist\/imports\.js/); assert.match(packJson, /Array\.isArray\(packed\)/); assert.match(packJson, /Object\.values\(packed \?\? \{\}\)/); assert.match(script, /toGuardedLangChainTools/); @@ -56,7 +61,7 @@ test("public release metadata and documentation use the scoped first-release con const releaseGuide = await readWorkflow("../docs/release.md"); assert.equal(manifest.name, "@theorvane/type-chain"); - assert.equal(manifest.version, "0.2.0"); + assert.equal(manifest.version, "0.2.1"); assert.equal(manifest.peerDependencies["@theorvane/type-mcp"], "^0.3.0"); assert.equal(manifest.publishConfig.access, "public"); assert.match(readme, /Install from npm/);