@prisma-idb/family-idb 0.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (45) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +30 -0
  3. package/dist/bin/prisma-idb.d.mts +1 -0
  4. package/dist/bin/prisma-idb.mjs +13 -0
  5. package/dist/bin/prisma-idb.mjs.map +1 -0
  6. package/dist/chain-order-CaHXo5jz.mjs +44 -0
  7. package/dist/chain-order-CaHXo5jz.mjs.map +1 -0
  8. package/dist/cli-Dlaym_DD.mjs +342 -0
  9. package/dist/cli-Dlaym_DD.mjs.map +1 -0
  10. package/dist/contract-space-codegen--gfuyap2.mjs +128 -0
  11. package/dist/contract-space-codegen--gfuyap2.mjs.map +1 -0
  12. package/dist/exports/cli.d.mts +26 -0
  13. package/dist/exports/cli.d.mts.map +1 -0
  14. package/dist/exports/cli.mjs +2 -0
  15. package/dist/exports/config-types.d.mts +38 -0
  16. package/dist/exports/config-types.d.mts.map +1 -0
  17. package/dist/exports/config-types.mjs +66 -0
  18. package/dist/exports/config-types.mjs.map +1 -0
  19. package/dist/exports/contract-psl.d.mts +59 -0
  20. package/dist/exports/contract-psl.d.mts.map +1 -0
  21. package/dist/exports/contract-psl.mjs +97 -0
  22. package/dist/exports/contract-psl.mjs.map +1 -0
  23. package/dist/exports/contract-ts.d.mts +98 -0
  24. package/dist/exports/contract-ts.d.mts.map +1 -0
  25. package/dist/exports/contract-ts.mjs +275 -0
  26. package/dist/exports/contract-ts.mjs.map +1 -0
  27. package/dist/exports/control.d.mts +107 -0
  28. package/dist/exports/control.d.mts.map +1 -0
  29. package/dist/exports/control.mjs +573 -0
  30. package/dist/exports/control.mjs.map +1 -0
  31. package/dist/exports/pack.d.mts +10 -0
  32. package/dist/exports/pack.d.mts.map +1 -0
  33. package/dist/exports/pack.mjs +11 -0
  34. package/dist/exports/pack.mjs.map +1 -0
  35. package/dist/migration-plan-BWhd8BdV.mjs +330 -0
  36. package/dist/migration-plan-BWhd8BdV.mjs.map +1 -0
  37. package/dist/preflight-4jDCNvS0.mjs +119 -0
  38. package/dist/preflight-4jDCNvS0.mjs.map +1 -0
  39. package/dist/psl-interpreter-C0suaXu2.d.mts +45 -0
  40. package/dist/psl-interpreter-C0suaXu2.d.mts.map +1 -0
  41. package/dist/psl-interpreter-C6Q4okuO.mjs +809 -0
  42. package/dist/psl-interpreter-C6Q4okuO.mjs.map +1 -0
  43. package/dist/validate-BLnItEKs.mjs +48 -0
  44. package/dist/validate-BLnItEKs.mjs.map +1 -0
  45. package/package.json +64 -0
@@ -0,0 +1 @@
1
+ {"version":3,"file":"contract-space-codegen--gfuyap2.mjs","names":[],"sources":["../src/core/contract-space-codegen.ts"],"sourcesContent":["import { mkdir, readdir, readFile, writeFile } from \"node:fs/promises\";\nimport type { MigrationMetadata } from \"@prisma/orm-toolchain/migration-tools/metadata\";\nimport { dirname, join, relative } from \"pathe\";\nimport { chainOrderByMetadata, type ChainablePackage } from \"./chain-order\";\n\n/**\n * Options for {@link generateContractSpace}.\n *\n * The CLI (`prisma-idb migration contract-space`) resolves all three\n * paths before calling this function — from explicit flags, or otherwise\n * from `prisma.config.ts` (`contract.output`, `migrations.dir`) via\n * `requireContractPath`/`resolveMigrationsDir` (`cli/migration/paths.ts`).\n * Direct callers (tests) must supply them explicitly.\n */\nexport interface GenerateContractSpaceOptions {\n readonly migrationsDir: string;\n readonly contractPath: string;\n readonly outPath: string;\n /** Output sinks. Default to `process.stdout`/`process.stderr`. */\n readonly out?: (line: string) => void;\n readonly err?: (line: string) => void;\n}\n\ninterface LoadedPackage extends ChainablePackage {\n readonly metadata: MigrationMetadata;\n}\n\n/**\n * Read every migration package under `<migrationsDir>/app/`, validate the\n * chain's connectivity, then emit a generated TypeScript module that\n * JSON-imports each package's `migration.json` + `ops.json` and assembles\n * them into a `ContractSpace` via `contractSpaceFromJson`. The head ref\n * is inlined as `{ hash, invariants }` derived from the last package's\n * metadata — no on-disk `refs/head.json` is written.\n *\n * (We deliberately avoid writing `migrations/refs/` because the framework's\n * contract-space layout treats top-level `migrations/<subdir>/` as a\n * per-space directory; an orphan `refs/` collides with that. Extension\n * packages — postgis, paradedb, etc. — DO write `migrations/refs/head.json`\n * because their package root IS their single space and there's no\n * ambiguity. App-level layouts use `migrations/app/` for the app space, and\n * the head ref for the app space comes from the latest package's `to`.)\n *\n * Idempotent: re-running produces byte-identical output (modulo\n * migration package list changes). Exit code 0 on success.\n */\nexport async function generateContractSpace(opts: GenerateContractSpaceOptions): Promise<number> {\n const out = opts.out ?? ((line: string) => process.stdout.write(line));\n const err = opts.err ?? ((line: string) => process.stderr.write(line));\n const migrationsDir = opts.migrationsDir;\n const appDir = join(migrationsDir, \"app\");\n const contractPath = opts.contractPath;\n const outPath = opts.outPath;\n\n const packages = await loadPackages(appDir, err);\n validateChain(packages);\n\n // Warn when no packages exist — the output module will have an empty\n // migrations list and `hash: \"\"`, which breaks createAutoMigratingIdbClient\n // on a fresh database (walkChain throws: \"no migration with from === null\").\n // The user should run `prisma-idb migration plan` first.\n if (packages.length === 0) {\n err(\n `Warning: no migration packages found in ${relative(process.cwd(), appDir)}/.\\n` +\n \"The generated module will have an empty migrations list, which breaks\\n\" +\n \"`createAutoMigratingIdbClient` on a fresh database.\\n\" +\n \"Run `prisma-idb migration plan` first to create the initial migration.\\n\\n\"\n );\n }\n\n // Emit the generated module. The head ref is derived inline.\n const outDir = dirname(outPath);\n await mkdir(outDir, { recursive: true });\n const source = renderModule({\n outDir,\n contractPath,\n appDir,\n packages,\n });\n await writeFile(outPath, source, \"utf-8\");\n\n out(`Wrote ${outPath} (${packages.length} migration${packages.length === 1 ? \"\" : \"s\"})\\n`);\n return 0;\n}\n\nasync function loadPackages(appDir: string, err: (line: string) => void): Promise<LoadedPackage[]> {\n let dirs: string[];\n try {\n dirs = (await readdir(appDir, { withFileTypes: true })).filter((d) => d.isDirectory()).map((d) => d.name);\n } catch (dirErr) {\n if ((dirErr as NodeJS.ErrnoException).code === \"ENOENT\") return [];\n throw dirErr;\n }\n\n // Load all packages unordered, then chain-walk to derive order. Directory\n // name lexicographic order is unreliable because timestamp formats can\n // mix (e.g. framework's `migration plan` writes `T0337`, hand-authored\n // baselines may use `T120000`). The truth is in metadata.from/to edges.\n const unordered = new Map<string, LoadedPackage>();\n for (const dirName of dirs) {\n const metaPath = join(appDir, dirName, \"migration.json\");\n const opsPath = join(appDir, dirName, \"ops.json\");\n try {\n const metaRaw = await readFile(metaPath, \"utf-8\");\n const metadata = JSON.parse(metaRaw) as MigrationMetadata;\n // existence check for ops.json — we don't parse here because the\n // generated module JSON-imports the file at build time.\n await readFile(opsPath, \"utf-8\");\n unordered.set(dirName, { dirName, metadata });\n } catch (loadErr) {\n err(`Skipping ${dirName}: missing or unreadable migration.json/ops.json ` + `(${(loadErr as Error).message})\\n`);\n }\n }\n\n return chainOrderByMetadata(unordered);\n}\n\n/**\n * No-op — `chainOrderByMetadata` already enforces all invariants during\n * {@link loadPackages}. Kept as a named hook so callers can compose their\n * own package list and re-validate without calling the full load path.\n */\nfunction validateChain(_packages: ReadonlyArray<LoadedPackage>): void {\n // Validation happens inside `chainOrderByMetadata` during load. No-op here.\n}\n\ninterface RenderInput {\n readonly outDir: string;\n readonly contractPath: string;\n readonly appDir: string;\n readonly packages: ReadonlyArray<LoadedPackage>;\n}\n\nfunction renderModule(input: RenderInput): string {\n const contractImportPath = toModuleSpecifier(relative(input.outDir, input.contractPath));\n\n // Local `Contract` import — picks up the IDB-narrowed type from the\n // user's `contract.d.ts` rather than the framework's wider `Contract`.\n // `contract.json` and `contract.d.ts` share a stem, so the .ts module\n // specifier matches via TypeScript's `.json` → bare-import resolution.\n const contractTypeSpecifier = contractImportPath.replace(/\\.json$/i, \"\");\n\n const importLines: string[] = [\n \"// THIS FILE IS AUTO-GENERATED — do not edit by hand.\",\n \"// Regenerate with: prisma-idb migration contract-space\",\n \"\",\n `import type { Contract } from \"${contractTypeSpecifier}\";`,\n 'import { contractSpaceFromJson } from \"@prisma/orm-toolchain/migration-tools/spaces\";',\n `import contractJson from \"${contractImportPath}\" with { type: \"json\" };`,\n ];\n\n for (const pkg of input.packages) {\n const id = identFromDir(pkg.dirName);\n const metaPath = toModuleSpecifier(relative(input.outDir, join(input.appDir, pkg.dirName, \"migration.json\")));\n const opsPath = toModuleSpecifier(relative(input.outDir, join(input.appDir, pkg.dirName, \"ops.json\")));\n importLines.push(`import ${id}_meta from \"${metaPath}\" with { type: \"json\" };`);\n importLines.push(`import ${id}_ops from \"${opsPath}\" with { type: \"json\" };`);\n }\n\n // Inline head ref derivation. The hash comes from the last package's\n // `to`; invariants come from its `providedInvariants` (empty for the\n // IDB app target today — no extension-contributed invariants).\n const last = input.packages[input.packages.length - 1];\n const headRefLiteral =\n last === undefined\n ? '{ hash: \"\", invariants: [] as const }'\n : `{ hash: ${identFromDir(last.dirName)}_meta.to, invariants: (${identFromDir(last.dirName)}_meta.providedInvariants ?? []) as readonly string[] }`;\n\n const migrationsBody =\n input.packages.length === 0\n ? \" migrations: [],\"\n : [\n \" migrations: [\",\n input.packages\n .map((pkg) => {\n const id = identFromDir(pkg.dirName);\n return ` { dirName: ${JSON.stringify(pkg.dirName)}, metadata: ${id}_meta, ops: ${id}_ops },`;\n })\n .join(\"\\n\"),\n \" ],\",\n ].join(\"\\n\");\n\n return [\n ...importLines,\n \"\",\n \"export const contractSpace = contractSpaceFromJson<Contract>({\",\n \" contractJson,\",\n migrationsBody,\n ` headRef: ${headRefLiteral},`,\n \"});\",\n \"\",\n ].join(\"\\n\");\n}\n\nfunction identFromDir(dirName: string): string {\n return `mig_${dirName.replace(/[^a-zA-Z0-9_]/g, \"_\")}`;\n}\n\n/**\n * Coerce a `pathe` relative path into a TypeScript module specifier.\n * - Adds a leading `./` if the path doesn't already start with `.` or `/`.\n * - Leaves absolute and parent-relative paths alone.\n */\nfunction toModuleSpecifier(p: string): string {\n if (p.startsWith(\".\") || p.startsWith(\"/\")) return p;\n return `./${p}`;\n}\n"],"mappings":"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"}
@@ -0,0 +1,26 @@
1
+ import { Cli, HostProcess } from "@prisma/cli-engine";
2
+ //#region src/cli/family.d.ts
3
+ /**
4
+ * The unit this package contributes to a `@prisma/cli-engine` shell: its
5
+ * config section (reused from the ORM family, see `config-section.ts`) and
6
+ * its 3 commands. These have no generic equivalent — the real `prisma` CLI's
7
+ * `migration new`/`plan`/etc. work against a live database or a SQL/Mongo
8
+ * on-disk model; ours works against `fake-indexeddb` and a hand-rolled
9
+ * contract-space convention.
10
+ */
11
+ declare const idbCommandFamily: import("@prisma/cli-engine").CommandFamily;
12
+ //#endregion
13
+ //#region src/cli/cli.d.ts
14
+ declare const BIN_NAME = "prisma-idb";
15
+ declare const BIN_GROUPS: {
16
+ readonly migration: {
17
+ readonly brief: "On-disk migration management commands";
18
+ readonly description: string;
19
+ };
20
+ };
21
+ declare function createIdbCli(): Cli;
22
+ /** Parses, executes and settles one invocation; returns the exit code. */
23
+ declare function runIdbCli(proc: HostProcess): Promise<number>;
24
+ //#endregion
25
+ export { BIN_GROUPS, BIN_NAME, createIdbCli, idbCommandFamily, runIdbCli };
26
+ //# sourceMappingURL=cli.d.mts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cli.d.mts","names":[],"sources":["../../src/cli/family.ts","../../src/cli/cli.ts"],"mappings":";;;;;;;;;;cAqBa,+CAAgB;;;cCfhB;cAEA;;;;;;iBASG,gBAAgB;;iBA6DV,UAAU,MAAM,cAAc"}
@@ -0,0 +1,2 @@
1
+ import { a as idbCommandFamily, i as runIdbCli, n as BIN_NAME, r as createIdbCli, t as BIN_GROUPS } from "../cli-Dlaym_DD.mjs";
2
+ export { BIN_GROUPS, BIN_NAME, createIdbCli, idbCommandFamily, runIdbCli };
@@ -0,0 +1,38 @@
1
+ import { Contract } from "@prisma/orm-framework/contract/types";
2
+ import { ContractConfig, PrismaNextConfig, defineConfig as defineConfig$1 } from "@prisma/orm-framework/config/config-types";
3
+ //#region src/exports/config-types.d.ts
4
+ declare const defineConfig: typeof defineConfig$1;
5
+ /**
6
+ * Wraps an in-memory contract object for use in `prisma.config.ts`.
7
+ *
8
+ * Use this with the no-emit (TypeScript-first) workflow per ADR 006.
9
+ *
10
+ * @example
11
+ * ```ts
12
+ * import { typescriptContract } from '@prisma-idb/family-idb/config-types';
13
+ * import contract from './prisma/contract';
14
+ *
15
+ * export default {
16
+ * family: idbFamily,
17
+ * target: idbTarget,
18
+ * contract: typescriptContract(contract, 'src/prisma/contract.json'),
19
+ * };
20
+ * ```
21
+ */
22
+ declare function typescriptContract(contract: Contract, output?: string): ContractConfig;
23
+ /**
24
+ * Loads a contract from a TypeScript file at `contractPath` and wraps it for
25
+ * use in `prisma.config.ts`. The file must export the contract as
26
+ * `default` or `contract`.
27
+ *
28
+ * @example
29
+ * ```ts
30
+ * export default {
31
+ * contract: typescriptContractFromPath('./prisma/contract.ts'),
32
+ * };
33
+ * ```
34
+ */
35
+ declare function typescriptContractFromPath(contractPath: string, output?: string): ContractConfig;
36
+ //#endregion
37
+ export { type PrismaNextConfig, defineConfig, typescriptContract, typescriptContractFromPath };
38
+ //# sourceMappingURL=config-types.d.mts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config-types.d.mts","names":[],"sources":["../../src/exports/config-types.ts"],"mappings":";;;cAYa,qBAAY;;;;;;;;;;;;;;;;;;iBAyBT,mBAAmB,UAAU,UAAU,kBAAkB;;;;;;;;;;;;;iBAqBzD,2BAA2B,sBAAsB,kBAAkB"}
@@ -0,0 +1,66 @@
1
+ import { ok } from "@prisma/orm-framework/utils/result";
2
+ import { extname } from "pathe";
3
+ import { pathToFileURL } from "node:url";
4
+ import { defineConfig as defineConfig$1 } from "@prisma/orm-framework/config/config-types";
5
+ //#region src/exports/config-types.ts
6
+ const defineConfig = defineConfig$1;
7
+ function defaultOutputFromContractPath(contractPath) {
8
+ const ext = extname(contractPath);
9
+ if (ext.length === 0) return `${contractPath}.json`;
10
+ return `${contractPath.slice(0, -ext.length)}.json`;
11
+ }
12
+ /**
13
+ * Wraps an in-memory contract object for use in `prisma.config.ts`.
14
+ *
15
+ * Use this with the no-emit (TypeScript-first) workflow per ADR 006.
16
+ *
17
+ * @example
18
+ * ```ts
19
+ * import { typescriptContract } from '@prisma-idb/family-idb/config-types';
20
+ * import contract from './prisma/contract';
21
+ *
22
+ * export default {
23
+ * family: idbFamily,
24
+ * target: idbTarget,
25
+ * contract: typescriptContract(contract, 'src/prisma/contract.json'),
26
+ * };
27
+ * ```
28
+ */
29
+ function typescriptContract(contract, output) {
30
+ return {
31
+ source: { load: async () => ok(contract) },
32
+ ...output !== void 0 ? { output } : {}
33
+ };
34
+ }
35
+ /**
36
+ * Loads a contract from a TypeScript file at `contractPath` and wraps it for
37
+ * use in `prisma.config.ts`. The file must export the contract as
38
+ * `default` or `contract`.
39
+ *
40
+ * @example
41
+ * ```ts
42
+ * export default {
43
+ * contract: typescriptContractFromPath('./prisma/contract.ts'),
44
+ * };
45
+ * ```
46
+ */
47
+ function typescriptContractFromPath(contractPath, output) {
48
+ return {
49
+ source: {
50
+ inputs: [contractPath],
51
+ load: async (context) => {
52
+ const [absolutePath] = context.resolvedInputs;
53
+ if (absolutePath === void 0) throw new Error("typescriptContractFromPath: context.resolvedInputs is empty. The CLI config loader should populate it positional-matched with source.inputs.");
54
+ const mod = await import(pathToFileURL(absolutePath).href);
55
+ const contract = mod.default ?? mod.contract;
56
+ if (contract === void 0) throw new Error(`typescriptContractFromPath: module at "${absolutePath}" has no "default" or "contract" export.`);
57
+ return ok(contract);
58
+ }
59
+ },
60
+ output: output ?? defaultOutputFromContractPath(contractPath)
61
+ };
62
+ }
63
+ //#endregion
64
+ export { defineConfig, typescriptContract, typescriptContractFromPath };
65
+
66
+ //# sourceMappingURL=config-types.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config-types.mjs","names":["coreDefineConfig"],"sources":["../../src/exports/config-types.ts"],"sourcesContent":["// Adapted from Prisma ORM's SQL contract config helpers.\n// These helpers are fully family-agnostic — they wrap any Contract object\n// in a ContractSourceProvider that the Prisma CLI config loader understands.\nimport { pathToFileURL } from \"node:url\";\nimport type { ContractConfig, PrismaNextConfig } from \"@prisma/orm-framework/config/config-types\";\nimport { defineConfig as coreDefineConfig } from \"@prisma/orm-framework/config/config-types\";\nimport type { Contract } from \"@prisma/orm-framework/contract/types\";\nimport { ok } from \"@prisma/orm-framework/utils/result\";\nimport { extname } from \"pathe\";\n\n// Re-export defineConfig so users only need @prisma-idb/family-idb.\nexport { type PrismaNextConfig };\nexport const defineConfig = coreDefineConfig;\n\nfunction defaultOutputFromContractPath(contractPath: string): string {\n const ext = extname(contractPath);\n if (ext.length === 0) return `${contractPath}.json`;\n return `${contractPath.slice(0, -ext.length)}.json`;\n}\n\n/**\n * Wraps an in-memory contract object for use in `prisma.config.ts`.\n *\n * Use this with the no-emit (TypeScript-first) workflow per ADR 006.\n *\n * @example\n * ```ts\n * import { typescriptContract } from '@prisma-idb/family-idb/config-types';\n * import contract from './prisma/contract';\n *\n * export default {\n * family: idbFamily,\n * target: idbTarget,\n * contract: typescriptContract(contract, 'src/prisma/contract.json'),\n * };\n * ```\n */\nexport function typescriptContract(contract: Contract, output?: string): ContractConfig {\n return {\n source: {\n load: async () => ok(contract),\n },\n ...(output !== undefined ? { output } : {}),\n };\n}\n\n/**\n * Loads a contract from a TypeScript file at `contractPath` and wraps it for\n * use in `prisma.config.ts`. The file must export the contract as\n * `default` or `contract`.\n *\n * @example\n * ```ts\n * export default {\n * contract: typescriptContractFromPath('./prisma/contract.ts'),\n * };\n * ```\n */\nexport function typescriptContractFromPath(contractPath: string, output?: string): ContractConfig {\n return {\n source: {\n inputs: [contractPath],\n load: async (context) => {\n const [absolutePath] = context.resolvedInputs;\n if (absolutePath === undefined) {\n throw new Error(\n \"typescriptContractFromPath: context.resolvedInputs is empty. The CLI config loader should populate it positional-matched with source.inputs.\"\n );\n }\n const mod = await import(pathToFileURL(absolutePath).href);\n const contract: Contract | undefined = mod.default ?? mod.contract;\n if (contract === undefined) {\n throw new Error(\n `typescriptContractFromPath: module at \"${absolutePath}\" has no \"default\" or \"contract\" export.`\n );\n }\n return ok(contract);\n },\n },\n output: output ?? defaultOutputFromContractPath(contractPath),\n };\n}\n"],"mappings":";;;;;AAYA,MAAa,eAAeA;AAE5B,SAAS,8BAA8B,cAA8B;CACnE,MAAM,MAAM,QAAQ,YAAY;CAChC,IAAI,IAAI,WAAW,GAAG,OAAO,GAAG,aAAa;CAC7C,OAAO,GAAG,aAAa,MAAM,GAAG,CAAC,IAAI,MAAM,EAAE;AAC/C;;;;;;;;;;;;;;;;;;AAmBA,SAAgB,mBAAmB,UAAoB,QAAiC;CACtF,OAAO;EACL,QAAQ,EACN,MAAM,YAAY,GAAG,QAAQ,EAC/B;EACA,GAAI,WAAW,KAAA,IAAY,EAAE,OAAO,IAAI,CAAC;CAC3C;AACF;;;;;;;;;;;;;AAcA,SAAgB,2BAA2B,cAAsB,QAAiC;CAChG,OAAO;EACL,QAAQ;GACN,QAAQ,CAAC,YAAY;GACrB,MAAM,OAAO,YAAY;IACvB,MAAM,CAAC,gBAAgB,QAAQ;IAC/B,IAAI,iBAAiB,KAAA,GACnB,MAAM,IAAI,MACR,8IACF;IAEF,MAAM,MAAM,MAAM,OAAO,cAAc,YAAY,CAAC,CAAC;IACrD,MAAM,WAAiC,IAAI,WAAW,IAAI;IAC1D,IAAI,aAAa,KAAA,GACf,MAAM,IAAI,MACR,0CAA0C,aAAa,yCACzD;IAEF,OAAO,GAAG,QAAQ;GACpB;EACF;EACA,QAAQ,UAAU,8BAA8B,YAAY;CAC9D;AACF"}
@@ -0,0 +1,59 @@
1
+ import { n as InterpretPslOptions, r as interpretPslDocumentToIdbContract, t as ContractProjection } from "../psl-interpreter-C0suaXu2.mjs";
2
+ import { ContractConfig } from "@prisma/orm-framework/config/config-types";
3
+ //#region src/core/psl-provider.d.ts
4
+ /**
5
+ * Removes `@idb.exclude`/`@@idb.exclude` from raw PSL text — the `idb`
6
+ * namespace family-idb owns (`psl-interpreter.ts`'s `IDB_EXCLUDE_ATTR`).
7
+ * A foreign PSL parser (e.g. the SQL family's) doesn't recognize this
8
+ * namespace and hard-errors on it (`PSL_EXTENSION_NAMESPACE_NOT_COMPOSED`);
9
+ * stripping it is the text-level equivalent of what family-idb itself
10
+ * already does for these same fields under `projection: "full"`, where the
11
+ * attribute is documented as a no-op. Use this when sharing a schema.prisma
12
+ * authored for family-idb with a different family's schema loader — the
13
+ * server always wants every field these attributes would otherwise hide
14
+ * from the client.
15
+ */
16
+ declare function stripIdbExcludeAttributes(schema: string): string;
17
+ interface PrismaIdbContractOptions {
18
+ readonly output?: string;
19
+ /**
20
+ * `"client"` projects out anything marked `@idb.exclude`/`@@idb.exclude`
21
+ * (ADR 012). Pass a distinct `output` alongside this so the client and
22
+ * full/server contracts don't collide on the same file.
23
+ * @default "full"
24
+ */
25
+ readonly projection?: ContractProjection;
26
+ /**
27
+ * Runs on the raw schema text right after it's read, before parsing.
28
+ * Lets a downstream package (e.g. `@prisma-idb/sync-server`) append
29
+ * synthetic model/enum declarations — the appended text goes through the
30
+ * exact same parse → interpret → hash pipeline as hand-authored PSL, so
31
+ * `storageHash` reflects it correctly (it's computed *inside*
32
+ * `interpretPslDocumentToIdbContract`, from whatever this returns).
33
+ */
34
+ readonly injectSchemaText?: (schema: string) => string;
35
+ }
36
+ /**
37
+ * Creates a `ContractConfig` that reads an IDB schema from a `.prisma` file.
38
+ *
39
+ * Use this in `prisma.config.ts` as the `contract:` value when you prefer
40
+ * PSL authoring over the TypeScript-first `defineContract()` helper.
41
+ *
42
+ * @example
43
+ * ```ts
44
+ * import { defineConfig } from '@prisma-idb/family-idb/config-types';
45
+ * import { prismaIdbContract } from '@prisma-idb/family-idb/contract-psl';
46
+ *
47
+ * export default defineConfig({
48
+ * // ...
49
+ * contract: prismaIdbContract('./src/prisma/schema.prisma'),
50
+ * });
51
+ * ```
52
+ *
53
+ * The emitted `contract.json` lands next to the schema file by default
54
+ * (`schema.prisma` → `contract.json`). Override with `options.output`.
55
+ */
56
+ declare function prismaIdbContract(schemaPath: string, options?: PrismaIdbContractOptions): ContractConfig;
57
+ //#endregion
58
+ export { type ContractProjection, type InterpretPslOptions, type PrismaIdbContractOptions, interpretPslDocumentToIdbContract, prismaIdbContract, stripIdbExcludeAttributes };
59
+ //# sourceMappingURL=contract-psl.d.mts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"contract-psl.d.mts","names":[],"sources":["../../src/core/psl-provider.ts"],"mappings":";;;;;;;;;;;;;;;iBAuBgB,0BAA0B;UA6BzB;WACN;;;;;;;WAOA,aAAa;;;;;;;;;WASb,oBAAoB;;;;;;;;;;;;;;;;;;;;;;iBAuBf,kBAAkB,oBAAoB,UAAU,2BAA2B"}
@@ -0,0 +1,97 @@
1
+ import { t as interpretPslDocumentToIdbContract } from "../psl-interpreter-C6Q4okuO.mjs";
2
+ import { notOk } from "@prisma/orm-framework/utils/result";
3
+ import { readFile } from "node:fs/promises";
4
+ import { buildSymbolTable, rangeToPslSpan } from "@prisma/orm-framework/psl-parser";
5
+ import { withSeedDiagnostics } from "@prisma/orm-framework/psl-parser/interpret";
6
+ import { parse } from "@prisma/orm-framework/psl-parser/syntax";
7
+ import { basename, extname } from "pathe";
8
+ //#region src/core/psl-provider.ts
9
+ /**
10
+ * Removes `@idb.exclude`/`@@idb.exclude` from raw PSL text — the `idb`
11
+ * namespace family-idb owns (`psl-interpreter.ts`'s `IDB_EXCLUDE_ATTR`).
12
+ * A foreign PSL parser (e.g. the SQL family's) doesn't recognize this
13
+ * namespace and hard-errors on it (`PSL_EXTENSION_NAMESPACE_NOT_COMPOSED`);
14
+ * stripping it is the text-level equivalent of what family-idb itself
15
+ * already does for these same fields under `projection: "full"`, where the
16
+ * attribute is documented as a no-op. Use this when sharing a schema.prisma
17
+ * authored for family-idb with a different family's schema loader — the
18
+ * server always wants every field these attributes would otherwise hide
19
+ * from the client.
20
+ */
21
+ function stripIdbExcludeAttributes(schema) {
22
+ return schema.replace(/^[ \t]*@@idb\.exclude\b.*\n?/gm, "").replace(/[ \t]*@idb\.exclude\b/g, "");
23
+ }
24
+ function defaultOutputFromSchemaPath(schemaPath) {
25
+ const ext = extname(schemaPath);
26
+ if (ext.length === 0) return `${schemaPath}.json`;
27
+ const base = schemaPath.slice(0, -ext.length);
28
+ if (basename(base) === "schema") return `${base.slice(0, -6)}contract.json`;
29
+ return `${base}.json`;
30
+ }
31
+ function mapParseDiagnostics(diagnostics, sourceFile, sourceId) {
32
+ return diagnostics.map((d) => ({
33
+ code: d.code,
34
+ message: d.message,
35
+ sourceId,
36
+ span: rangeToPslSpan(d.range, sourceFile)
37
+ }));
38
+ }
39
+ /**
40
+ * Creates a `ContractConfig` that reads an IDB schema from a `.prisma` file.
41
+ *
42
+ * Use this in `prisma.config.ts` as the `contract:` value when you prefer
43
+ * PSL authoring over the TypeScript-first `defineContract()` helper.
44
+ *
45
+ * @example
46
+ * ```ts
47
+ * import { defineConfig } from '@prisma-idb/family-idb/config-types';
48
+ * import { prismaIdbContract } from '@prisma-idb/family-idb/contract-psl';
49
+ *
50
+ * export default defineConfig({
51
+ * // ...
52
+ * contract: prismaIdbContract('./src/prisma/schema.prisma'),
53
+ * });
54
+ * ```
55
+ *
56
+ * The emitted `contract.json` lands next to the schema file by default
57
+ * (`schema.prisma` → `contract.json`). Override with `options.output`.
58
+ */
59
+ function prismaIdbContract(schemaPath, options) {
60
+ return {
61
+ source: {
62
+ inputs: [schemaPath],
63
+ load: async (context) => {
64
+ const [absoluteSchemaPath] = context.resolvedInputs;
65
+ if (absoluteSchemaPath === void 0) throw new Error("prismaIdbContract: context.resolvedInputs is empty. The CLI config loader should populate it positional-matched with source.inputs.");
66
+ let schema;
67
+ try {
68
+ schema = await readFile(absoluteSchemaPath, "utf-8");
69
+ } catch (error) {
70
+ const message = String(error);
71
+ return notOk({
72
+ summary: `Failed to read Prisma schema at "${schemaPath}"`,
73
+ diagnostics: [{
74
+ code: "PSL_SCHEMA_READ_FAILED",
75
+ message,
76
+ sourceId: schemaPath
77
+ }]
78
+ });
79
+ }
80
+ if (options?.injectSchemaText) schema = options.injectSchemaText(schema);
81
+ const { document, sourceFile, diagnostics: parseDiagnostics } = parse(schema);
82
+ const { table, diagnostics: symbolDiagnostics } = buildSymbolTable({
83
+ document,
84
+ sourceFile,
85
+ pslBlockDescriptors: {}
86
+ });
87
+ const seedDiagnostics = [...mapParseDiagnostics(parseDiagnostics, sourceFile, schemaPath), ...mapParseDiagnostics(symbolDiagnostics, sourceFile, schemaPath)];
88
+ return withSeedDiagnostics(interpretPslDocumentToIdbContract(table, schemaPath, options?.projection !== void 0 ? { projection: options.projection } : void 0), seedDiagnostics);
89
+ }
90
+ },
91
+ output: options?.output ?? defaultOutputFromSchemaPath(schemaPath)
92
+ };
93
+ }
94
+ //#endregion
95
+ export { interpretPslDocumentToIdbContract, prismaIdbContract, stripIdbExcludeAttributes };
96
+
97
+ //# sourceMappingURL=contract-psl.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"contract-psl.mjs","names":[],"sources":["../../src/core/psl-provider.ts"],"sourcesContent":["import { readFile } from \"node:fs/promises\";\nimport type { ContractConfig, ContractSourceDiagnostic } from \"@prisma/orm-framework/config/config-types\";\nimport { buildSymbolTable, rangeToPslSpan } from \"@prisma/orm-framework/psl-parser\";\nimport { withSeedDiagnostics } from \"@prisma/orm-framework/psl-parser/interpret\";\nimport type { ParseDiagnostic, SourceFile } from \"@prisma/orm-framework/psl-parser/syntax\";\nimport { parse } from \"@prisma/orm-framework/psl-parser/syntax\";\nimport { notOk } from \"@prisma/orm-framework/utils/result\";\nimport { extname, basename } from \"pathe\";\nimport type { ContractProjection } from \"./psl-interpreter\";\nimport { interpretPslDocumentToIdbContract } from \"./psl-interpreter\";\n\n/**\n * Removes `@idb.exclude`/`@@idb.exclude` from raw PSL text — the `idb`\n * namespace family-idb owns (`psl-interpreter.ts`'s `IDB_EXCLUDE_ATTR`).\n * A foreign PSL parser (e.g. the SQL family's) doesn't recognize this\n * namespace and hard-errors on it (`PSL_EXTENSION_NAMESPACE_NOT_COMPOSED`);\n * stripping it is the text-level equivalent of what family-idb itself\n * already does for these same fields under `projection: \"full\"`, where the\n * attribute is documented as a no-op. Use this when sharing a schema.prisma\n * authored for family-idb with a different family's schema loader — the\n * server always wants every field these attributes would otherwise hide\n * from the client.\n */\nexport function stripIdbExcludeAttributes(schema: string): string {\n return schema\n .replace(/^[ \\t]*@@idb\\.exclude\\b.*\\n?/gm, \"\") // model-level: drop the whole line, incl. trailing comments\n .replace(/[ \\t]*@idb\\.exclude\\b/g, \"\"); // field-level: drop just the token, keep the field\n}\n\nfunction defaultOutputFromSchemaPath(schemaPath: string): string {\n const ext = extname(schemaPath);\n if (ext.length === 0) return `${schemaPath}.json`;\n const base = schemaPath.slice(0, -ext.length);\n if (basename(base) === \"schema\") {\n return `${base.slice(0, -\"schema\".length)}contract.json`;\n }\n return `${base}.json`;\n}\n\nfunction mapParseDiagnostics(\n diagnostics: readonly ParseDiagnostic[],\n sourceFile: SourceFile,\n sourceId: string\n): ContractSourceDiagnostic[] {\n return diagnostics.map((d) => ({\n code: d.code as string,\n message: d.message,\n sourceId,\n span: rangeToPslSpan(d.range, sourceFile),\n }));\n}\n\nexport interface PrismaIdbContractOptions {\n readonly output?: string;\n /**\n * `\"client\"` projects out anything marked `@idb.exclude`/`@@idb.exclude`\n * (ADR 012). Pass a distinct `output` alongside this so the client and\n * full/server contracts don't collide on the same file.\n * @default \"full\"\n */\n readonly projection?: ContractProjection;\n /**\n * Runs on the raw schema text right after it's read, before parsing.\n * Lets a downstream package (e.g. `@prisma-idb/sync-server`) append\n * synthetic model/enum declarations — the appended text goes through the\n * exact same parse → interpret → hash pipeline as hand-authored PSL, so\n * `storageHash` reflects it correctly (it's computed *inside*\n * `interpretPslDocumentToIdbContract`, from whatever this returns).\n */\n readonly injectSchemaText?: (schema: string) => string;\n}\n\n/**\n * Creates a `ContractConfig` that reads an IDB schema from a `.prisma` file.\n *\n * Use this in `prisma.config.ts` as the `contract:` value when you prefer\n * PSL authoring over the TypeScript-first `defineContract()` helper.\n *\n * @example\n * ```ts\n * import { defineConfig } from '@prisma-idb/family-idb/config-types';\n * import { prismaIdbContract } from '@prisma-idb/family-idb/contract-psl';\n *\n * export default defineConfig({\n * // ...\n * contract: prismaIdbContract('./src/prisma/schema.prisma'),\n * });\n * ```\n *\n * The emitted `contract.json` lands next to the schema file by default\n * (`schema.prisma` → `contract.json`). Override with `options.output`.\n */\nexport function prismaIdbContract(schemaPath: string, options?: PrismaIdbContractOptions): ContractConfig {\n return {\n source: {\n inputs: [schemaPath],\n load: async (context) => {\n const [absoluteSchemaPath] = context.resolvedInputs;\n if (absoluteSchemaPath === undefined) {\n throw new Error(\n \"prismaIdbContract: context.resolvedInputs is empty. The CLI config loader should populate it positional-matched with source.inputs.\"\n );\n }\n\n let schema: string;\n try {\n schema = await readFile(absoluteSchemaPath, \"utf-8\");\n } catch (error) {\n const message = String(error);\n return notOk({\n summary: `Failed to read Prisma schema at \"${schemaPath}\"`,\n diagnostics: [\n {\n code: \"PSL_SCHEMA_READ_FAILED\",\n message,\n sourceId: schemaPath,\n },\n ],\n });\n }\n\n if (options?.injectSchemaText) {\n schema = options.injectSchemaText(schema);\n }\n\n const { document, sourceFile, diagnostics: parseDiagnostics } = parse(schema);\n const { table, diagnostics: symbolDiagnostics } = buildSymbolTable({\n document,\n sourceFile,\n pslBlockDescriptors: {},\n });\n\n // Do not short-circuit on provider-level diagnostics — the fault-tolerant\n // parser/symbol-table still produce a usable table, and the interpreter\n // may surface its own diagnostics in the same response.\n const seedDiagnostics = [\n ...mapParseDiagnostics(parseDiagnostics, sourceFile, schemaPath),\n ...mapParseDiagnostics(symbolDiagnostics, sourceFile, schemaPath),\n ];\n\n const interpreted = withSeedDiagnostics(\n interpretPslDocumentToIdbContract(\n table,\n schemaPath,\n options?.projection !== undefined ? { projection: options.projection } : undefined\n ),\n seedDiagnostics\n );\n // Return the full Result so seed diagnostics (parse + symbol-table\n // findings) survive the success path — the config loader surfaces\n // them alongside the contract.\n return interpreted;\n },\n },\n output: options?.output ?? defaultOutputFromSchemaPath(schemaPath),\n };\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;AAuBA,SAAgB,0BAA0B,QAAwB;CAChE,OAAO,OACJ,QAAQ,kCAAkC,EAAE,CAAC,CAC7C,QAAQ,0BAA0B,EAAE;AACzC;AAEA,SAAS,4BAA4B,YAA4B;CAC/D,MAAM,MAAM,QAAQ,UAAU;CAC9B,IAAI,IAAI,WAAW,GAAG,OAAO,GAAG,WAAW;CAC3C,MAAM,OAAO,WAAW,MAAM,GAAG,CAAC,IAAI,MAAM;CAC5C,IAAI,SAAS,IAAI,MAAM,UACrB,OAAO,GAAG,KAAK,MAAM,GAAG,EAAgB,EAAE;CAE5C,OAAO,GAAG,KAAK;AACjB;AAEA,SAAS,oBACP,aACA,YACA,UAC4B;CAC5B,OAAO,YAAY,KAAK,OAAO;EAC7B,MAAM,EAAE;EACR,SAAS,EAAE;EACX;EACA,MAAM,eAAe,EAAE,OAAO,UAAU;CAC1C,EAAE;AACJ;;;;;;;;;;;;;;;;;;;;;AA0CA,SAAgB,kBAAkB,YAAoB,SAAoD;CACxG,OAAO;EACL,QAAQ;GACN,QAAQ,CAAC,UAAU;GACnB,MAAM,OAAO,YAAY;IACvB,MAAM,CAAC,sBAAsB,QAAQ;IACrC,IAAI,uBAAuB,KAAA,GACzB,MAAM,IAAI,MACR,qIACF;IAGF,IAAI;IACJ,IAAI;KACF,SAAS,MAAM,SAAS,oBAAoB,OAAO;IACrD,SAAS,OAAO;KACd,MAAM,UAAU,OAAO,KAAK;KAC5B,OAAO,MAAM;MACX,SAAS,oCAAoC,WAAW;MACxD,aAAa,CACX;OACE,MAAM;OACN;OACA,UAAU;MACZ,CACF;KACF,CAAC;IACH;IAEA,IAAI,SAAS,kBACX,SAAS,QAAQ,iBAAiB,MAAM;IAG1C,MAAM,EAAE,UAAU,YAAY,aAAa,qBAAqB,MAAM,MAAM;IAC5E,MAAM,EAAE,OAAO,aAAa,sBAAsB,iBAAiB;KACjE;KACA;KACA,qBAAqB,CAAC;IACxB,CAAC;IAKD,MAAM,kBAAkB,CACtB,GAAG,oBAAoB,kBAAkB,YAAY,UAAU,GAC/D,GAAG,oBAAoB,mBAAmB,YAAY,UAAU,CAClE;IAaA,OAXoB,oBAClB,kCACE,OACA,YACA,SAAS,eAAe,KAAA,IAAY,EAAE,YAAY,QAAQ,WAAW,IAAI,KAAA,CAC3E,GACA,eAKe;GACnB;EACF;EACA,QAAQ,SAAS,UAAU,4BAA4B,UAAU;CACnE;AACF"}
@@ -0,0 +1,98 @@
1
+ import { t as ContractProjection } from "../psl-interpreter-C0suaXu2.mjs";
2
+ import { Contract } from "@prisma/orm-framework/contract/types";
3
+ import { IdbReferentialAction, IdbStorage } from "@prisma-idb/target-idb/pack";
4
+ //#region src/core/contract-builder.d.ts
5
+ type PrismaScalarType = "String" | "Int" | "Float" | "Boolean" | "DateTime" | "BigInt" | "Decimal" | "Json" | "Bytes";
6
+ /**
7
+ * A field spec string: the Prisma scalar type name, optionally suffixed with
8
+ * `?` to indicate the field is nullable (e.g. `"String"`, `"Int?"`, `"DateTime?"`).
9
+ */
10
+ type FieldSpec = PrismaScalarType | `${PrismaScalarType}?`;
11
+ type RelationDef = {
12
+ readonly to: string;
13
+ readonly cardinality: "1:1" | "1:N" | "N:1";
14
+ readonly on: {
15
+ readonly local: readonly string[];
16
+ readonly target: readonly string[];
17
+ };
18
+ readonly onDelete?: IdbReferentialAction;
19
+ readonly onUpdate?: IdbReferentialAction;
20
+ };
21
+ type IndexDef = {
22
+ readonly keyPath: string;
23
+ readonly unique?: boolean;
24
+ readonly multiEntry?: boolean;
25
+ };
26
+ type ModelDef = {
27
+ readonly store: string;
28
+ readonly key: string;
29
+ /** All scalar fields on the model. Use `"Type"` for non-nullable, `"Type?"` for nullable. */
30
+ readonly fields: Record<string, FieldSpec>;
31
+ readonly indexes?: Record<string, IndexDef>;
32
+ readonly relations?: Record<string, RelationDef>;
33
+ /**
34
+ * Literal default values, keyed by field name — feeds the `setDefault`
35
+ * referential action (a child's FK field is reset to its own declared
36
+ * default when its parent is deleted/updated with `onDelete`/`onUpdate:
37
+ * "setDefault"`). A sibling map to `fields`, deliberately not folded into
38
+ * `FieldSpec` (a bare type string) to avoid widening that type.
39
+ *
40
+ * Does NOT feed `create()`'s default-filling — the TS-DSL authoring path
41
+ * has no `execution.mutations.defaults` support at all yet (a separate,
42
+ * larger, pre-existing gap). Use the PSL authoring path's `@default(...)`
43
+ * if you need create-time defaults; this map only backs `setDefault`.
44
+ */
45
+ readonly fieldDefaults?: Record<string, string | number | boolean>;
46
+ /** Server-only model — dropped when `defineContract` runs with `{ projection: "client" }`. See ADR 012. */
47
+ readonly exclude?: boolean;
48
+ /** Server-only fields on an otherwise-synced model — dropped in client projection. See ADR 012. */
49
+ readonly excludeFields?: readonly string[];
50
+ };
51
+ type DefineContractInput = {
52
+ /** Pass the default export of `@prisma-idb/family-idb/pack`. */
53
+ readonly family: {
54
+ readonly familyId: "idb";
55
+ readonly id: string;
56
+ };
57
+ /** Pass the default export of `@prisma-idb/target-idb/pack`. */
58
+ readonly target: {
59
+ readonly targetId: string;
60
+ readonly id: string;
61
+ };
62
+ readonly models: Record<string, ModelDef>;
63
+ };
64
+ type DefineContractOptions = {
65
+ /** @default "full" */
66
+ readonly projection?: ContractProjection;
67
+ };
68
+ /**
69
+ * Builds a typed IDB contract from a developer-friendly model definition.
70
+ *
71
+ * This is the TypeScript-first (no-emit) authoring path per ADR 006. The
72
+ * returned contract object can be passed directly to `createIdbClient()` or
73
+ * to `typescriptContract()` for config-file usage.
74
+ *
75
+ * @example
76
+ * ```ts
77
+ * import { defineContract } from '@prisma-idb/family-idb/contract-ts';
78
+ * import idbFamily from '@prisma-idb/family-idb/pack';
79
+ * import idbTarget from '@prisma-idb/target-idb/pack';
80
+ *
81
+ * export default defineContract({
82
+ * family: idbFamily,
83
+ * target: idbTarget,
84
+ * models: {
85
+ * User: {
86
+ * store: 'users',
87
+ * key: 'id',
88
+ * fields: { id: 'String', name: 'String?', email: 'String' },
89
+ * indexes: { byEmail: { keyPath: 'email', unique: true } },
90
+ * },
91
+ * },
92
+ * });
93
+ * ```
94
+ */
95
+ declare function defineContract(input: DefineContractInput, options?: DefineContractOptions): Contract<IdbStorage>;
96
+ //#endregion
97
+ export { type ContractProjection, type DefineContractInput, type DefineContractOptions, type FieldSpec, type IndexDef, type ModelDef, type RelationDef, defineContract };
98
+ //# sourceMappingURL=contract-ts.d.mts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"contract-ts.d.mts","names":[],"sources":["../../src/core/contract-builder.ts"],"mappings":";;;;KAgBK;;;;;KAMO,YAAY,sBAAsB;KAgBlC;WACD;WACA;WACA;aACE;aACA;;WAEF,WAAW;WACX,WAAW;;KAGV;WACD;WACA;WACA;;KAGC;WACD;WACA;;WAEA,QAAQ,eAAe;WACvB,UAAU,eAAe;WACzB,YAAY,eAAe;;;;;;;;;;;;;WAa3B,gBAAgB;;WAEhB;;WAEA;;KAGC;;WAED;aAAmB;aAA0B;;;WAE7C;aAAmB;aAA2B;;WAC9C,QAAQ,eAAe;;KAGtB;;WAED,aAAa;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBAoUR,eAAe,OAAO,qBAAqB,UAAU,wBAAwB,SAAS"}