diff --git a/README.md b/README.md index c55e2e3..0fb6847 100644 --- a/README.md +++ b/README.md @@ -12,7 +12,7 @@ tskm is two things that fit together: - **An AOT (ahead-of-time) type compiler** — instead of deriving a type from a schema with `z.infer` at every use site, tskm pre-computes it once and writes the fully-expanded, concrete type to a real file. The answer comes from the actual TypeScript type checker, queried out of process. -It is a bun-workspaces monorepo: `tskm` (runtime), `@tskm/compiler` (AOT codegen + CLI), `@tskm/vite` (Vite plugin). +It is a bun-workspaces monorepo: `@tskm/core` (runtime), `@tskm/compiler` (AOT codegen + CLI), `@tskm/vite` (Vite plugin). ## Why tskm? @@ -35,7 +35,7 @@ tskm goes the **opposite direction — schema → type, not type → validator **Validate at runtime** — schemas are values; `parse` / `safeParse` are standalone functions: ```ts -import { object, string, number, array, pipe, minLength, parse, safeParse } from "tskm" +import { object, string, number, array, pipe, minLength, parse, safeParse } from "@tskm/core" const userSchema = object({ name: pipe(string(), minLength(2)), @@ -54,7 +54,7 @@ const result = safeParse(userSchema, { name: "", age: 1, tags: [] }) ```ts // user.schema.ts (you write — note: no `type User = Infer<...>` needed) -import { object, string, number, array, pipe, minLength } from "tskm" +import { object, string, number, array, pipe, minLength } from "@tskm/core" export const userSchema = object({ name: pipe(string(), minLength(2)), @@ -102,12 +102,12 @@ it runs the compiler on `buildStart` and watches during `vite dev`. The compiler never reads your schema at runtime — the inferred type only exists in the type system, so it asks the type checker directly: -1. **Discover** — [`oxc-parser`](https://oxc.rs) scans each source file (syntactically) for exported `const`s whose factory is imported from `tskm`, and for explicit `type T = Infer` markers. +1. **Discover** — [`oxc-parser`](https://oxc.rs) scans each source file (syntactically) for exported `const`s whose factory is imported from `@tskm/core`, and for explicit `type T = Infer` markers. 2. **Query** — for each schema, the compiler writes a tiny sibling file (`.tskm-query.ts`, deleted afterward) next to the source that declares a marker against the schema's output type: ```ts import { userSchema } from "./user.schema" - import type { InferOutput } from "tskm" + import type { InferOutput } from "@tskm/core" type __P = { [K in keyof T]: T[K] } & {} declare const __tskm_0: __P> ``` diff --git a/bun.lock b/bun.lock index 8ffd110..0d60e52 100644 --- a/bun.lock +++ b/bun.lock @@ -23,7 +23,7 @@ "name": "@tskm/example-basic", "version": "0.0.0", "dependencies": { - "tskm": "workspace:*", + "@tskm/core": "workspace:*", }, "devDependencies": { "@tskm/compiler": "workspace:*", @@ -31,9 +31,9 @@ }, "packages/compiler": { "name": "@tskm/compiler", - "version": "0.0.1", + "version": "0.0.2", "bin": { - "tskm": "./dist/cli.js", + "tskm": "./dist/cli.mjs", }, "dependencies": { "@corsa-bind/napi": "0.35.0", @@ -47,7 +47,7 @@ }, }, "packages/tskm": { - "name": "tskm", + "name": "@tskm/core", "version": "0.0.1", "devDependencies": { "@standard-schema/spec": "1.1.0", @@ -272,6 +272,8 @@ "@tskm/compiler": ["@tskm/compiler@workspace:packages/compiler"], + "@tskm/core": ["@tskm/core@workspace:packages/tskm"], + "@tskm/example-basic": ["@tskm/example-basic@workspace:examples/basic"], "@tskm/vite": ["@tskm/vite@workspace:packages/vite"], @@ -584,8 +586,6 @@ "to-regex-range": ["to-regex-range@5.0.1", "", { "dependencies": { "is-number": "^7.0.0" } }, "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ=="], - "tskm": ["tskm@workspace:packages/tskm"], - "tslib": ["tslib@2.8.1", "", {}, "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w=="], "typescript": ["typescript@6.0.3", "", { "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" } }, "sha512-y2TvuxSZPDyQakkFRPZHKFm+KKVqIisdg9/CZwm9ftvKXLP8NRWj38/ODjNbr43SsoXqNuAisEf1GdCxqWcdBw=="], diff --git a/examples/basic/package.json b/examples/basic/package.json index 7036c79..9d4ad62 100644 --- a/examples/basic/package.json +++ b/examples/basic/package.json @@ -4,7 +4,7 @@ "private": true, "type": "module", "dependencies": { - "tskm": "workspace:*" + "@tskm/core": "workspace:*" }, "devDependencies": { "@tskm/compiler": "workspace:*" diff --git a/examples/basic/src/main.ts b/examples/basic/src/main.ts index 72c29d7..1fee96b 100644 --- a/examples/basic/src/main.ts +++ b/examples/basic/src/main.ts @@ -1,4 +1,4 @@ -import { safeParse } from "tskm" +import { safeParse } from "@tskm/core" import type { Product, User } from "./user.schema.gen.ts" import { productSchema, userSchema } from "./user.schema.ts" diff --git a/examples/basic/src/user.schema.ts b/examples/basic/src/user.schema.ts index 484c397..c4c0a8b 100644 --- a/examples/basic/src/user.schema.ts +++ b/examples/basic/src/user.schema.ts @@ -1,4 +1,4 @@ -import { minLength, number, object, pipe, string } from "tskm" +import { minLength, number, object, pipe, string } from "@tskm/core" export const userSchema = object({ name: pipe(string(), minLength(2)), diff --git a/examples/basic/tsconfig.json b/examples/basic/tsconfig.json index 03e9f0d..90b35ff 100644 --- a/examples/basic/tsconfig.json +++ b/examples/basic/tsconfig.json @@ -8,7 +8,7 @@ "skipLibCheck": true, "noEmit": true, "paths": { - "tskm": ["../../packages/tskm/src/index.ts"] + "@tskm/core": ["../../packages/tskm/src/index.ts"] } }, "include": ["src"] diff --git a/packages/compiler/package.json b/packages/compiler/package.json index 82fd1d2..4b6fe72 100644 --- a/packages/compiler/package.json +++ b/packages/compiler/package.json @@ -1,6 +1,6 @@ { "name": "@tskm/compiler", - "version": "0.0.1", + "version": "0.0.2", "description": "AOT schema-to-type compiler for tskm, powered by the tsgo (Corsa) checker API", "type": "module", "license": "MIT", diff --git a/packages/compiler/src/discovery.ts b/packages/compiler/src/discovery.ts index ec0da53..902ded0 100644 --- a/packages/compiler/src/discovery.ts +++ b/packages/compiler/src/discovery.ts @@ -1,7 +1,7 @@ import { parseSync } from "oxc-parser" /** The runtime package whose exports mark a value as a tskm schema. */ -const RUNTIME_MODULE = "tskm" +const RUNTIME_MODULE = "@tskm/core" /** Type-level aliases that mark `export type T = ...` AOT targets. */ const INFER_ALIASES = new Set(["Infer", "InferOutput"]) @@ -73,7 +73,7 @@ function calleeName(init: OxcNode | undefined): string | undefined { /** * Reads an `export type T = Infer` (or `InferOutput<...>`, or - * `import("tskm").InferOutput`) alias and returns the referenced + * `import("@tskm/core").InferOutput`) alias and returns the referenced * schema name plus the declared alias name. */ function readInferAlias(decl: OxcNode | undefined): DiscoveredSchema | undefined { diff --git a/packages/compiler/src/inplace.ts b/packages/compiler/src/inplace.ts index 06af330..60c8832 100644 --- a/packages/compiler/src/inplace.ts +++ b/packages/compiler/src/inplace.ts @@ -57,7 +57,7 @@ const START_LINE = /^\/\/ @tskm-gen (\w+) from (\w+) #([0-9a-f]{8})$/ const END_LINE = /^\/\/ @tskm-end (\w+)$/ // First-run marker: only the SINGLE-LINE form is supported. Accepts the bare -// `Infer`/`InferOutput` reference and the `import("tskm").Infer*<...>` form — matching +// `Infer`/`InferOutput` reference and the `import("@tskm/core").Infer*<...>` form — matching // discovery's alias set. (`InferInput` is intentionally excluded: the resolver always // queries `InferOutput`, so an input marker would be silently filled with the output type.) const INFER_MARKER = diff --git a/packages/compiler/src/resolve.ts b/packages/compiler/src/resolve.ts index 9766f1a..1f4a72f 100644 --- a/packages/compiler/src/resolve.ts +++ b/packages/compiler/src/resolve.ts @@ -30,7 +30,7 @@ function buildQueryBody( if (names.length > 0) { lines.push(`import { ${names.join(", ")} } from "${sourceImportPath}"`) } - lines.push(`import type { InferOutput } from "tskm"`) + lines.push(`import type { InferOutput } from "@tskm/core"`) lines.push(`type __P = { [K in keyof T]: T[K] } & {}`) schemas.forEach((schema, i) => { lines.push(`declare const ${markers[i]}: __P>`) diff --git a/packages/compiler/test/discovery.test.ts b/packages/compiler/test/discovery.test.ts index 6daf374..95e1b7e 100644 --- a/packages/compiler/test/discovery.test.ts +++ b/packages/compiler/test/discovery.test.ts @@ -37,7 +37,7 @@ describe("deriveTypeName", () => { describe("discoverSchemas — const (alias-origin) factory declarations", () => { it("discovers an exported const built from a tskm runtime import", () => { const src = ` - import { object, string } from "tskm" + import { object, string } from "@tskm/core" export const userSchema = object({ name: string() }) ` const { schemas, diagnostics } = discoverSchemas("a.ts", src) @@ -49,7 +49,7 @@ describe("discoverSchemas — const (alias-origin) factory declarations", () => it("ignores consts whose callee is not a tskm runtime import", () => { const src = ` - import { object } from "tskm" + import { object } from "@tskm/core" import { other } from "elsewhere" export const x = other({ a: 1 }) ` @@ -59,7 +59,7 @@ describe("discoverSchemas — const (alias-origin) factory declarations", () => it("ignores a const whose init is not a call expression", () => { const src = ` - import { object } from "tskm" + import { object } from "@tskm/core" export const notACall = 42 ` const { schemas } = discoverSchemas("a.ts", src) @@ -68,7 +68,7 @@ describe("discoverSchemas — const (alias-origin) factory declarations", () => it("ignores a call whose callee is not a plain identifier (member expression)", () => { const src = ` - import { v } from "tskm" + import { v } from "@tskm/core" export const x = v.object({ a: 1 }) ` const { schemas } = discoverSchemas("a.ts", src) @@ -77,7 +77,7 @@ describe("discoverSchemas — const (alias-origin) factory declarations", () => it("ignores non-exported consts", () => { const src = ` - import { string } from "tskm" + import { string } from "@tskm/core" const internalSchema = string() ` const { schemas } = discoverSchemas("a.ts", src) @@ -86,7 +86,7 @@ describe("discoverSchemas — const (alias-origin) factory declarations", () => it("honors runtime-import local aliasing (import { object as o })", () => { const src = ` - import { object as o, string } from "tskm" + import { object as o, string } from "@tskm/core" export const petSchema = o({ name: string() }) ` const { schemas } = discoverSchemas("a.ts", src) @@ -110,8 +110,8 @@ describe("discoverSchemas — const (alias-origin) factory declarations", () => describe("discoverSchemas — Infer alias markers", () => { it("discovers an export type T = Infer marker", () => { const src = ` - import { string } from "tskm" - import type { Infer } from "tskm" + import { string } from "@tskm/core" + import type { Infer } from "@tskm/core" const xSchema = string() export type X = Infer ` @@ -129,19 +129,19 @@ describe("discoverSchemas — Infer alias markers", () => { expect(schemas).toEqual([{ name: "ySchema", typeName: "Y", origin: "alias" }]) }) - it('discovers the import("tskm").InferOutput<...> qualified form', () => { + it('discovers the import("@tskm/core").InferOutput<...> qualified form', () => { const src = ` const zSchema = {} - export type Z = import("tskm").InferOutput + export type Z = import("@tskm/core").InferOutput ` const { schemas } = discoverSchemas("a.ts", src) expect(schemas).toEqual([{ name: "zSchema", typeName: "Z", origin: "alias" }]) }) - it('discovers the import("tskm").Infer<...> qualified form', () => { + it('discovers the import("@tskm/core").Infer<...> qualified form', () => { const src = ` const wSchema = {} - export type W = import("tskm").Infer + export type W = import("@tskm/core").Infer ` const { schemas } = discoverSchemas("a.ts", src) expect(schemas).toEqual([{ name: "wSchema", typeName: "W", origin: "alias" }]) @@ -159,7 +159,7 @@ describe("discoverSchemas — Infer alias markers", () => { it("ignores an import-type whose qualifier is not an Infer alias", () => { const src = ` const qSchema = {} - export type Q = import("tskm").SomethingElse + export type Q = import("@tskm/core").SomethingElse ` const { schemas } = discoverSchemas("a.ts", src) expect(schemas).toHaveLength(0) @@ -202,8 +202,8 @@ describe("discoverSchemas — Infer alias markers", () => { describe("discoverSchemas — multiple schemas & dedup", () => { it("collects const and alias origins together from one file", () => { const src = ` - import { object, string, number } from "tskm" - import type { Infer } from "tskm" + import { object, string, number } from "@tskm/core" + import type { Infer } from "@tskm/core" export const userSchema = object({ name: string() }) export const ageSchema = number() const hiddenSchema = string() @@ -219,7 +219,7 @@ describe("discoverSchemas — multiple schemas & dedup", () => { it("does not re-add a const name already seen", () => { const src = ` - import { string } from "tskm" + import { string } from "@tskm/core" export const dupSchema = string(), other = string() ` const { schemas } = discoverSchemas("a.ts", src) diff --git a/packages/compiler/test/fixtures/basic/src/account.schema.ts b/packages/compiler/test/fixtures/basic/src/account.schema.ts index b79e82c..efbb580 100644 --- a/packages/compiler/test/fixtures/basic/src/account.schema.ts +++ b/packages/compiler/test/fixtures/basic/src/account.schema.ts @@ -1,4 +1,4 @@ -import { array, number, object, optional, pipe, string, transform } from "tskm" +import { array, number, object, optional, pipe, string, transform } from "@tskm/core" export const accountSchema = object({ id: string(), diff --git a/packages/compiler/test/fixtures/basic/tsconfig.json b/packages/compiler/test/fixtures/basic/tsconfig.json index 55250a9..4f32db8 100644 --- a/packages/compiler/test/fixtures/basic/tsconfig.json +++ b/packages/compiler/test/fixtures/basic/tsconfig.json @@ -9,7 +9,7 @@ "noEmit": true, "baseUrl": ".", "paths": { - "tskm": ["../../../../tskm/src/index.ts"] + "@tskm/core": ["../../../../tskm/src/index.ts"] } }, "include": ["src"] diff --git a/packages/compiler/test/inplace.integration.test.ts b/packages/compiler/test/inplace.integration.test.ts index 46964c0..0127d5c 100644 --- a/packages/compiler/test/inplace.integration.test.ts +++ b/packages/compiler/test/inplace.integration.test.ts @@ -11,7 +11,7 @@ const query = fileURLToPath( new URL("./fixtures/basic/src/widget.schema.tskm-query.ts", import.meta.url), ) -const SOURCE = `import { object, string, number, type Infer } from "tskm" +const SOURCE = `import { object, string, number, type Infer } from "@tskm/core" export const widgetSchema = object({ id: string(), diff --git a/packages/compiler/test/inplace.test.ts b/packages/compiler/test/inplace.test.ts index 8b54b43..7a59b74 100644 --- a/packages/compiler/test/inplace.test.ts +++ b/packages/compiler/test/inplace.test.ts @@ -61,8 +61,8 @@ describe("emitInplace — first run (Infer marker conversion)", () => { expect(readFileSync(file, "utf8")).toBe(result.content) }) - it('accepts the import("tskm").InferOutput<...> marker form', () => { - const source = `export type User = import("tskm").InferOutput\n` + it('accepts the import("@tskm/core").InferOutput<...> marker form', () => { + const source = `export type User = import("@tskm/core").InferOutput\n` const file = tmpFile("b.ts", source) const result = emitInplace(file, source, [{ typeName: "User", typeString: "{ id: string }" }], { version: VERSION, diff --git a/packages/compiler/test/jsonschema.integration.test.ts b/packages/compiler/test/jsonschema.integration.test.ts index ffb1807..8aed9fc 100644 --- a/packages/compiler/test/jsonschema.integration.test.ts +++ b/packages/compiler/test/jsonschema.integration.test.ts @@ -75,7 +75,7 @@ describe.skipIf(!bun)("generateJsonSchema — isolated subprocess (real import)" // file, so module output cannot break parsing. writeFileSync( noisySource, - `import { object, string } from "tskm"\nconsole.log("side effect on stdout")\nexport const noisySchema = object({ a: string() })\n`, + `import { object, string } from "@tskm/core"\nconsole.log("side effect on stdout")\nexport const noisySchema = object({ a: string() })\n`, ) const result = await generateJsonSchema({ root: fixtureRoot, diff --git a/packages/compiler/test/watch.integration.test.ts b/packages/compiler/test/watch.integration.test.ts index e7086dc..07b0b8f 100644 --- a/packages/compiler/test/watch.integration.test.ts +++ b/packages/compiler/test/watch.integration.test.ts @@ -16,7 +16,7 @@ const query = fileURLToPath( ) function inplaceSource(sizeField: string): string { - return `import { object, string, number, type Infer } from "tskm" + return `import { object, string, number, type Infer } from "@tskm/core" export const watchSchema = object({ id: string(), @@ -28,7 +28,7 @@ export type WatchTarget = Infer } function sidecarSource(extraField: string): string { - return `import { object, string, number } from "tskm" + return `import { object, string, number } from "@tskm/core" export const watchSchema = object({ id: string(), diff --git a/packages/tskm/package.json b/packages/tskm/package.json index b06b850..08f4e73 100644 --- a/packages/tskm/package.json +++ b/packages/tskm/package.json @@ -1,5 +1,5 @@ { - "name": "tskm", + "name": "@tskm/core", "version": "0.0.1", "description": "Standard Schema compliant, functional validation library with AOT type compilation", "type": "module", diff --git a/scripts/publish.ts b/scripts/publish.ts index f3e59fc..91467df 100644 --- a/scripts/publish.ts +++ b/scripts/publish.ts @@ -31,7 +31,7 @@ export type Runner = (cmd: string, args: string[], opts?: { cwd?: string }) => C export type PkgInfo = { name: string; version: string; dir: string } // Dependency order: vite depends on compiler, so compiler must reach the registry first. -export const PUBLISH_ORDER = ["@tskm/compiler", "tskm", "@tskm/vite"] as const +export const PUBLISH_ORDER = ["@tskm/compiler", "@tskm/core", "@tskm/vite"] as const const DEP_FIELDS = [ "dependencies", diff --git a/scripts/smoke.ts b/scripts/smoke.ts index 0f8eae2..2fdad17 100644 --- a/scripts/smoke.ts +++ b/scripts/smoke.ts @@ -42,7 +42,7 @@ function packPackage(pkg: PkgInfo, versionMap: Map, destDir: str const CHECKS: Record = { // tskm: zero-dependency library — a known named export must be callable. "check-tskm.mjs": - "import * as m from 'tskm'; if (typeof m.email !== 'function') { throw new Error('tskm: expected named export `email` to be a function'); } console.log('tskm import OK');", + "import * as m from '@tskm/core'; if (typeof m.email !== 'function') { throw new Error('tskm: expected named export `email` to be a function'); } console.log('tskm import OK');", // @tskm/compiler: a known named export must be present after install from the tarball. "check-compiler.mjs": "import * as m from '@tskm/compiler'; if (typeof m.defineConfig !== 'function') { throw new Error('@tskm/compiler: expected `defineConfig` export'); } console.log('@tskm/compiler import OK');", @@ -89,7 +89,7 @@ function main(): void { private: true, type: "module", dependencies: { - tskm: `file:${tarballs.get("tskm")}`, + "@tskm/core": `file:${tarballs.get("@tskm/core")}`, "@tskm/compiler": `file:${tarballs.get("@tskm/compiler")}`, "@tskm/vite": `file:${tarballs.get("@tskm/vite")}`, "@typescript/native-preview": nativePreview,