| 1 | import * as Exit from "effect/Exit"; |
| 2 | import * as Schema from "effect/Schema"; |
| 3 | |
| 4 | import { T3ProjectFile, T3_PROJECT_FILE_SCHEMA_URL } from "@t3tools/contracts"; |
| 5 | |
| 6 | import { fromLenientJson } from "./schemaJson.ts"; |
| 7 | |
| 8 | /** |
| 9 | * Codec between the raw `t3.json` file contents (lenient JSONC string) and the |
| 10 | * decoded {@link T3ProjectFile}. |
| 11 | */ |
| 12 | export const T3ProjectFileFromJson = fromLenientJson(T3ProjectFile); |
| 13 | |
| 14 | const decodeT3ProjectFile = Schema.decodeExit(T3ProjectFileFromJson); |
| 15 | |
| 16 | /** |
| 17 | * Decode raw `t3.json` contents, treating invalid or malformed files as |
| 18 | * absent. Clients use this to read optional defaults (scripts, thread env |
| 19 | * mode) without surfacing decode errors to the user. |
| 20 | */ |
| 21 | export function parseT3ProjectFile(contents: string): T3ProjectFile | null { |
| 22 | const decoded = decodeT3ProjectFile(contents); |
| 23 | return Exit.isSuccess(decoded) ? decoded.value : null; |
| 24 | } |
| 25 | |
| 26 | /** |
| 27 | * Build the publishable JSON Schema document for `t3.json` (draft 2020-12). |
| 28 | * |
| 29 | * Served from the marketing site at {@link T3_PROJECT_FILE_SCHEMA_URL} so |
| 30 | * editors get LSP support via a `$schema` reference. |
| 31 | */ |
| 32 | export function buildT3ProjectFileJsonSchema(): Record<string, unknown> { |
| 33 | // Closed objects, as before effect rc.113 changed the generator default; |
| 34 | // editors then flag unknown keys in t3.json. |
| 35 | const document = Schema.toJsonSchemaDocument(T3ProjectFile, { onExcessProperty: "error" }); |
| 36 | const jsonSchema: Record<string, unknown> = { |
| 37 | $schema: "https://json-schema.org/draft/2020-12/schema", |
| 38 | $id: T3_PROJECT_FILE_SCHEMA_URL, |
| 39 | ...document.schema, |
| 40 | }; |
| 41 | if (document.definitions && Object.keys(document.definitions).length > 0) { |
| 42 | jsonSchema.$defs = document.definitions; |
| 43 | } |
| 44 | return jsonSchema; |
| 45 | } |