@pythia-software/query-table-codegen 0.4.1 → 0.4.2

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.
@@ -116,10 +116,12 @@ function projectGoFields(doc) {
116
116
  const kindName = typeof postgres.kind === "string" ? postgres.kind : requiredString(field.type, `schema.fields[${index}].type`);
117
117
  const kind = GO_KINDS[kindName];
118
118
  if (!kind) throw new Error(`field ${JSON.stringify(name)} has unknown postgres kind ${JSON.stringify(kindName)}`);
119
+ let arrayCaseSensitive = false;
119
120
  let serverFilter = true;
120
121
  let filterOps;
121
122
  if (field.filter != null) {
122
123
  const filter = asObject(field.filter, `schema.fields[${index}].filter`);
124
+ arrayCaseSensitive = filter.arrayCaseSensitive === true;
123
125
  if (typeof filter.enabled === "boolean") serverFilter = filter.enabled;
124
126
  if (typeof filter.pushdown === "boolean") serverFilter = serverFilter && filter.pushdown;
125
127
  if (filter.ops != null) {
@@ -148,6 +150,7 @@ function projectGoFields(doc) {
148
150
  expr,
149
151
  synthetic: postgres.synthetic === true,
150
152
  serverFilter,
153
+ arrayCaseSensitive,
151
154
  sortable,
152
155
  sortExpr
153
156
  };
@@ -189,7 +192,7 @@ function generateGo(input, options) {
189
192
  const key = goString(field.name);
190
193
  const spacing = " ".repeat(longestFieldKey - key.length + 1);
191
194
  const filterOps = field.filterOps ? `, FilterOps: []string{${field.filterOps.map(goString).join(", ")}}` : "";
192
- return ` ${key}:${spacing}{Name: ${goString(field.name)}, Kind: querytable.${field.kind}, Expr: ${goString(field.expr)}, Synthetic: ${field.synthetic}, ServerFilter: ${field.serverFilter}${filterOps}, Sortable: ${field.sortable}, SortExpr: ${goString(field.sortExpr)}},`;
195
+ return ` ${key}:${spacing}{Name: ${goString(field.name)}, Kind: querytable.${field.kind}, Expr: ${goString(field.expr)}, Synthetic: ${field.synthetic}, ServerFilter: ${field.serverFilter}${filterOps}${field.arrayCaseSensitive ? ", ArrayCaseSensitive: true" : ""}, Sortable: ${field.sortable}, SortExpr: ${goString(field.sortExpr)}},`;
193
196
  }
194
197
  );
195
198
  return [
@@ -217,4 +220,4 @@ export {
217
220
  generateTypeScript,
218
221
  generateGo
219
222
  };
220
- //# sourceMappingURL=chunk-2SMI2V7J.js.map
223
+ //# sourceMappingURL=chunk-YQ663BVQ.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/generate.ts"],"sourcesContent":["import { loadSchema } from \"@pythia-software/query-table-core\";\n\nexport interface GoGenerationOptions {\n packageName: string;\n importPath?: string;\n}\n\nconst DEFAULT_GO_IMPORT = \"github.com/Pythia-Software/query-table/backends/go\";\n\nconst GO_KINDS: Record<string, string> = {\n text: \"FieldText\",\n number: \"FieldNumber\",\n datetime: \"FieldDatetime\",\n bool: \"FieldBool\",\n enum: \"FieldEnum\",\n textarray: \"FieldTextArray\",\n};\n\nconst GO_KEYWORDS = new Set([\n \"break\",\n \"default\",\n \"func\",\n \"interface\",\n \"select\",\n \"case\",\n \"defer\",\n \"go\",\n \"map\",\n \"struct\",\n \"chan\",\n \"else\",\n \"goto\",\n \"package\",\n \"switch\",\n \"const\",\n \"fallthrough\",\n \"if\",\n \"range\",\n \"type\",\n \"continue\",\n \"for\",\n \"import\",\n \"return\",\n \"var\",\n]);\n\ntype JsonObject = Record<string, unknown>;\n\ninterface GoField {\n name: string;\n kind: string;\n expr: string;\n synthetic: boolean;\n serverFilter: boolean;\n arrayCaseSensitive: boolean;\n filterOps?: string[];\n sortable: boolean;\n sortExpr: string;\n}\n\ninterface OrderTerm {\n field: string;\n dir: \"asc\" | \"desc\";\n nulls?: \"first\" | \"last\";\n extract?: { regex: string };\n}\n\nfunction asObject(value: unknown, label: string): JsonObject {\n if (value == null || typeof value !== \"object\" || Array.isArray(value)) {\n throw new Error(`${label} must be an object`);\n }\n return value as JsonObject;\n}\n\nfunction requiredString(value: unknown, label: string): string {\n if (typeof value !== \"string\" || !value) throw new Error(`${label} must be a non-empty string`);\n return value;\n}\n\nfunction goString(value: string): string {\n return JSON.stringify(value).replace(/\\u2028/g, \"\\\\u2028\").replace(/\\u2029/g, \"\\\\u2029\");\n}\n\nfunction exportedName(name: string): string {\n const parts = name.split(/[^A-Za-z0-9]+/).filter(Boolean);\n const base = parts.map((part) => part[0]!.toUpperCase() + part.slice(1)).join(\"\") || \"Generated\";\n return `${/^\\d/.test(base) ? `Schema${base}` : base}Schema`;\n}\n\nfunction validateGoPackage(packageName: string): void {\n if (!/^[A-Za-z_][A-Za-z0-9_]*$/.test(packageName) || GO_KEYWORDS.has(packageName)) {\n throw new Error(`invalid Go package name ${JSON.stringify(packageName)}`);\n }\n}\n\nfunction orderTerms(value: unknown, label: string, fieldNames: Set<string>): OrderTerm[] {\n if (value == null) return [];\n if (!Array.isArray(value)) throw new Error(`${label} must be an array`);\n return value.map((item, index) => {\n const raw = asObject(item, `${label}[${index}]`);\n const field = requiredString(raw.field, `${label}[${index}].field`);\n if (!fieldNames.has(field)) throw new Error(`${label}[${index}] references unknown field ${JSON.stringify(field)}`);\n if (raw.dir !== \"asc\" && raw.dir !== \"desc\") throw new Error(`${label}[${index}].dir must be \"asc\" or \"desc\"`);\n const term: OrderTerm = { field, dir: raw.dir };\n if (raw.nulls != null) {\n if (raw.nulls !== \"first\" && raw.nulls !== \"last\") {\n throw new Error(`${label}[${index}].nulls must be \"first\" or \"last\"`);\n }\n term.nulls = raw.nulls;\n }\n if (raw.extract != null) {\n const extract = asObject(raw.extract, `${label}[${index}].extract`);\n if (typeof extract.regex !== \"string\") throw new Error(`${label}[${index}].extract.regex must be a string`);\n if (extract.regex.length > 10_000) {\n throw new Error(`${label}[${index}].extract.regex exceeds 10000 characters`);\n }\n term.extract = { regex: extract.regex };\n }\n return term;\n });\n}\n\nfunction renderOrderTerms(terms: OrderTerm[]): string {\n if (terms.length === 0) return \"nil\";\n const members = terms.map((term) => {\n const nulls = term.nulls ? `, Nulls: ${goString(term.nulls)}` : \"\";\n const extract = term.extract\n ? `, Extract: &querytable.RegexExtract{Regex: ${goString(term.extract.regex)}}`\n : \"\";\n return `{Field: ${goString(term.field)}, Dir: ${goString(term.dir)}${nulls}${extract}}`;\n });\n return `[]querytable.OrderBy{${members.join(\", \")}}`;\n}\n\nfunction projectGoFields(doc: JsonObject): GoField[] {\n if (!Array.isArray(doc.fields)) throw new Error(\"schema.fields must be an array\");\n const rawFields = doc.fields.map((field, index) => asObject(field, `schema.fields[${index}]`));\n const exprByName = new Map<string, string>();\n\n for (const [index, field] of rawFields.entries()) {\n const name = requiredString(field.name, `schema.fields[${index}].name`);\n if (field.bindings == null) continue;\n const bindings = asObject(field.bindings, `schema.fields[${index}].bindings`);\n if (bindings.postgres == null) continue;\n const postgres = asObject(bindings.postgres, `schema.fields[${index}].bindings.postgres`);\n exprByName.set(name, requiredString(postgres.expr, `schema.fields[${index}].bindings.postgres.expr`));\n }\n\n const fields: GoField[] = [];\n for (const [index, field] of rawFields.entries()) {\n const name = requiredString(field.name, `schema.fields[${index}].name`);\n const expr = exprByName.get(name);\n if (!expr) continue;\n const bindings = asObject(field.bindings, `schema.fields[${index}].bindings`);\n const postgres = asObject(bindings.postgres, `schema.fields[${index}].bindings.postgres`);\n const kindName = typeof postgres.kind === \"string\" ? postgres.kind : requiredString(field.type, `schema.fields[${index}].type`);\n const kind = GO_KINDS[kindName];\n if (!kind) throw new Error(`field ${JSON.stringify(name)} has unknown postgres kind ${JSON.stringify(kindName)}`);\n\n let arrayCaseSensitive = false;\n let serverFilter = true;\n let filterOps: string[] | undefined;\n if (field.filter != null) {\n const filter = asObject(field.filter, `schema.fields[${index}].filter`);\n arrayCaseSensitive = filter.arrayCaseSensitive === true;\n if (typeof filter.enabled === \"boolean\") serverFilter = filter.enabled;\n if (typeof filter.pushdown === \"boolean\") serverFilter = serverFilter && filter.pushdown;\n if (filter.ops != null) {\n if (!Array.isArray(filter.ops) || !filter.ops.every((op) => typeof op === \"string\")) {\n throw new Error(`schema.fields[${index}].filter.ops must be an array of strings`);\n }\n filterOps = [...filter.ops] as string[];\n }\n }\n\n let sortable = true;\n let sortExpr = expr;\n if (field.sort != null) {\n const sort = asObject(field.sort, `schema.fields[${index}].sort`);\n if (typeof sort.enabled === \"boolean\") sortable = sort.enabled;\n if (typeof sort.field === \"string\") {\n const referencedExpr = exprByName.get(sort.field);\n if (!referencedExpr) {\n throw new Error(`field ${JSON.stringify(name)} sort target ${JSON.stringify(sort.field)} has no postgres binding`);\n }\n sortExpr = referencedExpr;\n }\n }\n\n const projected: GoField = {\n name,\n kind,\n expr,\n synthetic: postgres.synthetic === true,\n serverFilter,\n arrayCaseSensitive,\n sortable,\n sortExpr,\n };\n if (filterOps !== undefined) projected.filterOps = filterOps;\n fields.push(projected);\n }\n return fields;\n}\n\n/** Generate the frontend projection. SQL bindings are deliberately omitted. */\nexport function generateTypeScript(input: unknown): string {\n const schema = loadSchema(input);\n const constant = exportedName(schema.name).replace(/Schema$/, \"\").toUpperCase() + \"_SCHEMA\";\n return [\n \"// Code generated by query-table-codegen. DO NOT EDIT.\",\n 'import type { FieldSchema } from \"@pythia-software/query-table-core\";',\n \"\",\n `export const ${constant}: FieldSchema = ${JSON.stringify(schema, null, 2)};`,\n `export const ${constant.replace(/_SCHEMA$/, \"_FIELDS\")} = ${constant}.fields;`,\n \"\",\n ].join(\"\\n\");\n}\n\n/** Generate a direct Go Schema literal with no runtime JSON parsing. */\nexport function generateGo(input: unknown, options: GoGenerationOptions): string {\n validateGoPackage(options.packageName);\n loadSchema(input);\n const doc = asObject(input, \"schema\");\n const name = requiredString(doc.name, \"schema.name\");\n const idField = requiredString(doc.idField, \"schema.idField\");\n const fields = projectGoFields(doc);\n if (!fields.some((field) => field.name === idField)) {\n throw new Error(`id field ${JSON.stringify(idField)} has no postgres binding`);\n }\n const fieldNames = new Set((doc.fields as JsonObject[]).map((field) => requiredString(field.name, \"schema field name\")));\n const defaultSort = orderTerms(doc.defaultSort, \"schema.defaultSort\", fieldNames);\n const tiebreakSort = orderTerms(doc.tiebreakSort, \"schema.tiebreakSort\", fieldNames);\n const importPath = options.importPath ?? DEFAULT_GO_IMPORT;\n if (!importPath || /[\\s\\x00-\\x1f\\x7f\"]/u.test(importPath)) throw new Error(\"invalid Go import path\");\n\n const longestFieldKey = Math.max(0, ...fields.map((field) => goString(field.name).length));\n const fieldLines = fields.map(\n (field) => {\n const key = goString(field.name);\n const spacing = \" \".repeat(longestFieldKey - key.length + 1);\n const filterOps = field.filterOps\n ? `, FilterOps: []string{${field.filterOps.map(goString).join(\", \")}}`\n : \"\";\n return `\\t\\t\\t${key}:${spacing}{Name: ${goString(field.name)}, Kind: querytable.${field.kind}, Expr: ${goString(field.expr)}, Synthetic: ${field.synthetic}, ServerFilter: ${field.serverFilter}${filterOps}${field.arrayCaseSensitive ? \", ArrayCaseSensitive: true\" : \"\"}, Sortable: ${field.sortable}, SortExpr: ${goString(field.sortExpr)}},`;\n },\n );\n\n return [\n \"// Code generated by query-table-codegen. DO NOT EDIT.\",\n `package ${options.packageName}`,\n \"\",\n `import querytable ${goString(importPath)}`,\n \"\",\n `func ${exportedName(name)}() querytable.Schema {`,\n \"\\treturn querytable.Schema{\",\n `\\t\\tName: ${goString(name)},`,\n `\\t\\tIDField: ${goString(idField)},`,\n \"\\t\\tFields: map[string]querytable.FieldSpec{\",\n ...fieldLines,\n \"\\t\\t},\",\n `\\t\\tDefaultSort: ${renderOrderTerms(defaultSort)},`,\n `\\t\\tTiebreakSort: ${renderOrderTerms(tiebreakSort)},`,\n \"\\t}\",\n \"}\",\n \"\",\n ].join(\"\\n\");\n}\n"],"mappings":"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","names":[]}
package/dist/cli.js CHANGED
@@ -2,7 +2,7 @@
2
2
  import {
3
3
  generateGo,
4
4
  generateTypeScript
5
- } from "./chunk-2SMI2V7J.js";
5
+ } from "./chunk-YQ663BVQ.js";
6
6
 
7
7
  // src/cli.ts
8
8
  import { mkdir, readFile, writeFile } from "fs/promises";
package/dist/index.js CHANGED
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  generateGo,
3
3
  generateTypeScript
4
- } from "./chunk-2SMI2V7J.js";
4
+ } from "./chunk-YQ663BVQ.js";
5
5
  export {
6
6
  generateGo,
7
7
  generateTypeScript
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pythia-software/query-table-codegen",
3
- "version": "0.4.1",
3
+ "version": "0.4.2",
4
4
  "description": "Generate the TS catalog + Go schema from a query-table JSON schema document.",
5
5
  "keywords": ["codegen", "data-table", "json-schema", "typescript", "golang"],
6
6
  "license": "MIT",
@@ -34,6 +34,6 @@
34
34
  "typecheck": "tsc --noEmit"
35
35
  },
36
36
  "dependencies": {
37
- "@pythia-software/query-table-core": "0.4.1"
37
+ "@pythia-software/query-table-core": "0.4.2"
38
38
  }
39
39
  }
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/generate.ts"],"sourcesContent":["import { loadSchema } from \"@pythia-software/query-table-core\";\n\nexport interface GoGenerationOptions {\n packageName: string;\n importPath?: string;\n}\n\nconst DEFAULT_GO_IMPORT = \"github.com/Pythia-Software/query-table/backends/go\";\n\nconst GO_KINDS: Record<string, string> = {\n text: \"FieldText\",\n number: \"FieldNumber\",\n datetime: \"FieldDatetime\",\n bool: \"FieldBool\",\n enum: \"FieldEnum\",\n textarray: \"FieldTextArray\",\n};\n\nconst GO_KEYWORDS = new Set([\n \"break\",\n \"default\",\n \"func\",\n \"interface\",\n \"select\",\n \"case\",\n \"defer\",\n \"go\",\n \"map\",\n \"struct\",\n \"chan\",\n \"else\",\n \"goto\",\n \"package\",\n \"switch\",\n \"const\",\n \"fallthrough\",\n \"if\",\n \"range\",\n \"type\",\n \"continue\",\n \"for\",\n \"import\",\n \"return\",\n \"var\",\n]);\n\ntype JsonObject = Record<string, unknown>;\n\ninterface GoField {\n name: string;\n kind: string;\n expr: string;\n synthetic: boolean;\n serverFilter: boolean;\n filterOps?: string[];\n sortable: boolean;\n sortExpr: string;\n}\n\ninterface OrderTerm {\n field: string;\n dir: \"asc\" | \"desc\";\n nulls?: \"first\" | \"last\";\n extract?: { regex: string };\n}\n\nfunction asObject(value: unknown, label: string): JsonObject {\n if (value == null || typeof value !== \"object\" || Array.isArray(value)) {\n throw new Error(`${label} must be an object`);\n }\n return value as JsonObject;\n}\n\nfunction requiredString(value: unknown, label: string): string {\n if (typeof value !== \"string\" || !value) throw new Error(`${label} must be a non-empty string`);\n return value;\n}\n\nfunction goString(value: string): string {\n return JSON.stringify(value).replace(/\\u2028/g, \"\\\\u2028\").replace(/\\u2029/g, \"\\\\u2029\");\n}\n\nfunction exportedName(name: string): string {\n const parts = name.split(/[^A-Za-z0-9]+/).filter(Boolean);\n const base = parts.map((part) => part[0]!.toUpperCase() + part.slice(1)).join(\"\") || \"Generated\";\n return `${/^\\d/.test(base) ? `Schema${base}` : base}Schema`;\n}\n\nfunction validateGoPackage(packageName: string): void {\n if (!/^[A-Za-z_][A-Za-z0-9_]*$/.test(packageName) || GO_KEYWORDS.has(packageName)) {\n throw new Error(`invalid Go package name ${JSON.stringify(packageName)}`);\n }\n}\n\nfunction orderTerms(value: unknown, label: string, fieldNames: Set<string>): OrderTerm[] {\n if (value == null) return [];\n if (!Array.isArray(value)) throw new Error(`${label} must be an array`);\n return value.map((item, index) => {\n const raw = asObject(item, `${label}[${index}]`);\n const field = requiredString(raw.field, `${label}[${index}].field`);\n if (!fieldNames.has(field)) throw new Error(`${label}[${index}] references unknown field ${JSON.stringify(field)}`);\n if (raw.dir !== \"asc\" && raw.dir !== \"desc\") throw new Error(`${label}[${index}].dir must be \"asc\" or \"desc\"`);\n const term: OrderTerm = { field, dir: raw.dir };\n if (raw.nulls != null) {\n if (raw.nulls !== \"first\" && raw.nulls !== \"last\") {\n throw new Error(`${label}[${index}].nulls must be \"first\" or \"last\"`);\n }\n term.nulls = raw.nulls;\n }\n if (raw.extract != null) {\n const extract = asObject(raw.extract, `${label}[${index}].extract`);\n if (typeof extract.regex !== \"string\") throw new Error(`${label}[${index}].extract.regex must be a string`);\n if (extract.regex.length > 10_000) {\n throw new Error(`${label}[${index}].extract.regex exceeds 10000 characters`);\n }\n term.extract = { regex: extract.regex };\n }\n return term;\n });\n}\n\nfunction renderOrderTerms(terms: OrderTerm[]): string {\n if (terms.length === 0) return \"nil\";\n const members = terms.map((term) => {\n const nulls = term.nulls ? `, Nulls: ${goString(term.nulls)}` : \"\";\n const extract = term.extract\n ? `, Extract: &querytable.RegexExtract{Regex: ${goString(term.extract.regex)}}`\n : \"\";\n return `{Field: ${goString(term.field)}, Dir: ${goString(term.dir)}${nulls}${extract}}`;\n });\n return `[]querytable.OrderBy{${members.join(\", \")}}`;\n}\n\nfunction projectGoFields(doc: JsonObject): GoField[] {\n if (!Array.isArray(doc.fields)) throw new Error(\"schema.fields must be an array\");\n const rawFields = doc.fields.map((field, index) => asObject(field, `schema.fields[${index}]`));\n const exprByName = new Map<string, string>();\n\n for (const [index, field] of rawFields.entries()) {\n const name = requiredString(field.name, `schema.fields[${index}].name`);\n if (field.bindings == null) continue;\n const bindings = asObject(field.bindings, `schema.fields[${index}].bindings`);\n if (bindings.postgres == null) continue;\n const postgres = asObject(bindings.postgres, `schema.fields[${index}].bindings.postgres`);\n exprByName.set(name, requiredString(postgres.expr, `schema.fields[${index}].bindings.postgres.expr`));\n }\n\n const fields: GoField[] = [];\n for (const [index, field] of rawFields.entries()) {\n const name = requiredString(field.name, `schema.fields[${index}].name`);\n const expr = exprByName.get(name);\n if (!expr) continue;\n const bindings = asObject(field.bindings, `schema.fields[${index}].bindings`);\n const postgres = asObject(bindings.postgres, `schema.fields[${index}].bindings.postgres`);\n const kindName = typeof postgres.kind === \"string\" ? postgres.kind : requiredString(field.type, `schema.fields[${index}].type`);\n const kind = GO_KINDS[kindName];\n if (!kind) throw new Error(`field ${JSON.stringify(name)} has unknown postgres kind ${JSON.stringify(kindName)}`);\n\n let serverFilter = true;\n let filterOps: string[] | undefined;\n if (field.filter != null) {\n const filter = asObject(field.filter, `schema.fields[${index}].filter`);\n if (typeof filter.enabled === \"boolean\") serverFilter = filter.enabled;\n if (typeof filter.pushdown === \"boolean\") serverFilter = serverFilter && filter.pushdown;\n if (filter.ops != null) {\n if (!Array.isArray(filter.ops) || !filter.ops.every((op) => typeof op === \"string\")) {\n throw new Error(`schema.fields[${index}].filter.ops must be an array of strings`);\n }\n filterOps = [...filter.ops] as string[];\n }\n }\n\n let sortable = true;\n let sortExpr = expr;\n if (field.sort != null) {\n const sort = asObject(field.sort, `schema.fields[${index}].sort`);\n if (typeof sort.enabled === \"boolean\") sortable = sort.enabled;\n if (typeof sort.field === \"string\") {\n const referencedExpr = exprByName.get(sort.field);\n if (!referencedExpr) {\n throw new Error(`field ${JSON.stringify(name)} sort target ${JSON.stringify(sort.field)} has no postgres binding`);\n }\n sortExpr = referencedExpr;\n }\n }\n\n const projected: GoField = {\n name,\n kind,\n expr,\n synthetic: postgres.synthetic === true,\n serverFilter,\n sortable,\n sortExpr,\n };\n if (filterOps !== undefined) projected.filterOps = filterOps;\n fields.push(projected);\n }\n return fields;\n}\n\n/** Generate the frontend projection. SQL bindings are deliberately omitted. */\nexport function generateTypeScript(input: unknown): string {\n const schema = loadSchema(input);\n const constant = exportedName(schema.name).replace(/Schema$/, \"\").toUpperCase() + \"_SCHEMA\";\n return [\n \"// Code generated by query-table-codegen. DO NOT EDIT.\",\n 'import type { FieldSchema } from \"@pythia-software/query-table-core\";',\n \"\",\n `export const ${constant}: FieldSchema = ${JSON.stringify(schema, null, 2)};`,\n `export const ${constant.replace(/_SCHEMA$/, \"_FIELDS\")} = ${constant}.fields;`,\n \"\",\n ].join(\"\\n\");\n}\n\n/** Generate a direct Go Schema literal with no runtime JSON parsing. */\nexport function generateGo(input: unknown, options: GoGenerationOptions): string {\n validateGoPackage(options.packageName);\n loadSchema(input);\n const doc = asObject(input, \"schema\");\n const name = requiredString(doc.name, \"schema.name\");\n const idField = requiredString(doc.idField, \"schema.idField\");\n const fields = projectGoFields(doc);\n if (!fields.some((field) => field.name === idField)) {\n throw new Error(`id field ${JSON.stringify(idField)} has no postgres binding`);\n }\n const fieldNames = new Set((doc.fields as JsonObject[]).map((field) => requiredString(field.name, \"schema field name\")));\n const defaultSort = orderTerms(doc.defaultSort, \"schema.defaultSort\", fieldNames);\n const tiebreakSort = orderTerms(doc.tiebreakSort, \"schema.tiebreakSort\", fieldNames);\n const importPath = options.importPath ?? DEFAULT_GO_IMPORT;\n if (!importPath || /[\\s\\x00-\\x1f\\x7f\"]/u.test(importPath)) throw new Error(\"invalid Go import path\");\n\n const longestFieldKey = Math.max(0, ...fields.map((field) => goString(field.name).length));\n const fieldLines = fields.map(\n (field) => {\n const key = goString(field.name);\n const spacing = \" \".repeat(longestFieldKey - key.length + 1);\n const filterOps = field.filterOps\n ? `, FilterOps: []string{${field.filterOps.map(goString).join(\", \")}}`\n : \"\";\n return `\\t\\t\\t${key}:${spacing}{Name: ${goString(field.name)}, Kind: querytable.${field.kind}, Expr: ${goString(field.expr)}, Synthetic: ${field.synthetic}, ServerFilter: ${field.serverFilter}${filterOps}, Sortable: ${field.sortable}, SortExpr: ${goString(field.sortExpr)}},`;\n },\n );\n\n return [\n \"// Code generated by query-table-codegen. DO NOT EDIT.\",\n `package ${options.packageName}`,\n \"\",\n `import querytable ${goString(importPath)}`,\n \"\",\n `func ${exportedName(name)}() querytable.Schema {`,\n \"\\treturn querytable.Schema{\",\n `\\t\\tName: ${goString(name)},`,\n `\\t\\tIDField: ${goString(idField)},`,\n \"\\t\\tFields: map[string]querytable.FieldSpec{\",\n ...fieldLines,\n \"\\t\\t},\",\n `\\t\\tDefaultSort: ${renderOrderTerms(defaultSort)},`,\n `\\t\\tTiebreakSort: ${renderOrderTerms(tiebreakSort)},`,\n \"\\t}\",\n \"}\",\n \"\",\n ].join(\"\\n\");\n}\n"],"mappings":"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","names":[]}