typebars 1.0.9 → 1.0.11

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.
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/types.ts"],"sourcesContent":["import type { JSONSchema7 } from \"json-schema\";\nimport type { FromSchema, JSONSchema } from \"json-schema-to-ts\";\n\n// ─── Template Input ──────────────────────────────────────────────────────────\n// The engine accepts primitive values in addition to template strings.\n// When a non-string value is passed, it is treated as a literal passthrough:\n// analysis returns the inferred type, and execution returns the value as-is.\n\n/**\n * Object where each property is a `TemplateInput` (recursive).\n *\n * Allows passing an entire structure as a template:\n * ```\n * engine.analyze({\n * userName: \"{{name}}\",\n * userAge: \"{{age}}\",\n * nested: { x: \"{{foo}}\" },\n * }, inputSchema);\n * ```\n */\nexport interface TemplateInputObject {\n\t[key: string]: TemplateInput;\n}\n\n/**\n * Array where each element is a `TemplateInput` (recursive).\n *\n * Allows passing an array as a template:\n * ```\n * engine.analyze([\"{{name}}\", \"{{age}}\"], inputSchema);\n * engine.execute([\"{{name}}\", 42], data);\n * ```\n */\nexport type TemplateInputArray = TemplateInput[];\n\n/**\n * Input type accepted by the template engine.\n *\n * - `string` → standard Handlebars template (parsed and executed)\n * - `number` → numeric literal (passthrough)\n * - `boolean` → boolean literal (passthrough)\n * - `null` → null literal (passthrough)\n * - `TemplateInputArray` → array where each element is a `TemplateInput`\n * - `TemplateInputObject` → object where each property is a `TemplateInput`\n */\nexport type TemplateInput =\n\t| string\n\t| number\n\t| boolean\n\t| null\n\t| TemplateInputArray\n\t| TemplateInputObject;\n\n/**\n * Checks whether a value is a non-string primitive literal (number, boolean, null).\n * These values are treated as passthrough by the engine.\n *\n * Note: objects (`TemplateInputObject`) and arrays (`TemplateInputArray`) are NOT literals.\n */\nexport function isLiteralInput(\n\tinput: TemplateInput,\n): input is number | boolean | null {\n\treturn (\n\t\tinput === null || (typeof input !== \"string\" && typeof input !== \"object\")\n\t);\n}\n\n/**\n * Checks whether a value is a template array (`TemplateInputArray`).\n * Template arrays are processed recursively by the engine:\n * each element is analyzed/executed individually and the result is an array.\n */\nexport function isArrayInput(\n\tinput: TemplateInput,\n): input is TemplateInputArray {\n\treturn Array.isArray(input);\n}\n\n/**\n * Checks whether a value is a template object (`TemplateInputObject`).\n * Template objects are processed recursively by the engine:\n * each property is analyzed/executed individually.\n *\n * Note: arrays are excluded — use `isArrayInput()` first.\n */\nexport function isObjectInput(\n\tinput: TemplateInput,\n): input is TemplateInputObject {\n\treturn input !== null && typeof input === \"object\" && !Array.isArray(input);\n}\n\n/**\n * Infers the JSON Schema of a non-string primitive value.\n *\n * @param value - The primitive value (number, boolean, null)\n * @returns The corresponding JSON Schema\n *\n * @example\n * ```\n * inferPrimitiveSchema(42) // → { type: \"number\" }\n * inferPrimitiveSchema(true) // → { type: \"boolean\" }\n * inferPrimitiveSchema(null) // → { type: \"null\" }\n * ```\n */\nexport function inferPrimitiveSchema(\n\tvalue: number | boolean | null,\n): JSONSchema7 {\n\tif (value === null) return { type: \"null\" };\n\tif (typeof value === \"boolean\") return { type: \"boolean\" };\n\tif (typeof value === \"number\") {\n\t\treturn Number.isInteger(value) ? { type: \"integer\" } : { type: \"number\" };\n\t}\n\t// Exhaustiveness check — all branches are covered above.\n\t// If the type of `value` changes, TypeScript will raise an error here.\n\tvalue satisfies never;\n\treturn { type: \"null\" };\n}\n\n// ─── Diagnostic Codes ────────────────────────────────────────────────────────\n// Machine-readable codes for each error/warning type, enabling the frontend\n// to react programmatically without parsing the human-readable message.\n\nexport type DiagnosticCode =\n\t/** The referenced property does not exist in the context schema */\n\t| \"UNKNOWN_PROPERTY\"\n\t/** Type mismatch (e.g. #each on a non-array) */\n\t| \"TYPE_MISMATCH\"\n\t/** A block helper is used without a required argument */\n\t| \"MISSING_ARGUMENT\"\n\t/** Unknown block helper (neither built-in nor registered) */\n\t| \"UNKNOWN_HELPER\"\n\t/** The expression cannot be statically analyzed */\n\t| \"UNANALYZABLE\"\n\t/** The {{key:N}} syntax is used but no identifierSchemas were provided */\n\t| \"MISSING_IDENTIFIER_SCHEMAS\"\n\t/** The identifier N does not exist in the provided identifierSchemas */\n\t| \"UNKNOWN_IDENTIFIER\"\n\t/** The property does not exist in the identifier's schema */\n\t| \"IDENTIFIER_PROPERTY_NOT_FOUND\"\n\t/** Syntax error in the template */\n\t| \"PARSE_ERROR\";\n\n// ─── Diagnostic Details ──────────────────────────────────────────────────────\n// Supplementary information to understand the exact cause of the error.\n// Designed to be easily JSON-serializable and consumable by a frontend.\n\nexport interface DiagnosticDetails {\n\t/** Path of the expression that caused the error (e.g. `\"user.name.foo\"`) */\n\tpath?: string;\n\t/** Name of the helper involved (for helper-related errors) */\n\thelperName?: string;\n\t/** What was expected (e.g. `\"array\"`, `\"property to exist\"`) */\n\texpected?: string;\n\t/** What was found (e.g. `\"string\"`, `\"undefined\"`) */\n\tactual?: string;\n\t/** Available properties in the current schema (for suggestions) */\n\tavailableProperties?: string[];\n\t/** Template identifier number (for `{{key:N}}` errors) */\n\tidentifier?: number;\n}\n\n// ─── Static Analysis Result ──────────────────────────────────────────────────\n\n/** Diagnostic produced by the static analyzer */\nexport interface TemplateDiagnostic {\n\t/** \"error\" blocks execution, \"warning\" is informational */\n\tseverity: \"error\" | \"warning\";\n\n\t/** Machine-readable code identifying the error type */\n\tcode: DiagnosticCode;\n\n\t/** Human-readable message describing the problem */\n\tmessage: string;\n\n\t/** Position in the template source (if available from the AST) */\n\tloc?: {\n\t\tstart: { line: number; column: number };\n\t\tend: { line: number; column: number };\n\t};\n\n\t/** Fragment of the template source around the error */\n\tsource?: string;\n\n\t/** Structured information for debugging and frontend display */\n\tdetails?: DiagnosticDetails;\n}\n\n/** Complete result of the static analysis */\nexport interface AnalysisResult {\n\t/** true if no errors (warnings are tolerated) */\n\tvalid: boolean;\n\t/** List of diagnostics (errors + warnings) */\n\tdiagnostics: TemplateDiagnostic[];\n\t/** JSON Schema describing the template's return type */\n\toutputSchema: JSONSchema7;\n}\n\n/** Lightweight validation result (without output type inference) */\nexport interface ValidationResult {\n\t/** true if no errors (warnings are tolerated) */\n\tvalid: boolean;\n\t/** List of diagnostics (errors + warnings) */\n\tdiagnostics: TemplateDiagnostic[];\n}\n\n// ─── Public Engine Options ───────────────────────────────────────────────────\n\nexport interface TemplateEngineOptions {\n\t/**\n\t * Capacity of the parsed AST cache. Each parsed template is cached\n\t * to avoid costly re-parsing on repeated calls.\n\t * @default 256\n\t */\n\tastCacheSize?: number;\n\n\t/**\n\t * Capacity of the compiled Handlebars template cache.\n\t * @default 256\n\t */\n\tcompilationCacheSize?: number;\n\n\t/**\n\t * Custom helpers to register during engine construction.\n\t *\n\t * Each entry describes a helper with its name, implementation,\n\t * expected parameters, and return type.\n\t *\n\t * @example\n\t * ```\n\t * const engine = new Typebars({\n\t * helpers: [\n\t * {\n\t * name: \"uppercase\",\n\t * description: \"Converts a string to uppercase\",\n\t * fn: (value: string) => String(value).toUpperCase(),\n\t * params: [\n\t * { name: \"value\", type: { type: \"string\" }, description: \"The string to convert\" },\n\t * ],\n\t * returnType: { type: \"string\" },\n\t * },\n\t * ],\n\t * });\n\t * ```\n\t */\n\thelpers?: HelperConfig[];\n}\n\n// ─── Execution Options ───────────────────────────────────────────────────────\n// Optional options object for `execute()`, replacing multiple positional\n// parameters for better ergonomics.\n\nexport interface ExecuteOptions {\n\t/** JSON Schema for pre-execution static validation */\n\tschema?: JSONSchema7;\n\t/** Data by identifier `{ [id]: { key: value } }` */\n\tidentifierData?: Record<number, Record<string, unknown>>;\n\t/** Schemas by identifier (for static validation with identifiers) */\n\tidentifierSchemas?: Record<number, JSONSchema7>;\n}\n\n// ─── Combined Analyze-and-Execute Options ────────────────────────────────────\n// Optional options object for `analyzeAndExecute()`, grouping parameters\n// related to template identifiers.\n\nexport interface AnalyzeAndExecuteOptions {\n\t/** Schemas by identifier `{ [id]: JSONSchema7 }` for static analysis */\n\tidentifierSchemas?: Record<number, JSONSchema7>;\n\t/** Data by identifier `{ [id]: { key: value } }` for execution */\n\tidentifierData?: Record<number, Record<string, unknown>>;\n}\n\n// ─── Custom Helpers ──────────────────────────────────────────────────────────\n// Allows registering custom helpers with their type signature for static\n// analysis support.\n\n/** Describes a parameter expected by a helper */\nexport interface HelperParam {\n\t/** Parameter name (for documentation / introspection) */\n\tname: string;\n\n\t/**\n\t * JSON Schema describing the expected type for this parameter.\n\t * Used for documentation and static validation.\n\t */\n\ttype?: JSONSchema7;\n\n\t/** Human-readable description of the parameter */\n\tdescription?: string;\n\n\t/**\n\t * Whether the parameter is optional.\n\t * @default false\n\t */\n\toptional?: boolean;\n}\n\n/**\n * Definition of a helper registerable via `registerHelper()`.\n *\n * Contains the runtime implementation and typing metadata\n * for static analysis.\n */\nexport interface HelperDefinition {\n\t/**\n\t * Runtime implementation of the helper — will be registered with Handlebars.\n\t *\n\t * For an inline helper `{{uppercase name}}`:\n\t * `(value: string) => string`\n\t *\n\t * For a block helper `{{#repeat count}}...{{/repeat}}`:\n\t * `function(this: any, count: number, options: Handlebars.HelperOptions) { ... }`\n\t */\n\t// biome-ignore lint/suspicious/noExplicitAny: Handlebars helper signatures are inherently dynamic\n\tfn: (...args: any[]) => unknown;\n\n\t/**\n\t * Parameters expected by the helper (for documentation and analysis).\n\t *\n\t * @example\n\t * ```\n\t * params: [\n\t * { name: \"value\", type: { type: \"number\" }, description: \"The value to round\" },\n\t * { name: \"precision\", type: { type: \"number\" }, description: \"Decimal places\", optional: true },\n\t * ]\n\t * ```\n\t */\n\tparams?: HelperParam[];\n\n\t/**\n\t * JSON Schema describing the helper's return type for static analysis.\n\t * @default { type: \"string\" }\n\t */\n\treturnType?: JSONSchema7;\n\n\t/** Human-readable description of the helper */\n\tdescription?: string;\n}\n\n/**\n * Full helper configuration for registration via the `Typebars({ helpers: [...] })`\n * constructor options.\n *\n * Extends `HelperDefinition` with a required `name`.\n *\n * @example\n * ```\n * const config: HelperConfig = {\n * name: \"round\",\n * description: \"Rounds a number to a given precision\",\n * fn: (value: number, precision?: number) => { ... },\n * params: [\n * { name: \"value\", type: { type: \"number\" } },\n * { name: \"precision\", type: { type: \"number\" }, optional: true },\n * ],\n * returnType: { type: \"number\" },\n * };\n * ```\n */\nexport interface HelperConfig extends HelperDefinition {\n\t/** Name of the helper as used in templates (e.g. `\"uppercase\"`) */\n\tname: string;\n}\n\n// ─── Automatic Type Inference via json-schema-to-ts ──────────────────────────\n// Allows `defineHelper()` to infer TypeScript types for `fn` arguments\n// from the JSON Schemas declared in `params`.\n\n/**\n * Param definition used for type inference.\n * Accepts `JSONSchema` from `json-schema-to-ts` to allow `FromSchema`\n * to resolve literal types.\n */\ntype TypedHelperParam = {\n\treadonly name: string;\n\treadonly type?: JSONSchema;\n\treadonly description?: string;\n\treadonly optional?: boolean;\n};\n\n/**\n * Infers the TypeScript type of a single parameter from its JSON Schema.\n * - If `optional: true`, the resolved type is unioned with `undefined`.\n * - If `type` is not provided, the type is `unknown`.\n */\ntype InferParamType<P> = P extends {\n\treadonly type: infer S extends JSONSchema;\n\treadonly optional: true;\n}\n\t? FromSchema<S> | undefined\n\t: P extends { readonly type: infer S extends JSONSchema }\n\t\t? FromSchema<S>\n\t\t: unknown;\n\n/**\n * Maps a tuple of `TypedHelperParam` to a tuple of inferred TypeScript types,\n * usable as the `fn` signature.\n *\n * @example\n * ```\n * type Args = InferArgs<readonly [\n * { name: \"a\"; type: { type: \"string\" } },\n * { name: \"b\"; type: { type: \"number\" }; optional: true },\n * ]>;\n * // => [string, number | undefined]\n * ```\n */\ntype InferArgs<P extends readonly TypedHelperParam[]> = {\n\t[K in keyof P]: InferParamType<P[K]>;\n};\n\n/**\n * Helper configuration with generic parameter inference.\n * Used exclusively by `defineHelper()`.\n */\ninterface TypedHelperConfig<P extends readonly TypedHelperParam[]> {\n\tname: string;\n\tdescription?: string;\n\tparams: P;\n\tfn: (...args: InferArgs<P>) => unknown;\n\treturnType?: JSONSchema;\n}\n\n/**\n * Creates a `HelperConfig` with automatic type inference for `fn` arguments\n * based on the JSON Schemas declared in `params`.\n *\n * The generic parameter `const P` preserves schema literal types\n * (equivalent of `as const`), enabling `FromSchema` to resolve the\n * corresponding TypeScript types.\n *\n * @example\n * ```\n * const helper = defineHelper({\n * name: \"concat\",\n * description: \"Concatenates two strings\",\n * params: [\n * { name: \"a\", type: { type: \"string\" }, description: \"First string\" },\n * { name: \"b\", type: { type: \"string\" }, description: \"Second string\" },\n * { name: \"sep\", type: { type: \"string\" }, description: \"Separator\", optional: true },\n * ],\n * fn: (a, b, sep) => {\n * // a: string, b: string, sep: string | undefined\n * const separator = sep ?? \"\";\n * return `${a}${separator}${b}`;\n * },\n * returnType: { type: \"string\" },\n * });\n * ```\n */\nexport function defineHelper<const P extends readonly TypedHelperParam[]>(\n\tconfig: TypedHelperConfig<P>,\n): HelperConfig {\n\treturn config as unknown as HelperConfig;\n}\n"],"names":["isLiteralInput","input","isArrayInput","Array","isArray","isObjectInput","inferPrimitiveSchema","value","type","Number","isInteger","defineHelper","config"],"mappings":"AA2DA,OAAO,SAASA,eACfC,KAAoB,EAEpB,OACCA,QAAU,MAAS,OAAOA,QAAU,UAAY,OAAOA,QAAU,QAEnE,CAOA,OAAO,SAASC,aACfD,KAAoB,EAEpB,OAAOE,MAAMC,OAAO,CAACH,MACtB,CASA,OAAO,SAASI,cACfJ,KAAoB,EAEpB,OAAOA,QAAU,MAAQ,OAAOA,QAAU,UAAY,CAACE,MAAMC,OAAO,CAACH,MACtE,CAeA,OAAO,SAASK,qBACfC,KAA8B,EAE9B,GAAIA,QAAU,KAAM,MAAO,CAAEC,KAAM,MAAO,EAC1C,GAAI,OAAOD,QAAU,UAAW,MAAO,CAAEC,KAAM,SAAU,EACzD,GAAI,OAAOD,QAAU,SAAU,CAC9B,OAAOE,OAAOC,SAAS,CAACH,OAAS,CAAEC,KAAM,SAAU,EAAI,CAAEA,KAAM,QAAS,CACzE,CAGAD,MACA,MAAO,CAAEC,KAAM,MAAO,CACvB,CA6UA,OAAO,SAASG,aACfC,MAA4B,EAE5B,OAAOA,MACR"}
1
+ {"version":3,"sources":["../../src/types.ts"],"sourcesContent":["import type { JSONSchema7 } from \"json-schema\";\nimport type { FromSchema, JSONSchema } from \"json-schema-to-ts\";\n\n// ─── Template Input ──────────────────────────────────────────────────────────\n// The engine accepts primitive values in addition to template strings.\n// When a non-string value is passed, it is treated as a literal passthrough:\n// analysis returns the inferred type, and execution returns the value as-is.\n\n/**\n * Object where each property is a `TemplateInput` (recursive).\n *\n * Allows passing an entire structure as a template:\n * ```\n * engine.analyze({\n * userName: \"{{name}}\",\n * userAge: \"{{age}}\",\n * nested: { x: \"{{foo}}\" },\n * }, inputSchema);\n * ```\n */\nexport interface TemplateInputObject {\n\t[key: string]: TemplateInput;\n}\n\n/**\n * Array where each element is a `TemplateInput` (recursive).\n *\n * Allows passing an array as a template:\n * ```\n * engine.analyze([\"{{name}}\", \"{{age}}\"], inputSchema);\n * engine.execute([\"{{name}}\", 42], data);\n * ```\n */\nexport type TemplateInputArray = TemplateInput[];\n\n/**\n * Input type accepted by the template engine.\n *\n * - `string` → standard Handlebars template (parsed and executed)\n * - `number` → numeric literal (passthrough)\n * - `boolean` → boolean literal (passthrough)\n * - `null` → null literal (passthrough)\n * - `TemplateInputArray` → array where each element is a `TemplateInput`\n * - `TemplateInputObject` → object where each property is a `TemplateInput`\n */\nexport type TemplateInput =\n\t| string\n\t| number\n\t| boolean\n\t| null\n\t| TemplateInputArray\n\t| TemplateInputObject;\n\n/**\n * Checks whether a value is a non-string primitive literal (number, boolean, null).\n * These values are treated as passthrough by the engine.\n *\n * Note: objects (`TemplateInputObject`) and arrays (`TemplateInputArray`) are NOT literals.\n */\nexport function isLiteralInput(\n\tinput: TemplateInput,\n): input is number | boolean | null {\n\treturn (\n\t\tinput === null || (typeof input !== \"string\" && typeof input !== \"object\")\n\t);\n}\n\n/**\n * Checks whether a value is a template array (`TemplateInputArray`).\n * Template arrays are processed recursively by the engine:\n * each element is analyzed/executed individually and the result is an array.\n */\nexport function isArrayInput(\n\tinput: TemplateInput,\n): input is TemplateInputArray {\n\treturn Array.isArray(input);\n}\n\n/**\n * Checks whether a value is a template object (`TemplateInputObject`).\n * Template objects are processed recursively by the engine:\n * each property is analyzed/executed individually.\n *\n * Note: arrays are excluded — use `isArrayInput()` first.\n */\nexport function isObjectInput(\n\tinput: TemplateInput,\n): input is TemplateInputObject {\n\treturn input !== null && typeof input === \"object\" && !Array.isArray(input);\n}\n\n/**\n * Infers the JSON Schema of a non-string primitive value.\n *\n * @param value - The primitive value (number, boolean, null)\n * @returns The corresponding JSON Schema\n *\n * @example\n * ```\n * inferPrimitiveSchema(42) // → { type: \"number\" }\n * inferPrimitiveSchema(true) // → { type: \"boolean\" }\n * inferPrimitiveSchema(null) // → { type: \"null\" }\n * ```\n */\nexport function inferPrimitiveSchema(\n\tvalue: number | boolean | null,\n): JSONSchema7 {\n\tif (value === null) return { type: \"null\" };\n\tif (typeof value === \"boolean\") return { type: \"boolean\" };\n\tif (typeof value === \"number\") {\n\t\treturn Number.isInteger(value) ? { type: \"integer\" } : { type: \"number\" };\n\t}\n\t// Exhaustiveness check — all branches are covered above.\n\t// If the type of `value` changes, TypeScript will raise an error here.\n\tvalue satisfies never;\n\treturn { type: \"null\" };\n}\n\n// ─── Diagnostic Codes ────────────────────────────────────────────────────────\n// Machine-readable codes for each error/warning type, enabling the frontend\n// to react programmatically without parsing the human-readable message.\n\nexport type DiagnosticCode =\n\t/** The referenced property does not exist in the context schema */\n\t| \"UNKNOWN_PROPERTY\"\n\t/** Type mismatch (e.g. #each on a non-array) */\n\t| \"TYPE_MISMATCH\"\n\t/** A block helper is used without a required argument */\n\t| \"MISSING_ARGUMENT\"\n\t/** Unknown block helper (neither built-in nor registered) */\n\t| \"UNKNOWN_HELPER\"\n\t/** The expression cannot be statically analyzed */\n\t| \"UNANALYZABLE\"\n\t/** The {{key:N}} syntax is used but no identifierSchemas were provided */\n\t| \"MISSING_IDENTIFIER_SCHEMAS\"\n\t/** The identifier N does not exist in the provided identifierSchemas */\n\t| \"UNKNOWN_IDENTIFIER\"\n\t/** The property does not exist in the identifier's schema */\n\t| \"IDENTIFIER_PROPERTY_NOT_FOUND\"\n\t/** Syntax error in the template */\n\t| \"PARSE_ERROR\";\n\n// ─── Diagnostic Details ──────────────────────────────────────────────────────\n// Supplementary information to understand the exact cause of the error.\n// Designed to be easily JSON-serializable and consumable by a frontend.\n\nexport interface DiagnosticDetails {\n\t/** Path of the expression that caused the error (e.g. `\"user.name.foo\"`) */\n\tpath?: string;\n\t/** Name of the helper involved (for helper-related errors) */\n\thelperName?: string;\n\t/** What was expected (e.g. `\"array\"`, `\"property to exist\"`) */\n\texpected?: string;\n\t/** What was found (e.g. `\"string\"`, `\"undefined\"`) */\n\tactual?: string;\n\t/** Available properties in the current schema (for suggestions) */\n\tavailableProperties?: string[];\n\t/** Template identifier number (for `{{key:N}}` errors) */\n\tidentifier?: number;\n}\n\n// ─── Static Analysis Result ──────────────────────────────────────────────────\n\n/** Diagnostic produced by the static analyzer */\nexport interface TemplateDiagnostic {\n\t/** \"error\" blocks execution, \"warning\" is informational */\n\tseverity: \"error\" | \"warning\";\n\n\t/** Machine-readable code identifying the error type */\n\tcode: DiagnosticCode;\n\n\t/** Human-readable message describing the problem */\n\tmessage: string;\n\n\t/** Position in the template source (if available from the AST) */\n\tloc?: {\n\t\tstart: { line: number; column: number };\n\t\tend: { line: number; column: number };\n\t};\n\n\t/** Fragment of the template source around the error */\n\tsource?: string;\n\n\t/** Structured information for debugging and frontend display */\n\tdetails?: DiagnosticDetails;\n}\n\n/** Complete result of the static analysis */\nexport interface AnalysisResult {\n\t/** true if no errors (warnings are tolerated) */\n\tvalid: boolean;\n\t/** List of diagnostics (errors + warnings) */\n\tdiagnostics: TemplateDiagnostic[];\n\t/** JSON Schema describing the template's return type */\n\toutputSchema: JSONSchema7;\n}\n\n/** Lightweight validation result (without output type inference) */\nexport interface ValidationResult {\n\t/** true if no errors (warnings are tolerated) */\n\tvalid: boolean;\n\t/** List of diagnostics (errors + warnings) */\n\tdiagnostics: TemplateDiagnostic[];\n}\n\n// ─── Public Engine Options ───────────────────────────────────────────────────\n\nexport interface TemplateEngineOptions {\n\t/**\n\t * Capacity of the parsed AST cache. Each parsed template is cached\n\t * to avoid costly re-parsing on repeated calls.\n\t * @default 256\n\t */\n\tastCacheSize?: number;\n\n\t/**\n\t * Capacity of the compiled Handlebars template cache.\n\t * @default 256\n\t */\n\tcompilationCacheSize?: number;\n\n\t/**\n\t * Custom helpers to register during engine construction.\n\t *\n\t * Each entry describes a helper with its name, implementation,\n\t * expected parameters, and return type.\n\t *\n\t * @example\n\t * ```\n\t * const engine = new Typebars({\n\t * helpers: [\n\t * {\n\t * name: \"uppercase\",\n\t * description: \"Converts a string to uppercase\",\n\t * fn: (value: string) => String(value).toUpperCase(),\n\t * params: [\n\t * { name: \"value\", type: { type: \"string\" }, description: \"The string to convert\" },\n\t * ],\n\t * returnType: { type: \"string\" },\n\t * },\n\t * ],\n\t * });\n\t * ```\n\t */\n\thelpers?: HelperConfig[];\n}\n\n// ─── Execution Options ───────────────────────────────────────────────────────\n// Optional options object for `execute()`, replacing multiple positional\n// parameters for better ergonomics.\n\nexport interface ExecuteOptions {\n\t/** JSON Schema for pre-execution static validation */\n\tschema?: JSONSchema7;\n\t/** Data by identifier `{ [id]: { key: value } }` */\n\tidentifierData?: Record<number, Record<string, unknown>>;\n\t/** Schemas by identifier (for static validation with identifiers) */\n\tidentifierSchemas?: Record<number, JSONSchema7>;\n\t/**\n\t * Explicit coercion schema for the output value.\n\t * When provided with a primitive type, the execution result will be\n\t * coerced to match the declared type instead of using auto-detection.\n\t */\n\tcoerceSchema?: JSONSchema7;\n}\n\n// ─── Combined Analyze-and-Execute Options ────────────────────────────────────\n// Optional options object for `analyzeAndExecute()`, grouping parameters\n// related to template identifiers.\n\nexport interface AnalyzeAndExecuteOptions {\n\t/** Schemas by identifier `{ [id]: JSONSchema7 }` for static analysis */\n\tidentifierSchemas?: Record<number, JSONSchema7>;\n\t/** Data by identifier `{ [id]: { key: value } }` for execution */\n\tidentifierData?: Record<number, Record<string, unknown>>;\n\t/**\n\t * Explicit coercion schema for the output value.\n\t * When provided with a primitive type, the execution result will be\n\t * coerced to match the declared type instead of using auto-detection.\n\t */\n\tcoerceSchema?: JSONSchema7;\n}\n\n// ─── Custom Helpers ──────────────────────────────────────────────────────────\n// Allows registering custom helpers with their type signature for static\n// analysis support.\n\n/** Describes a parameter expected by a helper */\nexport interface HelperParam {\n\t/** Parameter name (for documentation / introspection) */\n\tname: string;\n\n\t/**\n\t * JSON Schema describing the expected type for this parameter.\n\t * Used for documentation and static validation.\n\t */\n\ttype?: JSONSchema7;\n\n\t/** Human-readable description of the parameter */\n\tdescription?: string;\n\n\t/**\n\t * Whether the parameter is optional.\n\t * @default false\n\t */\n\toptional?: boolean;\n}\n\n/**\n * Definition of a helper registerable via `registerHelper()`.\n *\n * Contains the runtime implementation and typing metadata\n * for static analysis.\n */\nexport interface HelperDefinition {\n\t/**\n\t * Runtime implementation of the helper — will be registered with Handlebars.\n\t *\n\t * For an inline helper `{{uppercase name}}`:\n\t * `(value: string) => string`\n\t *\n\t * For a block helper `{{#repeat count}}...{{/repeat}}`:\n\t * `function(this: any, count: number, options: Handlebars.HelperOptions) { ... }`\n\t */\n\t// biome-ignore lint/suspicious/noExplicitAny: Handlebars helper signatures are inherently dynamic\n\tfn: (...args: any[]) => unknown;\n\n\t/**\n\t * Parameters expected by the helper (for documentation and analysis).\n\t *\n\t * @example\n\t * ```\n\t * params: [\n\t * { name: \"value\", type: { type: \"number\" }, description: \"The value to round\" },\n\t * { name: \"precision\", type: { type: \"number\" }, description: \"Decimal places\", optional: true },\n\t * ]\n\t * ```\n\t */\n\tparams?: HelperParam[];\n\n\t/**\n\t * JSON Schema describing the helper's return type for static analysis.\n\t * @default { type: \"string\" }\n\t */\n\treturnType?: JSONSchema7;\n\n\t/** Human-readable description of the helper */\n\tdescription?: string;\n}\n\n/**\n * Full helper configuration for registration via the `Typebars({ helpers: [...] })`\n * constructor options.\n *\n * Extends `HelperDefinition` with a required `name`.\n *\n * @example\n * ```\n * const config: HelperConfig = {\n * name: \"round\",\n * description: \"Rounds a number to a given precision\",\n * fn: (value: number, precision?: number) => { ... },\n * params: [\n * { name: \"value\", type: { type: \"number\" } },\n * { name: \"precision\", type: { type: \"number\" }, optional: true },\n * ],\n * returnType: { type: \"number\" },\n * };\n * ```\n */\nexport interface HelperConfig extends HelperDefinition {\n\t/** Name of the helper as used in templates (e.g. `\"uppercase\"`) */\n\tname: string;\n}\n\n// ─── Automatic Type Inference via json-schema-to-ts ──────────────────────────\n// Allows `defineHelper()` to infer TypeScript types for `fn` arguments\n// from the JSON Schemas declared in `params`.\n\n/**\n * Param definition used for type inference.\n * Accepts `JSONSchema` from `json-schema-to-ts` to allow `FromSchema`\n * to resolve literal types.\n */\ntype TypedHelperParam = {\n\treadonly name: string;\n\treadonly type?: JSONSchema;\n\treadonly description?: string;\n\treadonly optional?: boolean;\n};\n\n/**\n * Infers the TypeScript type of a single parameter from its JSON Schema.\n * - If `optional: true`, the resolved type is unioned with `undefined`.\n * - If `type` is not provided, the type is `unknown`.\n */\ntype InferParamType<P> = P extends {\n\treadonly type: infer S extends JSONSchema;\n\treadonly optional: true;\n}\n\t? FromSchema<S> | undefined\n\t: P extends { readonly type: infer S extends JSONSchema }\n\t\t? FromSchema<S>\n\t\t: unknown;\n\n/**\n * Maps a tuple of `TypedHelperParam` to a tuple of inferred TypeScript types,\n * usable as the `fn` signature.\n *\n * @example\n * ```\n * type Args = InferArgs<readonly [\n * { name: \"a\"; type: { type: \"string\" } },\n * { name: \"b\"; type: { type: \"number\" }; optional: true },\n * ]>;\n * // => [string, number | undefined]\n * ```\n */\ntype InferArgs<P extends readonly TypedHelperParam[]> = {\n\t[K in keyof P]: InferParamType<P[K]>;\n};\n\n/**\n * Helper configuration with generic parameter inference.\n * Used exclusively by `defineHelper()`.\n */\ninterface TypedHelperConfig<P extends readonly TypedHelperParam[]> {\n\tname: string;\n\tdescription?: string;\n\tparams: P;\n\tfn: (...args: InferArgs<P>) => unknown;\n\treturnType?: JSONSchema;\n}\n\n/**\n * Creates a `HelperConfig` with automatic type inference for `fn` arguments\n * based on the JSON Schemas declared in `params`.\n *\n * The generic parameter `const P` preserves schema literal types\n * (equivalent of `as const`), enabling `FromSchema` to resolve the\n * corresponding TypeScript types.\n *\n * @example\n * ```\n * const helper = defineHelper({\n * name: \"concat\",\n * description: \"Concatenates two strings\",\n * params: [\n * { name: \"a\", type: { type: \"string\" }, description: \"First string\" },\n * { name: \"b\", type: { type: \"string\" }, description: \"Second string\" },\n * { name: \"sep\", type: { type: \"string\" }, description: \"Separator\", optional: true },\n * ],\n * fn: (a, b, sep) => {\n * // a: string, b: string, sep: string | undefined\n * const separator = sep ?? \"\";\n * return `${a}${separator}${b}`;\n * },\n * returnType: { type: \"string\" },\n * });\n * ```\n */\nexport function defineHelper<const P extends readonly TypedHelperParam[]>(\n\tconfig: TypedHelperConfig<P>,\n): HelperConfig {\n\treturn config as unknown as HelperConfig;\n}\n"],"names":["isLiteralInput","input","isArrayInput","Array","isArray","isObjectInput","inferPrimitiveSchema","value","type","Number","isInteger","defineHelper","config"],"mappings":"AA2DA,OAAO,SAASA,eACfC,KAAoB,EAEpB,OACCA,QAAU,MAAS,OAAOA,QAAU,UAAY,OAAOA,QAAU,QAEnE,CAOA,OAAO,SAASC,aACfD,KAAoB,EAEpB,OAAOE,MAAMC,OAAO,CAACH,MACtB,CASA,OAAO,SAASI,cACfJ,KAAoB,EAEpB,OAAOA,QAAU,MAAQ,OAAOA,QAAU,UAAY,CAACE,MAAMC,OAAO,CAACH,MACtE,CAeA,OAAO,SAASK,qBACfC,KAA8B,EAE9B,GAAIA,QAAU,KAAM,MAAO,CAAEC,KAAM,MAAO,EAC1C,GAAI,OAAOD,QAAU,UAAW,MAAO,CAAEC,KAAM,SAAU,EACzD,GAAI,OAAOD,QAAU,SAAU,CAC9B,OAAOE,OAAOC,SAAS,CAACH,OAAS,CAAEC,KAAM,SAAU,EAAI,CAAEA,KAAM,QAAS,CACzE,CAGAD,MACA,MAAO,CAAEC,KAAM,MAAO,CACvB,CAyVA,OAAO,SAASG,aACfC,MAA4B,EAE5B,OAAOA,MACR"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "typebars",
3
- "version": "1.0.9",
3
+ "version": "1.0.11",
4
4
  "license": "MIT",
5
5
  "description": "Typebars is a type-safe handlebars based template engine for generating object or content with static type checking",
6
6
  "author": {