@suiteportal/generator 0.3.0 → 0.5.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.
package/dist/index.cjs CHANGED
@@ -80,6 +80,122 @@ function fieldTypeToTS(fieldType) {
80
80
  }
81
81
 
82
82
  // src/emitters/type-emitter.ts
83
+ function fieldTypeToFilter(fieldType) {
84
+ switch (fieldType) {
85
+ case "string":
86
+ case "text":
87
+ case "richtext":
88
+ case "email":
89
+ case "url":
90
+ case "phone":
91
+ case "date":
92
+ case "datetime":
93
+ case "multiselect":
94
+ return { filterType: "StringFilter", shorthand: "string" };
95
+ case "integer":
96
+ case "float":
97
+ case "currency":
98
+ case "percent":
99
+ return { filterType: "NumberFilter", shorthand: "number" };
100
+ case "boolean":
101
+ return { filterType: "BooleanFilter", shorthand: "boolean" };
102
+ case "select":
103
+ return { filterType: "SelectFilter", shorthand: "string | number" };
104
+ case "unknown":
105
+ default:
106
+ return { filterType: "StringFilter", shorthand: "unknown" };
107
+ }
108
+ }
109
+ function emitFilterTypes() {
110
+ return `/** String field filter operators. */
111
+ export interface StringFilter {
112
+ equals?: string | null;
113
+ not?: string | null;
114
+ in?: string[];
115
+ notIn?: string[];
116
+ gt?: string;
117
+ gte?: string;
118
+ lt?: string;
119
+ lte?: string;
120
+ contains?: string;
121
+ startsWith?: string;
122
+ endsWith?: string;
123
+ isNull?: boolean;
124
+ }
125
+
126
+ /** Number field filter operators. */
127
+ export interface NumberFilter {
128
+ equals?: number | null;
129
+ not?: number | null;
130
+ in?: number[];
131
+ notIn?: number[];
132
+ gt?: number;
133
+ gte?: number;
134
+ lt?: number;
135
+ lte?: number;
136
+ isNull?: boolean;
137
+ }
138
+
139
+ /** Boolean field filter operators. */
140
+ export interface BooleanFilter {
141
+ equals?: boolean | null;
142
+ not?: boolean | null;
143
+ isNull?: boolean;
144
+ }
145
+
146
+ /** Select (string | number) field filter operators. */
147
+ export interface SelectFilter {
148
+ equals?: string | number | null;
149
+ not?: string | number | null;
150
+ in?: (string | number)[];
151
+ notIn?: (string | number)[];
152
+ gt?: string | number;
153
+ gte?: string | number;
154
+ lt?: string | number;
155
+ lte?: string | number;
156
+ isNull?: boolean;
157
+ }`;
158
+ }
159
+ function emitWhereInput(recordId, record) {
160
+ const name = toPascalCase(recordId);
161
+ const lines = [];
162
+ lines.push(`/** Where clause for ${record.label} queries. */`);
163
+ lines.push(`export interface ${name}WhereInput {`);
164
+ for (const [fieldId, field] of Object.entries(record.fields)) {
165
+ const { filterType, shorthand } = fieldTypeToFilter(field.type);
166
+ lines.push(` /** ${field.label} */`);
167
+ lines.push(` ${fieldId}?: ${shorthand} | ${filterType};`);
168
+ }
169
+ lines.push(` AND?: ${name}WhereInput[];`);
170
+ lines.push(` OR?: ${name}WhereInput[];`);
171
+ lines.push(` NOT?: ${name}WhereInput;`);
172
+ lines.push("}");
173
+ return lines.join("\n");
174
+ }
175
+ function emitSelectType(recordId, record) {
176
+ const name = toPascalCase(recordId);
177
+ const lines = [];
178
+ lines.push(`/** Field selection for ${record.label} queries. */`);
179
+ lines.push(`export interface ${name}Select {`);
180
+ for (const [fieldId, field] of Object.entries(record.fields)) {
181
+ lines.push(` /** ${field.label} */`);
182
+ lines.push(` ${fieldId}?: boolean;`);
183
+ }
184
+ lines.push("}");
185
+ return lines.join("\n");
186
+ }
187
+ function emitOrderByType(recordId, record) {
188
+ const name = toPascalCase(recordId);
189
+ const lines = [];
190
+ lines.push(`/** Order by clause for ${record.label} queries. */`);
191
+ lines.push(`export interface ${name}OrderByInput {`);
192
+ for (const [fieldId, field] of Object.entries(record.fields)) {
193
+ lines.push(` /** ${field.label} */`);
194
+ lines.push(` ${fieldId}?: 'asc' | 'desc';`);
195
+ }
196
+ lines.push("}");
197
+ return lines.join("\n");
198
+ }
83
199
  function emitRecordInterface(recordId, record) {
84
200
  const name = toPascalCase(recordId);
85
201
  const fieldEntries = Object.entries(record.fields);
@@ -163,6 +279,10 @@ function emitTypes(schema) {
163
279
  ""
164
280
  ];
165
281
  const recordEntries = Object.entries(schema.records);
282
+ if (recordEntries.length > 0) {
283
+ lines.push(emitFilterTypes());
284
+ lines.push("");
285
+ }
166
286
  for (const [recordId, record] of recordEntries) {
167
287
  lines.push(emitRecordInterface(recordId, record));
168
288
  lines.push("");
@@ -175,6 +295,12 @@ function emitTypes(schema) {
175
295
  lines.push("");
176
296
  lines.push(emitUpdateInput(recordId, record));
177
297
  lines.push("");
298
+ lines.push(emitWhereInput(recordId, record));
299
+ lines.push("");
300
+ lines.push(emitSelectType(recordId, record));
301
+ lines.push("");
302
+ lines.push(emitOrderByType(recordId, record));
303
+ lines.push("");
178
304
  }
179
305
  if (recordEntries.length > 0) {
180
306
  const names = recordEntries.map(([id]) => `'${id}'`);
@@ -193,6 +319,21 @@ function emitTypes(schema) {
193
319
  }
194
320
 
195
321
  // src/emitters/client-emitter.ts
322
+ function emitDelegate(recordId) {
323
+ const name = toPascalCase(recordId);
324
+ const lines = [];
325
+ lines.push(`/** Typed delegate for ${name} records. */`);
326
+ lines.push(`export interface ${name}Delegate {`);
327
+ lines.push(` findMany(args?: { where?: ${name}WhereInput; select?: ${name}Select; orderBy?: ${name}OrderByInput; include?: IncludeInput; take?: number; skip?: number }): Promise<${name}[]>;`);
328
+ lines.push(` findFirst(args?: { where?: ${name}WhereInput; select?: ${name}Select; orderBy?: ${name}OrderByInput; include?: IncludeInput; skip?: number }): Promise<${name} | null>;`);
329
+ lines.push(` count(args?: { where?: ${name}WhereInput }): Promise<number>;`);
330
+ lines.push(` create(args: { data: ${name}CreateInput }): Promise<${name}>;`);
331
+ lines.push(` update(args: { where: { id: { equals: string | number } }; data: ${name}UpdateInput }): Promise<${name}>;`);
332
+ lines.push(` delete(args: { where: { id: { equals: string | number } } }): Promise<void>;`);
333
+ lines.push(` upsert(args: { where: { externalId: string }; data: ${name}CreateInput }): Promise<${name}>;`);
334
+ lines.push("}");
335
+ return lines.join("\n");
336
+ }
196
337
  function emitClient(schema) {
197
338
  const recordEntries = Object.entries(schema.records);
198
339
  const typeImports = recordEntries.map(([id]) => toPascalCase(id));
@@ -205,41 +346,34 @@ function emitClient(schema) {
205
346
  ` SuitePortalClient as BaseClient,`,
206
347
  ` getClient as baseGetClient,`,
207
348
  ` destroySingleton,`,
208
- ` type FindManyArgs,`,
209
- ` type FindFirstArgs,`,
210
- ` type CountArgs,`,
211
- ` type CreateArgs,`,
212
- ` type UpdateArgs,`,
213
- ` type DeleteArgs,`,
214
- ` type UpsertArgs,`,
215
349
  ` type IncludeInput,`,
216
350
  ` type ClientOptions,`,
217
351
  `} from 'suiteportal';`
218
352
  ];
219
353
  if (typeImports.length > 0) {
220
- const inputImports = recordEntries.flatMap(([id]) => {
354
+ const perRecordImports = recordEntries.flatMap(([id]) => {
221
355
  const name = toPascalCase(id);
222
- return [`${name}CreateInput`, `${name}UpdateInput`];
356
+ return [
357
+ name,
358
+ `${name}CreateInput`,
359
+ `${name}UpdateInput`,
360
+ `${name}WhereInput`,
361
+ `${name}Select`,
362
+ `${name}OrderByInput`
363
+ ];
223
364
  });
224
- lines.push(`import type { ${[...typeImports, ...inputImports].join(", ")} } from './types';`);
365
+ lines.push(`import type { ${perRecordImports.join(", ")} } from './types';`);
225
366
  }
226
367
  lines.push("");
227
- lines.push("/** A typed model delegate for a specific record type. */");
228
- lines.push("export interface TypedModelDelegate<T, TCreate = Record<string, unknown>, TUpdate = Record<string, unknown>> {");
229
- lines.push(" findMany(args?: FindManyArgs): Promise<T[]>;");
230
- lines.push(" findFirst(args?: FindFirstArgs): Promise<T | null>;");
231
- lines.push(" count(args?: CountArgs): Promise<number>;");
232
- lines.push(" create(args: CreateArgs<TCreate>): Promise<T>;");
233
- lines.push(" update(args: UpdateArgs<TUpdate>): Promise<T>;");
234
- lines.push(" delete(args: DeleteArgs): Promise<void>;");
235
- lines.push(" upsert(args: UpsertArgs<TCreate>): Promise<T>;");
236
- lines.push("}");
237
- lines.push("");
368
+ for (const [recordId] of recordEntries) {
369
+ lines.push(emitDelegate(recordId));
370
+ lines.push("");
371
+ }
238
372
  lines.push("/** Typed SuitePortal client with per-record delegates. */");
239
373
  lines.push("export interface SuitePortalClient {");
240
374
  for (const [recordId] of recordEntries) {
241
375
  const typeName = toPascalCase(recordId);
242
- lines.push(` ${recordId}: TypedModelDelegate<${typeName}, ${typeName}CreateInput, ${typeName}UpdateInput>;`);
376
+ lines.push(` ${recordId}: ${typeName}Delegate;`);
243
377
  }
244
378
  lines.push(" $queryRaw<T = Record<string, unknown>>(sql: string): Promise<T[]>;");
245
379
  lines.push(" $disconnect(): void;");
@@ -272,7 +406,7 @@ function emitClient(schema) {
272
406
  lines.push("");
273
407
  lines.push("export { destroySingleton };");
274
408
  lines.push("");
275
- lines.push("export type { FindManyArgs, FindFirstArgs, CountArgs, CreateArgs, UpdateArgs, DeleteArgs, UpsertArgs, IncludeInput } from 'suiteportal';");
409
+ lines.push("export type { IncludeInput } from 'suiteportal';");
276
410
  lines.push("");
277
411
  return lines.join("\n");
278
412
  }
@@ -287,15 +421,23 @@ function emitBarrel(schema) {
287
421
  ""
288
422
  ];
289
423
  if (typeNames.length > 0) {
290
- const inputTypes = recordEntries.flatMap(([id]) => {
424
+ const perRecordTypes = recordEntries.flatMap(([id]) => {
291
425
  const name = toPascalCase(id);
292
- return [`${name}CreateInput`, `${name}UpdateInput`];
426
+ return [
427
+ `${name}CreateInput`,
428
+ `${name}UpdateInput`,
429
+ `${name}WhereInput`,
430
+ `${name}Select`,
431
+ `${name}OrderByInput`
432
+ ];
293
433
  });
294
- lines.push(`export type { ${[...typeNames, ...inputTypes].join(", ")}, RecordTypeId, RecordTypeMap } from './types';`);
434
+ lines.push(`export type { ${[...typeNames, ...perRecordTypes].join(", ")}, RecordTypeId, RecordTypeMap } from './types';`);
435
+ lines.push(`export type { StringFilter, NumberFilter, BooleanFilter, SelectFilter } from './types';`);
295
436
  }
296
- lines.push(`export type { SuitePortalClient, TypedModelDelegate } from './client';`);
437
+ const delegateTypes = recordEntries.map(([id]) => `${toPascalCase(id)}Delegate`);
438
+ lines.push(`export type { SuitePortalClient${delegateTypes.length > 0 ? ", " + delegateTypes.join(", ") : ""} } from './client';`);
297
439
  lines.push(`export { createClient } from './client';`);
298
- lines.push(`export type { FindManyArgs, FindFirstArgs, CountArgs, CreateArgs, UpdateArgs, DeleteArgs, IncludeInput } from './client';`);
440
+ lines.push(`export type { IncludeInput } from './client';`);
299
441
  lines.push("");
300
442
  return lines.join("\n");
301
443
  }
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/index.ts","../src/generate.ts","../src/schema-reader.ts","../src/naming.ts","../src/emitters/type-emitter.ts","../src/emitters/client-emitter.ts","../src/emitters/barrel-emitter.ts"],"sourcesContent":["// Generator\nexport { generate } from './generate.js';\n\n// Schema reader\nexport { readSchema } from './schema-reader.js';\n\n// Naming utilities\nexport { toPascalCase, fieldTypeToTS } from './naming.js';\n\n// Emitters\nexport { emitTypes } from './emitters/type-emitter.js';\nexport { emitClient } from './emitters/client-emitter.js';\nexport { emitBarrel } from './emitters/barrel-emitter.js';\n\n// Types\nexport type { GenerateOptions, GenerateResult } from './types.js';\n","import { mkdir, writeFile } from 'node:fs/promises';\nimport { join } from 'node:path';\nimport { readSchema } from './schema-reader.js';\nimport { emitTypes } from './emitters/type-emitter.js';\nimport { emitClient } from './emitters/client-emitter.js';\nimport { emitBarrel } from './emitters/barrel-emitter.js';\nimport type { GenerateOptions, GenerateResult } from './types.js';\n\nconst DEFAULT_SCHEMA_PATH = '.suiteportal/schema.json';\nconst DEFAULT_OUTPUT_DIR = '.suiteportal/client';\n\n/**\n * Generate typed client code from a schema.json file.\n *\n * Reads the introspected schema, emits TypeScript interfaces for all records,\n * a typed client wrapper, and a barrel export file.\n */\nexport async function generate(options?: GenerateOptions): Promise<GenerateResult> {\n const schemaPath = options?.schemaPath ?? DEFAULT_SCHEMA_PATH;\n const outputDir = options?.outputDir ?? DEFAULT_OUTPUT_DIR;\n\n // Read schema\n const schema = await readSchema(schemaPath);\n\n // Ensure output directory exists\n await mkdir(outputDir, { recursive: true });\n\n // Generate files\n const typesContent = emitTypes(schema);\n const clientContent = emitClient(schema);\n const barrelContent = emitBarrel(schema);\n\n // Write files\n const typesPath = join(outputDir, 'types.ts');\n const clientPath = join(outputDir, 'client.ts');\n const barrelPath = join(outputDir, 'index.ts');\n\n await Promise.all([\n writeFile(typesPath, typesContent, 'utf-8'),\n writeFile(clientPath, clientContent, 'utf-8'),\n writeFile(barrelPath, barrelContent, 'utf-8'),\n ]);\n\n // Compute stats\n const recordEntries = Object.entries(schema.records);\n const fieldCount = recordEntries.reduce(\n (sum, [, record]) => sum + Object.keys(record.fields).length,\n 0,\n );\n\n return {\n recordCount: recordEntries.length,\n fieldCount,\n files: [typesPath, clientPath, barrelPath],\n outputDir,\n };\n}\n","import { readFile } from 'node:fs/promises';\nimport type { NormalizedSchema } from '@suiteportal/introspector';\n\n/**\n * Read and parse a schema.json file.\n */\nexport async function readSchema(schemaPath: string): Promise<NormalizedSchema> {\n const raw = await readFile(schemaPath, 'utf-8');\n const schema = JSON.parse(raw) as NormalizedSchema;\n\n if (!schema.records || typeof schema.records !== 'object') {\n throw new Error(`Invalid schema: missing \"records\" in ${schemaPath}`);\n }\n\n return schema;\n}\n","import type { FieldType } from '@suiteportal/introspector';\n\n/**\n * Convert a record ID to PascalCase for use as a TypeScript interface name.\n * Examples:\n * 'customer' → 'Customer'\n * 'salesorder' → 'Salesorder'\n * 'customrecord_mytype' → 'CustomrecordMytype'\n */\nexport function toPascalCase(name: string): string {\n return name\n .split('_')\n .map((part) => (part.length > 0 ? part[0]!.toUpperCase() + part.slice(1).toLowerCase() : ''))\n .join('');\n}\n\n/**\n * Map a normalized FieldType to its TypeScript type representation.\n */\nexport function fieldTypeToTS(fieldType: FieldType): string {\n switch (fieldType) {\n case 'string':\n case 'text':\n case 'richtext':\n case 'email':\n case 'url':\n case 'phone':\n return 'string';\n\n case 'integer':\n case 'float':\n case 'currency':\n case 'percent':\n return 'number';\n\n case 'boolean':\n return 'boolean';\n\n case 'date':\n case 'datetime':\n return 'string'; // SuiteQL returns date strings\n\n case 'select':\n return 'string | number';\n\n case 'multiselect':\n return 'string';\n\n case 'unknown':\n default:\n return 'unknown';\n }\n}\n","import type { NormalizedSchema, RecordDefinition, SublistDefinition } from '@suiteportal/introspector';\nimport { toPascalCase, fieldTypeToTS } from '../naming.js';\n\n/**\n * Emit a TypeScript interface for a single record.\n */\nfunction emitRecordInterface(recordId: string, record: RecordDefinition): string {\n const name = toPascalCase(recordId);\n const fieldEntries = Object.entries(record.fields);\n const fieldCount = fieldEntries.length;\n\n const lines: string[] = [];\n lines.push(`/** ${record.label} — ${fieldCount} fields */`);\n lines.push(`export interface ${name} {`);\n\n for (const [fieldId, field] of fieldEntries) {\n const tsType = fieldTypeToTS(field.type);\n lines.push(` /** ${field.label} */`);\n lines.push(` ${fieldId}?: ${tsType};`);\n }\n\n lines.push('}');\n return lines.join('\\n');\n}\n\n/**\n * Emit a TypeScript interface for a single sublist item.\n */\nfunction emitSublistItem(recordId: string, sublistId: string, sublist: SublistDefinition): string {\n const recordName = toPascalCase(recordId);\n const sublistName = toPascalCase(sublistId);\n const interfaceName = `${recordName}${sublistName}Item`;\n const fieldEntries = Object.entries(sublist.fields);\n\n const lines: string[] = [];\n lines.push(`/** ${sublist.label} line item on ${recordName}. */`);\n lines.push(`export interface ${interfaceName} {`);\n\n for (const [fieldId, field] of fieldEntries) {\n const tsType = fieldTypeToTS(field.type);\n lines.push(` /** ${field.label} */`);\n lines.push(` ${fieldId}?: ${tsType};`);\n }\n\n lines.push('}');\n return lines.join('\\n');\n}\n\n/**\n * Emit a CreateInput interface for a record.\n * Excludes readOnly fields and `id`. Required writable fields are non-optional.\n */\nfunction emitCreateInput(recordId: string, record: RecordDefinition): string {\n const name = toPascalCase(recordId);\n const sublistKeys = new Set(Object.keys(record.sublists ?? {}));\n const lines: string[] = [];\n lines.push(`/** Fields for creating a ${record.label}. */`);\n lines.push(`export interface ${name}CreateInput {`);\n\n for (const [fieldId, field] of Object.entries(record.fields)) {\n if (fieldId === 'id' || field.readOnly) continue;\n // Skip fields that collide with sublist names — sublist takes precedence\n if (sublistKeys.has(fieldId)) continue;\n const tsType = fieldTypeToTS(field.type);\n const optional = field.required ? '' : '?';\n lines.push(` /** ${field.label} */`);\n lines.push(` ${fieldId}${optional}: ${tsType};`);\n }\n\n // Sublist fields\n const sublistEntries = Object.entries(record.sublists ?? {});\n for (const [sublistId] of sublistEntries) {\n const itemType = `${name}${toPascalCase(sublistId)}Item`;\n lines.push(` /** ${toPascalCase(sublistId)} sublist. */`);\n lines.push(` ${sublistId}?: { items: ${itemType}[] };`);\n }\n\n lines.push('}');\n return lines.join('\\n');\n}\n\n/**\n * Emit an UpdateInput interface for a record.\n * Excludes readOnly fields and `id`. All fields are optional.\n */\nfunction emitUpdateInput(recordId: string, record: RecordDefinition): string {\n const name = toPascalCase(recordId);\n const sublistKeys = new Set(Object.keys(record.sublists ?? {}));\n const lines: string[] = [];\n lines.push(`/** Fields for updating a ${record.label}. */`);\n lines.push(`export interface ${name}UpdateInput {`);\n\n for (const [fieldId, field] of Object.entries(record.fields)) {\n if (fieldId === 'id' || field.readOnly) continue;\n // Skip fields that collide with sublist names — sublist takes precedence\n if (sublistKeys.has(fieldId)) continue;\n const tsType = fieldTypeToTS(field.type);\n lines.push(` /** ${field.label} */`);\n lines.push(` ${fieldId}?: ${tsType};`);\n }\n\n // Sublist fields\n const sublistEntries = Object.entries(record.sublists ?? {});\n for (const [sublistId] of sublistEntries) {\n const itemType = `${name}${toPascalCase(sublistId)}Item`;\n lines.push(` /** ${toPascalCase(sublistId)} sublist. */`);\n lines.push(` ${sublistId}?: { items: ${itemType}[] };`);\n }\n\n lines.push('}');\n return lines.join('\\n');\n}\n\n/**\n * Emit the full types.ts file content from a schema.\n */\nexport function emitTypes(schema: NormalizedSchema): string {\n const lines: string[] = [\n '// Auto-generated by @suiteportal/generator — DO NOT EDIT',\n `// Generated at: ${new Date().toISOString()}`,\n '',\n ];\n\n const recordEntries = Object.entries(schema.records);\n\n for (const [recordId, record] of recordEntries) {\n lines.push(emitRecordInterface(recordId, record));\n lines.push('');\n\n // Emit sublist item interfaces before Create/UpdateInput (they reference the item types)\n const sublistEntries = Object.entries(record.sublists ?? {});\n for (const [sublistId, sublist] of sublistEntries) {\n lines.push(emitSublistItem(recordId, sublistId, sublist));\n lines.push('');\n }\n\n lines.push(emitCreateInput(recordId, record));\n lines.push('');\n lines.push(emitUpdateInput(recordId, record));\n lines.push('');\n }\n\n // Export a union type of all record names\n if (recordEntries.length > 0) {\n const names = recordEntries.map(([id]) => `'${id}'`);\n lines.push(`/** All available record type IDs. */`);\n lines.push(`export type RecordTypeId = ${names.join(' | ')};`);\n lines.push('');\n\n // Record type map\n lines.push(`/** Map of record type IDs to their TypeScript interfaces. */`);\n lines.push(`export interface RecordTypeMap {`);\n for (const [recordId] of recordEntries) {\n lines.push(` ${recordId}: ${toPascalCase(recordId)};`);\n }\n lines.push('}');\n lines.push('');\n }\n\n return lines.join('\\n');\n}\n","import type { NormalizedSchema } from '@suiteportal/introspector';\nimport { toPascalCase } from '../naming.js';\n\n/**\n * Emit the client.ts file content — a typed wrapper around the base SuitePortalClient.\n */\nexport function emitClient(schema: NormalizedSchema): string {\n const recordEntries = Object.entries(schema.records);\n const typeImports = recordEntries.map(([id]) => toPascalCase(id));\n\n const lines: string[] = [\n '// Auto-generated by suiteportal — DO NOT EDIT',\n `// Generated at: ${new Date().toISOString()}`,\n '',\n `import type { NetSuiteConfig } from 'suiteportal';`,\n `import {`,\n ` SuitePortalClient as BaseClient,`,\n ` getClient as baseGetClient,`,\n ` destroySingleton,`,\n ` type FindManyArgs,`,\n ` type FindFirstArgs,`,\n ` type CountArgs,`,\n ` type CreateArgs,`,\n ` type UpdateArgs,`,\n ` type DeleteArgs,`,\n ` type UpsertArgs,`,\n ` type IncludeInput,`,\n ` type ClientOptions,`,\n `} from 'suiteportal';`,\n ];\n\n if (typeImports.length > 0) {\n const inputImports = recordEntries.flatMap(([id]) => {\n const name = toPascalCase(id);\n return [`${name}CreateInput`, `${name}UpdateInput`];\n });\n lines.push(`import type { ${[...typeImports, ...inputImports].join(', ')} } from './types';`);\n }\n\n lines.push('');\n\n // TypedModelDelegate interface\n lines.push('/** A typed model delegate for a specific record type. */');\n lines.push('export interface TypedModelDelegate<T, TCreate = Record<string, unknown>, TUpdate = Record<string, unknown>> {');\n lines.push(' findMany(args?: FindManyArgs): Promise<T[]>;');\n lines.push(' findFirst(args?: FindFirstArgs): Promise<T | null>;');\n lines.push(' count(args?: CountArgs): Promise<number>;');\n lines.push(' create(args: CreateArgs<TCreate>): Promise<T>;');\n lines.push(' update(args: UpdateArgs<TUpdate>): Promise<T>;');\n lines.push(' delete(args: DeleteArgs): Promise<void>;');\n lines.push(' upsert(args: UpsertArgs<TCreate>): Promise<T>;');\n lines.push('}');\n lines.push('');\n\n // SuitePortalClient interface\n lines.push('/** Typed SuitePortal client with per-record delegates. */');\n lines.push('export interface SuitePortalClient {');\n\n for (const [recordId] of recordEntries) {\n const typeName = toPascalCase(recordId);\n lines.push(` ${recordId}: TypedModelDelegate<${typeName}, ${typeName}CreateInput, ${typeName}UpdateInput>;`);\n }\n\n lines.push(' $queryRaw<T = Record<string, unknown>>(sql: string): Promise<T[]>;');\n lines.push(' $disconnect(): void;');\n lines.push(' $loadSchema(): Promise<void>;');\n lines.push('}');\n lines.push('');\n\n // createClient function\n lines.push('/**');\n lines.push(' * Create a typed SuitePortal client.');\n lines.push(' * Loads schema.json and provides typed access to all record types.');\n lines.push(' */');\n lines.push('export async function createClient(');\n lines.push(' config: NetSuiteConfig,');\n lines.push(' options?: ClientOptions,');\n lines.push('): Promise<SuitePortalClient> {');\n lines.push(' const client = new BaseClient(config, options);');\n lines.push(' await client.$loadSchema();');\n lines.push(' return client as unknown as SuitePortalClient;');\n lines.push('}');\n lines.push('');\n\n // getClient singleton\n lines.push('/**');\n lines.push(' * Get (or create) a process-wide singleton typed client.');\n lines.push(' * Safe for use across server components, server actions, and API routes.');\n lines.push(' */');\n lines.push('export async function getClient(');\n lines.push(' config: NetSuiteConfig,');\n lines.push(' options?: ClientOptions,');\n lines.push('): Promise<SuitePortalClient> {');\n lines.push(' return baseGetClient(config, options) as Promise<unknown> as Promise<SuitePortalClient>;');\n lines.push('}');\n lines.push('');\n\n // Re-export destroySingleton\n lines.push('export { destroySingleton };');\n lines.push('');\n\n // Re-export types for convenience\n lines.push('export type { FindManyArgs, FindFirstArgs, CountArgs, CreateArgs, UpdateArgs, DeleteArgs, UpsertArgs, IncludeInput } from \\'suiteportal\\';');\n lines.push('');\n\n return lines.join('\\n');\n}\n","import type { NormalizedSchema } from '@suiteportal/introspector';\nimport { toPascalCase } from '../naming.js';\n\n/**\n * Emit the index.ts barrel export file content.\n */\nexport function emitBarrel(schema: NormalizedSchema): string {\n const recordEntries = Object.entries(schema.records);\n const typeNames = recordEntries.map(([id]) => toPascalCase(id));\n\n const lines: string[] = [\n '// Auto-generated by @suiteportal/generator — DO NOT EDIT',\n `// Generated at: ${new Date().toISOString()}`,\n '',\n ];\n\n // Type exports\n if (typeNames.length > 0) {\n const inputTypes = recordEntries.flatMap(([id]) => {\n const name = toPascalCase(id);\n return [`${name}CreateInput`, `${name}UpdateInput`];\n });\n lines.push(`export type { ${[...typeNames, ...inputTypes].join(', ')}, RecordTypeId, RecordTypeMap } from './types';`);\n }\n\n // Client exports\n lines.push(`export type { SuitePortalClient, TypedModelDelegate } from './client';`);\n lines.push(`export { createClient } from './client';`);\n lines.push(`export type { FindManyArgs, FindFirstArgs, CountArgs, CreateArgs, UpdateArgs, DeleteArgs, IncludeInput } from './client';`);\n lines.push('');\n\n return lines.join('\\n');\n}\n"],"mappings":"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","names":["import_promises"]}
1
+ {"version":3,"sources":["../src/index.ts","../src/generate.ts","../src/schema-reader.ts","../src/naming.ts","../src/emitters/type-emitter.ts","../src/emitters/client-emitter.ts","../src/emitters/barrel-emitter.ts"],"sourcesContent":["// Generator\nexport { generate } from './generate.js';\n\n// Schema reader\nexport { readSchema } from './schema-reader.js';\n\n// Naming utilities\nexport { toPascalCase, fieldTypeToTS } from './naming.js';\n\n// Emitters\nexport { emitTypes } from './emitters/type-emitter.js';\nexport { emitClient } from './emitters/client-emitter.js';\nexport { emitBarrel } from './emitters/barrel-emitter.js';\n\n// Types\nexport type { GenerateOptions, GenerateResult } from './types.js';\n","import { mkdir, writeFile } from 'node:fs/promises';\nimport { join } from 'node:path';\nimport { readSchema } from './schema-reader.js';\nimport { emitTypes } from './emitters/type-emitter.js';\nimport { emitClient } from './emitters/client-emitter.js';\nimport { emitBarrel } from './emitters/barrel-emitter.js';\nimport type { GenerateOptions, GenerateResult } from './types.js';\n\nconst DEFAULT_SCHEMA_PATH = '.suiteportal/schema.json';\nconst DEFAULT_OUTPUT_DIR = '.suiteportal/client';\n\n/**\n * Generate typed client code from a schema.json file.\n *\n * Reads the introspected schema, emits TypeScript interfaces for all records,\n * a typed client wrapper, and a barrel export file.\n */\nexport async function generate(options?: GenerateOptions): Promise<GenerateResult> {\n const schemaPath = options?.schemaPath ?? DEFAULT_SCHEMA_PATH;\n const outputDir = options?.outputDir ?? DEFAULT_OUTPUT_DIR;\n\n // Read schema\n const schema = await readSchema(schemaPath);\n\n // Ensure output directory exists\n await mkdir(outputDir, { recursive: true });\n\n // Generate files\n const typesContent = emitTypes(schema);\n const clientContent = emitClient(schema);\n const barrelContent = emitBarrel(schema);\n\n // Write files\n const typesPath = join(outputDir, 'types.ts');\n const clientPath = join(outputDir, 'client.ts');\n const barrelPath = join(outputDir, 'index.ts');\n\n await Promise.all([\n writeFile(typesPath, typesContent, 'utf-8'),\n writeFile(clientPath, clientContent, 'utf-8'),\n writeFile(barrelPath, barrelContent, 'utf-8'),\n ]);\n\n // Compute stats\n const recordEntries = Object.entries(schema.records);\n const fieldCount = recordEntries.reduce(\n (sum, [, record]) => sum + Object.keys(record.fields).length,\n 0,\n );\n\n return {\n recordCount: recordEntries.length,\n fieldCount,\n files: [typesPath, clientPath, barrelPath],\n outputDir,\n };\n}\n","import { readFile } from 'node:fs/promises';\nimport type { NormalizedSchema } from '@suiteportal/introspector';\n\n/**\n * Read and parse a schema.json file.\n */\nexport async function readSchema(schemaPath: string): Promise<NormalizedSchema> {\n const raw = await readFile(schemaPath, 'utf-8');\n const schema = JSON.parse(raw) as NormalizedSchema;\n\n if (!schema.records || typeof schema.records !== 'object') {\n throw new Error(`Invalid schema: missing \"records\" in ${schemaPath}`);\n }\n\n return schema;\n}\n","import type { FieldType } from '@suiteportal/introspector';\n\n/**\n * Convert a record ID to PascalCase for use as a TypeScript interface name.\n * Examples:\n * 'customer' → 'Customer'\n * 'salesorder' → 'Salesorder'\n * 'customrecord_mytype' → 'CustomrecordMytype'\n */\nexport function toPascalCase(name: string): string {\n return name\n .split('_')\n .map((part) => (part.length > 0 ? part[0]!.toUpperCase() + part.slice(1).toLowerCase() : ''))\n .join('');\n}\n\n/**\n * Map a normalized FieldType to its TypeScript type representation.\n */\nexport function fieldTypeToTS(fieldType: FieldType): string {\n switch (fieldType) {\n case 'string':\n case 'text':\n case 'richtext':\n case 'email':\n case 'url':\n case 'phone':\n return 'string';\n\n case 'integer':\n case 'float':\n case 'currency':\n case 'percent':\n return 'number';\n\n case 'boolean':\n return 'boolean';\n\n case 'date':\n case 'datetime':\n return 'string'; // SuiteQL returns date strings\n\n case 'select':\n return 'string | number';\n\n case 'multiselect':\n return 'string';\n\n case 'unknown':\n default:\n return 'unknown';\n }\n}\n","import type { NormalizedSchema, RecordDefinition, FieldDefinition, SublistDefinition, FieldType } from '@suiteportal/introspector';\nimport { toPascalCase, fieldTypeToTS } from '../naming.js';\n\n/**\n * Map a FieldType to its filter type name and shorthand value type.\n */\nfunction fieldTypeToFilter(fieldType: FieldType): { filterType: string; shorthand: string } {\n switch (fieldType) {\n case 'string':\n case 'text':\n case 'richtext':\n case 'email':\n case 'url':\n case 'phone':\n case 'date':\n case 'datetime':\n case 'multiselect':\n return { filterType: 'StringFilter', shorthand: 'string' };\n\n case 'integer':\n case 'float':\n case 'currency':\n case 'percent':\n return { filterType: 'NumberFilter', shorthand: 'number' };\n\n case 'boolean':\n return { filterType: 'BooleanFilter', shorthand: 'boolean' };\n\n case 'select':\n return { filterType: 'SelectFilter', shorthand: 'string | number' };\n\n case 'unknown':\n default:\n return { filterType: 'StringFilter', shorthand: 'unknown' };\n }\n}\n\n/**\n * Emit shared filter type interfaces used by all per-record WhereInput types.\n */\nfunction emitFilterTypes(): string {\n return `/** String field filter operators. */\nexport interface StringFilter {\n equals?: string | null;\n not?: string | null;\n in?: string[];\n notIn?: string[];\n gt?: string;\n gte?: string;\n lt?: string;\n lte?: string;\n contains?: string;\n startsWith?: string;\n endsWith?: string;\n isNull?: boolean;\n}\n\n/** Number field filter operators. */\nexport interface NumberFilter {\n equals?: number | null;\n not?: number | null;\n in?: number[];\n notIn?: number[];\n gt?: number;\n gte?: number;\n lt?: number;\n lte?: number;\n isNull?: boolean;\n}\n\n/** Boolean field filter operators. */\nexport interface BooleanFilter {\n equals?: boolean | null;\n not?: boolean | null;\n isNull?: boolean;\n}\n\n/** Select (string | number) field filter operators. */\nexport interface SelectFilter {\n equals?: string | number | null;\n not?: string | number | null;\n in?: (string | number)[];\n notIn?: (string | number)[];\n gt?: string | number;\n gte?: string | number;\n lt?: string | number;\n lte?: string | number;\n isNull?: boolean;\n}`;\n}\n\n/**\n * Emit a per-record WhereInput type with typed fields.\n */\nfunction emitWhereInput(recordId: string, record: RecordDefinition): string {\n const name = toPascalCase(recordId);\n const lines: string[] = [];\n lines.push(`/** Where clause for ${record.label} queries. */`);\n lines.push(`export interface ${name}WhereInput {`);\n\n for (const [fieldId, field] of Object.entries(record.fields)) {\n const { filterType, shorthand } = fieldTypeToFilter(field.type);\n lines.push(` /** ${field.label} */`);\n lines.push(` ${fieldId}?: ${shorthand} | ${filterType};`);\n }\n\n lines.push(` AND?: ${name}WhereInput[];`);\n lines.push(` OR?: ${name}WhereInput[];`);\n lines.push(` NOT?: ${name}WhereInput;`);\n lines.push('}');\n return lines.join('\\n');\n}\n\n/**\n * Emit a per-record Select type.\n */\nfunction emitSelectType(recordId: string, record: RecordDefinition): string {\n const name = toPascalCase(recordId);\n const lines: string[] = [];\n lines.push(`/** Field selection for ${record.label} queries. */`);\n lines.push(`export interface ${name}Select {`);\n\n for (const [fieldId, field] of Object.entries(record.fields)) {\n lines.push(` /** ${field.label} */`);\n lines.push(` ${fieldId}?: boolean;`);\n }\n\n lines.push('}');\n return lines.join('\\n');\n}\n\n/**\n * Emit a per-record OrderByInput type.\n */\nfunction emitOrderByType(recordId: string, record: RecordDefinition): string {\n const name = toPascalCase(recordId);\n const lines: string[] = [];\n lines.push(`/** Order by clause for ${record.label} queries. */`);\n lines.push(`export interface ${name}OrderByInput {`);\n\n for (const [fieldId, field] of Object.entries(record.fields)) {\n lines.push(` /** ${field.label} */`);\n lines.push(` ${fieldId}?: 'asc' | 'desc';`);\n }\n\n lines.push('}');\n return lines.join('\\n');\n}\n\n/**\n * Emit a TypeScript interface for a single record.\n */\nfunction emitRecordInterface(recordId: string, record: RecordDefinition): string {\n const name = toPascalCase(recordId);\n const fieldEntries = Object.entries(record.fields);\n const fieldCount = fieldEntries.length;\n\n const lines: string[] = [];\n lines.push(`/** ${record.label} — ${fieldCount} fields */`);\n lines.push(`export interface ${name} {`);\n\n for (const [fieldId, field] of fieldEntries) {\n const tsType = fieldTypeToTS(field.type);\n lines.push(` /** ${field.label} */`);\n lines.push(` ${fieldId}?: ${tsType};`);\n }\n\n lines.push('}');\n return lines.join('\\n');\n}\n\n/**\n * Emit a TypeScript interface for a single sublist item.\n */\nfunction emitSublistItem(recordId: string, sublistId: string, sublist: SublistDefinition): string {\n const recordName = toPascalCase(recordId);\n const sublistName = toPascalCase(sublistId);\n const interfaceName = `${recordName}${sublistName}Item`;\n const fieldEntries = Object.entries(sublist.fields);\n\n const lines: string[] = [];\n lines.push(`/** ${sublist.label} line item on ${recordName}. */`);\n lines.push(`export interface ${interfaceName} {`);\n\n for (const [fieldId, field] of fieldEntries) {\n const tsType = fieldTypeToTS(field.type);\n lines.push(` /** ${field.label} */`);\n lines.push(` ${fieldId}?: ${tsType};`);\n }\n\n lines.push('}');\n return lines.join('\\n');\n}\n\n/**\n * Emit a CreateInput interface for a record.\n * Excludes readOnly fields and `id`. Required writable fields are non-optional.\n */\nfunction emitCreateInput(recordId: string, record: RecordDefinition): string {\n const name = toPascalCase(recordId);\n const sublistKeys = new Set(Object.keys(record.sublists ?? {}));\n const lines: string[] = [];\n lines.push(`/** Fields for creating a ${record.label}. */`);\n lines.push(`export interface ${name}CreateInput {`);\n\n for (const [fieldId, field] of Object.entries(record.fields)) {\n if (fieldId === 'id' || field.readOnly) continue;\n // Skip fields that collide with sublist names — sublist takes precedence\n if (sublistKeys.has(fieldId)) continue;\n const tsType = fieldTypeToTS(field.type);\n const optional = field.required ? '' : '?';\n lines.push(` /** ${field.label} */`);\n lines.push(` ${fieldId}${optional}: ${tsType};`);\n }\n\n // Sublist fields\n const sublistEntries = Object.entries(record.sublists ?? {});\n for (const [sublistId] of sublistEntries) {\n const itemType = `${name}${toPascalCase(sublistId)}Item`;\n lines.push(` /** ${toPascalCase(sublistId)} sublist. */`);\n lines.push(` ${sublistId}?: { items: ${itemType}[] };`);\n }\n\n lines.push('}');\n return lines.join('\\n');\n}\n\n/**\n * Emit an UpdateInput interface for a record.\n * Excludes readOnly fields and `id`. All fields are optional.\n */\nfunction emitUpdateInput(recordId: string, record: RecordDefinition): string {\n const name = toPascalCase(recordId);\n const sublistKeys = new Set(Object.keys(record.sublists ?? {}));\n const lines: string[] = [];\n lines.push(`/** Fields for updating a ${record.label}. */`);\n lines.push(`export interface ${name}UpdateInput {`);\n\n for (const [fieldId, field] of Object.entries(record.fields)) {\n if (fieldId === 'id' || field.readOnly) continue;\n // Skip fields that collide with sublist names — sublist takes precedence\n if (sublistKeys.has(fieldId)) continue;\n const tsType = fieldTypeToTS(field.type);\n lines.push(` /** ${field.label} */`);\n lines.push(` ${fieldId}?: ${tsType};`);\n }\n\n // Sublist fields\n const sublistEntries = Object.entries(record.sublists ?? {});\n for (const [sublistId] of sublistEntries) {\n const itemType = `${name}${toPascalCase(sublistId)}Item`;\n lines.push(` /** ${toPascalCase(sublistId)} sublist. */`);\n lines.push(` ${sublistId}?: { items: ${itemType}[] };`);\n }\n\n lines.push('}');\n return lines.join('\\n');\n}\n\n/**\n * Emit the full types.ts file content from a schema.\n */\nexport function emitTypes(schema: NormalizedSchema): string {\n const lines: string[] = [\n '// Auto-generated by @suiteportal/generator — DO NOT EDIT',\n `// Generated at: ${new Date().toISOString()}`,\n '',\n ];\n\n const recordEntries = Object.entries(schema.records);\n\n // Emit shared filter types first (used by all WhereInput types)\n if (recordEntries.length > 0) {\n lines.push(emitFilterTypes());\n lines.push('');\n }\n\n for (const [recordId, record] of recordEntries) {\n lines.push(emitRecordInterface(recordId, record));\n lines.push('');\n\n // Emit sublist item interfaces before Create/UpdateInput (they reference the item types)\n const sublistEntries = Object.entries(record.sublists ?? {});\n for (const [sublistId, sublist] of sublistEntries) {\n lines.push(emitSublistItem(recordId, sublistId, sublist));\n lines.push('');\n }\n\n lines.push(emitCreateInput(recordId, record));\n lines.push('');\n lines.push(emitUpdateInput(recordId, record));\n lines.push('');\n\n // Emit per-record query types (WhereInput, Select, OrderByInput)\n lines.push(emitWhereInput(recordId, record));\n lines.push('');\n lines.push(emitSelectType(recordId, record));\n lines.push('');\n lines.push(emitOrderByType(recordId, record));\n lines.push('');\n }\n\n // Export a union type of all record names\n if (recordEntries.length > 0) {\n const names = recordEntries.map(([id]) => `'${id}'`);\n lines.push(`/** All available record type IDs. */`);\n lines.push(`export type RecordTypeId = ${names.join(' | ')};`);\n lines.push('');\n\n // Record type map\n lines.push(`/** Map of record type IDs to their TypeScript interfaces. */`);\n lines.push(`export interface RecordTypeMap {`);\n for (const [recordId] of recordEntries) {\n lines.push(` ${recordId}: ${toPascalCase(recordId)};`);\n }\n lines.push('}');\n lines.push('');\n }\n\n return lines.join('\\n');\n}\n","import type { NormalizedSchema } from '@suiteportal/introspector';\nimport { toPascalCase } from '../naming.js';\n\n/**\n * Emit a per-record delegate interface with fully typed query args.\n */\nfunction emitDelegate(recordId: string): string {\n const name = toPascalCase(recordId);\n const lines: string[] = [];\n lines.push(`/** Typed delegate for ${name} records. */`);\n lines.push(`export interface ${name}Delegate {`);\n lines.push(` findMany(args?: { where?: ${name}WhereInput; select?: ${name}Select; orderBy?: ${name}OrderByInput; include?: IncludeInput; take?: number; skip?: number }): Promise<${name}[]>;`);\n lines.push(` findFirst(args?: { where?: ${name}WhereInput; select?: ${name}Select; orderBy?: ${name}OrderByInput; include?: IncludeInput; skip?: number }): Promise<${name} | null>;`);\n lines.push(` count(args?: { where?: ${name}WhereInput }): Promise<number>;`);\n lines.push(` create(args: { data: ${name}CreateInput }): Promise<${name}>;`);\n lines.push(` update(args: { where: { id: { equals: string | number } }; data: ${name}UpdateInput }): Promise<${name}>;`);\n lines.push(` delete(args: { where: { id: { equals: string | number } } }): Promise<void>;`);\n lines.push(` upsert(args: { where: { externalId: string }; data: ${name}CreateInput }): Promise<${name}>;`);\n lines.push('}');\n return lines.join('\\n');\n}\n\n/**\n * Emit the client.ts file content — a typed wrapper around the base SuitePortalClient.\n */\nexport function emitClient(schema: NormalizedSchema): string {\n const recordEntries = Object.entries(schema.records);\n const typeImports = recordEntries.map(([id]) => toPascalCase(id));\n\n const lines: string[] = [\n '// Auto-generated by suiteportal — DO NOT EDIT',\n `// Generated at: ${new Date().toISOString()}`,\n '',\n `import type { NetSuiteConfig } from 'suiteportal';`,\n `import {`,\n ` SuitePortalClient as BaseClient,`,\n ` getClient as baseGetClient,`,\n ` destroySingleton,`,\n ` type IncludeInput,`,\n ` type ClientOptions,`,\n `} from 'suiteportal';`,\n ];\n\n if (typeImports.length > 0) {\n const perRecordImports = recordEntries.flatMap(([id]) => {\n const name = toPascalCase(id);\n return [\n name,\n `${name}CreateInput`,\n `${name}UpdateInput`,\n `${name}WhereInput`,\n `${name}Select`,\n `${name}OrderByInput`,\n ];\n });\n lines.push(`import type { ${perRecordImports.join(', ')} } from './types';`);\n }\n\n lines.push('');\n\n // Per-record delegate interfaces\n for (const [recordId] of recordEntries) {\n lines.push(emitDelegate(recordId));\n lines.push('');\n }\n\n // SuitePortalClient interface\n lines.push('/** Typed SuitePortal client with per-record delegates. */');\n lines.push('export interface SuitePortalClient {');\n\n for (const [recordId] of recordEntries) {\n const typeName = toPascalCase(recordId);\n lines.push(` ${recordId}: ${typeName}Delegate;`);\n }\n\n lines.push(' $queryRaw<T = Record<string, unknown>>(sql: string): Promise<T[]>;');\n lines.push(' $disconnect(): void;');\n lines.push(' $loadSchema(): Promise<void>;');\n lines.push('}');\n lines.push('');\n\n // createClient function\n lines.push('/**');\n lines.push(' * Create a typed SuitePortal client.');\n lines.push(' * Loads schema.json and provides typed access to all record types.');\n lines.push(' */');\n lines.push('export async function createClient(');\n lines.push(' config: NetSuiteConfig,');\n lines.push(' options?: ClientOptions,');\n lines.push('): Promise<SuitePortalClient> {');\n lines.push(' const client = new BaseClient(config, options);');\n lines.push(' await client.$loadSchema();');\n lines.push(' return client as unknown as SuitePortalClient;');\n lines.push('}');\n lines.push('');\n\n // getClient singleton\n lines.push('/**');\n lines.push(' * Get (or create) a process-wide singleton typed client.');\n lines.push(' * Safe for use across server components, server actions, and API routes.');\n lines.push(' */');\n lines.push('export async function getClient(');\n lines.push(' config: NetSuiteConfig,');\n lines.push(' options?: ClientOptions,');\n lines.push('): Promise<SuitePortalClient> {');\n lines.push(' return baseGetClient(config, options) as Promise<unknown> as Promise<SuitePortalClient>;');\n lines.push('}');\n lines.push('');\n\n // Re-export destroySingleton\n lines.push('export { destroySingleton };');\n lines.push('');\n\n // Re-export types for convenience\n lines.push('export type { IncludeInput } from \\'suiteportal\\';');\n lines.push('');\n\n return lines.join('\\n');\n}\n","import type { NormalizedSchema } from '@suiteportal/introspector';\nimport { toPascalCase } from '../naming.js';\n\n/**\n * Emit the index.ts barrel export file content.\n */\nexport function emitBarrel(schema: NormalizedSchema): string {\n const recordEntries = Object.entries(schema.records);\n const typeNames = recordEntries.map(([id]) => toPascalCase(id));\n\n const lines: string[] = [\n '// Auto-generated by @suiteportal/generator — DO NOT EDIT',\n `// Generated at: ${new Date().toISOString()}`,\n '',\n ];\n\n // Type exports\n if (typeNames.length > 0) {\n const perRecordTypes = recordEntries.flatMap(([id]) => {\n const name = toPascalCase(id);\n return [\n `${name}CreateInput`,\n `${name}UpdateInput`,\n `${name}WhereInput`,\n `${name}Select`,\n `${name}OrderByInput`,\n ];\n });\n lines.push(`export type { ${[...typeNames, ...perRecordTypes].join(', ')}, RecordTypeId, RecordTypeMap } from './types';`);\n lines.push(`export type { StringFilter, NumberFilter, BooleanFilter, SelectFilter } from './types';`);\n }\n\n // Client exports\n const delegateTypes = recordEntries.map(([id]) => `${toPascalCase(id)}Delegate`);\n lines.push(`export type { SuitePortalClient${delegateTypes.length > 0 ? ', ' + delegateTypes.join(', ') : ''} } from './client';`);\n lines.push(`export { createClient } from './client';`);\n lines.push(`export type { IncludeInput } from './client';`);\n lines.push('');\n\n return lines.join('\\n');\n}\n"],"mappings":"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","names":["import_promises"]}
package/dist/index.js CHANGED
@@ -48,6 +48,122 @@ function fieldTypeToTS(fieldType) {
48
48
  }
49
49
 
50
50
  // src/emitters/type-emitter.ts
51
+ function fieldTypeToFilter(fieldType) {
52
+ switch (fieldType) {
53
+ case "string":
54
+ case "text":
55
+ case "richtext":
56
+ case "email":
57
+ case "url":
58
+ case "phone":
59
+ case "date":
60
+ case "datetime":
61
+ case "multiselect":
62
+ return { filterType: "StringFilter", shorthand: "string" };
63
+ case "integer":
64
+ case "float":
65
+ case "currency":
66
+ case "percent":
67
+ return { filterType: "NumberFilter", shorthand: "number" };
68
+ case "boolean":
69
+ return { filterType: "BooleanFilter", shorthand: "boolean" };
70
+ case "select":
71
+ return { filterType: "SelectFilter", shorthand: "string | number" };
72
+ case "unknown":
73
+ default:
74
+ return { filterType: "StringFilter", shorthand: "unknown" };
75
+ }
76
+ }
77
+ function emitFilterTypes() {
78
+ return `/** String field filter operators. */
79
+ export interface StringFilter {
80
+ equals?: string | null;
81
+ not?: string | null;
82
+ in?: string[];
83
+ notIn?: string[];
84
+ gt?: string;
85
+ gte?: string;
86
+ lt?: string;
87
+ lte?: string;
88
+ contains?: string;
89
+ startsWith?: string;
90
+ endsWith?: string;
91
+ isNull?: boolean;
92
+ }
93
+
94
+ /** Number field filter operators. */
95
+ export interface NumberFilter {
96
+ equals?: number | null;
97
+ not?: number | null;
98
+ in?: number[];
99
+ notIn?: number[];
100
+ gt?: number;
101
+ gte?: number;
102
+ lt?: number;
103
+ lte?: number;
104
+ isNull?: boolean;
105
+ }
106
+
107
+ /** Boolean field filter operators. */
108
+ export interface BooleanFilter {
109
+ equals?: boolean | null;
110
+ not?: boolean | null;
111
+ isNull?: boolean;
112
+ }
113
+
114
+ /** Select (string | number) field filter operators. */
115
+ export interface SelectFilter {
116
+ equals?: string | number | null;
117
+ not?: string | number | null;
118
+ in?: (string | number)[];
119
+ notIn?: (string | number)[];
120
+ gt?: string | number;
121
+ gte?: string | number;
122
+ lt?: string | number;
123
+ lte?: string | number;
124
+ isNull?: boolean;
125
+ }`;
126
+ }
127
+ function emitWhereInput(recordId, record) {
128
+ const name = toPascalCase(recordId);
129
+ const lines = [];
130
+ lines.push(`/** Where clause for ${record.label} queries. */`);
131
+ lines.push(`export interface ${name}WhereInput {`);
132
+ for (const [fieldId, field] of Object.entries(record.fields)) {
133
+ const { filterType, shorthand } = fieldTypeToFilter(field.type);
134
+ lines.push(` /** ${field.label} */`);
135
+ lines.push(` ${fieldId}?: ${shorthand} | ${filterType};`);
136
+ }
137
+ lines.push(` AND?: ${name}WhereInput[];`);
138
+ lines.push(` OR?: ${name}WhereInput[];`);
139
+ lines.push(` NOT?: ${name}WhereInput;`);
140
+ lines.push("}");
141
+ return lines.join("\n");
142
+ }
143
+ function emitSelectType(recordId, record) {
144
+ const name = toPascalCase(recordId);
145
+ const lines = [];
146
+ lines.push(`/** Field selection for ${record.label} queries. */`);
147
+ lines.push(`export interface ${name}Select {`);
148
+ for (const [fieldId, field] of Object.entries(record.fields)) {
149
+ lines.push(` /** ${field.label} */`);
150
+ lines.push(` ${fieldId}?: boolean;`);
151
+ }
152
+ lines.push("}");
153
+ return lines.join("\n");
154
+ }
155
+ function emitOrderByType(recordId, record) {
156
+ const name = toPascalCase(recordId);
157
+ const lines = [];
158
+ lines.push(`/** Order by clause for ${record.label} queries. */`);
159
+ lines.push(`export interface ${name}OrderByInput {`);
160
+ for (const [fieldId, field] of Object.entries(record.fields)) {
161
+ lines.push(` /** ${field.label} */`);
162
+ lines.push(` ${fieldId}?: 'asc' | 'desc';`);
163
+ }
164
+ lines.push("}");
165
+ return lines.join("\n");
166
+ }
51
167
  function emitRecordInterface(recordId, record) {
52
168
  const name = toPascalCase(recordId);
53
169
  const fieldEntries = Object.entries(record.fields);
@@ -131,6 +247,10 @@ function emitTypes(schema) {
131
247
  ""
132
248
  ];
133
249
  const recordEntries = Object.entries(schema.records);
250
+ if (recordEntries.length > 0) {
251
+ lines.push(emitFilterTypes());
252
+ lines.push("");
253
+ }
134
254
  for (const [recordId, record] of recordEntries) {
135
255
  lines.push(emitRecordInterface(recordId, record));
136
256
  lines.push("");
@@ -143,6 +263,12 @@ function emitTypes(schema) {
143
263
  lines.push("");
144
264
  lines.push(emitUpdateInput(recordId, record));
145
265
  lines.push("");
266
+ lines.push(emitWhereInput(recordId, record));
267
+ lines.push("");
268
+ lines.push(emitSelectType(recordId, record));
269
+ lines.push("");
270
+ lines.push(emitOrderByType(recordId, record));
271
+ lines.push("");
146
272
  }
147
273
  if (recordEntries.length > 0) {
148
274
  const names = recordEntries.map(([id]) => `'${id}'`);
@@ -161,6 +287,21 @@ function emitTypes(schema) {
161
287
  }
162
288
 
163
289
  // src/emitters/client-emitter.ts
290
+ function emitDelegate(recordId) {
291
+ const name = toPascalCase(recordId);
292
+ const lines = [];
293
+ lines.push(`/** Typed delegate for ${name} records. */`);
294
+ lines.push(`export interface ${name}Delegate {`);
295
+ lines.push(` findMany(args?: { where?: ${name}WhereInput; select?: ${name}Select; orderBy?: ${name}OrderByInput; include?: IncludeInput; take?: number; skip?: number }): Promise<${name}[]>;`);
296
+ lines.push(` findFirst(args?: { where?: ${name}WhereInput; select?: ${name}Select; orderBy?: ${name}OrderByInput; include?: IncludeInput; skip?: number }): Promise<${name} | null>;`);
297
+ lines.push(` count(args?: { where?: ${name}WhereInput }): Promise<number>;`);
298
+ lines.push(` create(args: { data: ${name}CreateInput }): Promise<${name}>;`);
299
+ lines.push(` update(args: { where: { id: { equals: string | number } }; data: ${name}UpdateInput }): Promise<${name}>;`);
300
+ lines.push(` delete(args: { where: { id: { equals: string | number } } }): Promise<void>;`);
301
+ lines.push(` upsert(args: { where: { externalId: string }; data: ${name}CreateInput }): Promise<${name}>;`);
302
+ lines.push("}");
303
+ return lines.join("\n");
304
+ }
164
305
  function emitClient(schema) {
165
306
  const recordEntries = Object.entries(schema.records);
166
307
  const typeImports = recordEntries.map(([id]) => toPascalCase(id));
@@ -173,41 +314,34 @@ function emitClient(schema) {
173
314
  ` SuitePortalClient as BaseClient,`,
174
315
  ` getClient as baseGetClient,`,
175
316
  ` destroySingleton,`,
176
- ` type FindManyArgs,`,
177
- ` type FindFirstArgs,`,
178
- ` type CountArgs,`,
179
- ` type CreateArgs,`,
180
- ` type UpdateArgs,`,
181
- ` type DeleteArgs,`,
182
- ` type UpsertArgs,`,
183
317
  ` type IncludeInput,`,
184
318
  ` type ClientOptions,`,
185
319
  `} from 'suiteportal';`
186
320
  ];
187
321
  if (typeImports.length > 0) {
188
- const inputImports = recordEntries.flatMap(([id]) => {
322
+ const perRecordImports = recordEntries.flatMap(([id]) => {
189
323
  const name = toPascalCase(id);
190
- return [`${name}CreateInput`, `${name}UpdateInput`];
324
+ return [
325
+ name,
326
+ `${name}CreateInput`,
327
+ `${name}UpdateInput`,
328
+ `${name}WhereInput`,
329
+ `${name}Select`,
330
+ `${name}OrderByInput`
331
+ ];
191
332
  });
192
- lines.push(`import type { ${[...typeImports, ...inputImports].join(", ")} } from './types';`);
333
+ lines.push(`import type { ${perRecordImports.join(", ")} } from './types';`);
193
334
  }
194
335
  lines.push("");
195
- lines.push("/** A typed model delegate for a specific record type. */");
196
- lines.push("export interface TypedModelDelegate<T, TCreate = Record<string, unknown>, TUpdate = Record<string, unknown>> {");
197
- lines.push(" findMany(args?: FindManyArgs): Promise<T[]>;");
198
- lines.push(" findFirst(args?: FindFirstArgs): Promise<T | null>;");
199
- lines.push(" count(args?: CountArgs): Promise<number>;");
200
- lines.push(" create(args: CreateArgs<TCreate>): Promise<T>;");
201
- lines.push(" update(args: UpdateArgs<TUpdate>): Promise<T>;");
202
- lines.push(" delete(args: DeleteArgs): Promise<void>;");
203
- lines.push(" upsert(args: UpsertArgs<TCreate>): Promise<T>;");
204
- lines.push("}");
205
- lines.push("");
336
+ for (const [recordId] of recordEntries) {
337
+ lines.push(emitDelegate(recordId));
338
+ lines.push("");
339
+ }
206
340
  lines.push("/** Typed SuitePortal client with per-record delegates. */");
207
341
  lines.push("export interface SuitePortalClient {");
208
342
  for (const [recordId] of recordEntries) {
209
343
  const typeName = toPascalCase(recordId);
210
- lines.push(` ${recordId}: TypedModelDelegate<${typeName}, ${typeName}CreateInput, ${typeName}UpdateInput>;`);
344
+ lines.push(` ${recordId}: ${typeName}Delegate;`);
211
345
  }
212
346
  lines.push(" $queryRaw<T = Record<string, unknown>>(sql: string): Promise<T[]>;");
213
347
  lines.push(" $disconnect(): void;");
@@ -240,7 +374,7 @@ function emitClient(schema) {
240
374
  lines.push("");
241
375
  lines.push("export { destroySingleton };");
242
376
  lines.push("");
243
- lines.push("export type { FindManyArgs, FindFirstArgs, CountArgs, CreateArgs, UpdateArgs, DeleteArgs, UpsertArgs, IncludeInput } from 'suiteportal';");
377
+ lines.push("export type { IncludeInput } from 'suiteportal';");
244
378
  lines.push("");
245
379
  return lines.join("\n");
246
380
  }
@@ -255,15 +389,23 @@ function emitBarrel(schema) {
255
389
  ""
256
390
  ];
257
391
  if (typeNames.length > 0) {
258
- const inputTypes = recordEntries.flatMap(([id]) => {
392
+ const perRecordTypes = recordEntries.flatMap(([id]) => {
259
393
  const name = toPascalCase(id);
260
- return [`${name}CreateInput`, `${name}UpdateInput`];
394
+ return [
395
+ `${name}CreateInput`,
396
+ `${name}UpdateInput`,
397
+ `${name}WhereInput`,
398
+ `${name}Select`,
399
+ `${name}OrderByInput`
400
+ ];
261
401
  });
262
- lines.push(`export type { ${[...typeNames, ...inputTypes].join(", ")}, RecordTypeId, RecordTypeMap } from './types';`);
402
+ lines.push(`export type { ${[...typeNames, ...perRecordTypes].join(", ")}, RecordTypeId, RecordTypeMap } from './types';`);
403
+ lines.push(`export type { StringFilter, NumberFilter, BooleanFilter, SelectFilter } from './types';`);
263
404
  }
264
- lines.push(`export type { SuitePortalClient, TypedModelDelegate } from './client';`);
405
+ const delegateTypes = recordEntries.map(([id]) => `${toPascalCase(id)}Delegate`);
406
+ lines.push(`export type { SuitePortalClient${delegateTypes.length > 0 ? ", " + delegateTypes.join(", ") : ""} } from './client';`);
265
407
  lines.push(`export { createClient } from './client';`);
266
- lines.push(`export type { FindManyArgs, FindFirstArgs, CountArgs, CreateArgs, UpdateArgs, DeleteArgs, IncludeInput } from './client';`);
408
+ lines.push(`export type { IncludeInput } from './client';`);
267
409
  lines.push("");
268
410
  return lines.join("\n");
269
411
  }
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/generate.ts","../src/schema-reader.ts","../src/naming.ts","../src/emitters/type-emitter.ts","../src/emitters/client-emitter.ts","../src/emitters/barrel-emitter.ts"],"sourcesContent":["import { mkdir, writeFile } from 'node:fs/promises';\nimport { join } from 'node:path';\nimport { readSchema } from './schema-reader.js';\nimport { emitTypes } from './emitters/type-emitter.js';\nimport { emitClient } from './emitters/client-emitter.js';\nimport { emitBarrel } from './emitters/barrel-emitter.js';\nimport type { GenerateOptions, GenerateResult } from './types.js';\n\nconst DEFAULT_SCHEMA_PATH = '.suiteportal/schema.json';\nconst DEFAULT_OUTPUT_DIR = '.suiteportal/client';\n\n/**\n * Generate typed client code from a schema.json file.\n *\n * Reads the introspected schema, emits TypeScript interfaces for all records,\n * a typed client wrapper, and a barrel export file.\n */\nexport async function generate(options?: GenerateOptions): Promise<GenerateResult> {\n const schemaPath = options?.schemaPath ?? DEFAULT_SCHEMA_PATH;\n const outputDir = options?.outputDir ?? DEFAULT_OUTPUT_DIR;\n\n // Read schema\n const schema = await readSchema(schemaPath);\n\n // Ensure output directory exists\n await mkdir(outputDir, { recursive: true });\n\n // Generate files\n const typesContent = emitTypes(schema);\n const clientContent = emitClient(schema);\n const barrelContent = emitBarrel(schema);\n\n // Write files\n const typesPath = join(outputDir, 'types.ts');\n const clientPath = join(outputDir, 'client.ts');\n const barrelPath = join(outputDir, 'index.ts');\n\n await Promise.all([\n writeFile(typesPath, typesContent, 'utf-8'),\n writeFile(clientPath, clientContent, 'utf-8'),\n writeFile(barrelPath, barrelContent, 'utf-8'),\n ]);\n\n // Compute stats\n const recordEntries = Object.entries(schema.records);\n const fieldCount = recordEntries.reduce(\n (sum, [, record]) => sum + Object.keys(record.fields).length,\n 0,\n );\n\n return {\n recordCount: recordEntries.length,\n fieldCount,\n files: [typesPath, clientPath, barrelPath],\n outputDir,\n };\n}\n","import { readFile } from 'node:fs/promises';\nimport type { NormalizedSchema } from '@suiteportal/introspector';\n\n/**\n * Read and parse a schema.json file.\n */\nexport async function readSchema(schemaPath: string): Promise<NormalizedSchema> {\n const raw = await readFile(schemaPath, 'utf-8');\n const schema = JSON.parse(raw) as NormalizedSchema;\n\n if (!schema.records || typeof schema.records !== 'object') {\n throw new Error(`Invalid schema: missing \"records\" in ${schemaPath}`);\n }\n\n return schema;\n}\n","import type { FieldType } from '@suiteportal/introspector';\n\n/**\n * Convert a record ID to PascalCase for use as a TypeScript interface name.\n * Examples:\n * 'customer' → 'Customer'\n * 'salesorder' → 'Salesorder'\n * 'customrecord_mytype' → 'CustomrecordMytype'\n */\nexport function toPascalCase(name: string): string {\n return name\n .split('_')\n .map((part) => (part.length > 0 ? part[0]!.toUpperCase() + part.slice(1).toLowerCase() : ''))\n .join('');\n}\n\n/**\n * Map a normalized FieldType to its TypeScript type representation.\n */\nexport function fieldTypeToTS(fieldType: FieldType): string {\n switch (fieldType) {\n case 'string':\n case 'text':\n case 'richtext':\n case 'email':\n case 'url':\n case 'phone':\n return 'string';\n\n case 'integer':\n case 'float':\n case 'currency':\n case 'percent':\n return 'number';\n\n case 'boolean':\n return 'boolean';\n\n case 'date':\n case 'datetime':\n return 'string'; // SuiteQL returns date strings\n\n case 'select':\n return 'string | number';\n\n case 'multiselect':\n return 'string';\n\n case 'unknown':\n default:\n return 'unknown';\n }\n}\n","import type { NormalizedSchema, RecordDefinition, SublistDefinition } from '@suiteportal/introspector';\nimport { toPascalCase, fieldTypeToTS } from '../naming.js';\n\n/**\n * Emit a TypeScript interface for a single record.\n */\nfunction emitRecordInterface(recordId: string, record: RecordDefinition): string {\n const name = toPascalCase(recordId);\n const fieldEntries = Object.entries(record.fields);\n const fieldCount = fieldEntries.length;\n\n const lines: string[] = [];\n lines.push(`/** ${record.label} — ${fieldCount} fields */`);\n lines.push(`export interface ${name} {`);\n\n for (const [fieldId, field] of fieldEntries) {\n const tsType = fieldTypeToTS(field.type);\n lines.push(` /** ${field.label} */`);\n lines.push(` ${fieldId}?: ${tsType};`);\n }\n\n lines.push('}');\n return lines.join('\\n');\n}\n\n/**\n * Emit a TypeScript interface for a single sublist item.\n */\nfunction emitSublistItem(recordId: string, sublistId: string, sublist: SublistDefinition): string {\n const recordName = toPascalCase(recordId);\n const sublistName = toPascalCase(sublistId);\n const interfaceName = `${recordName}${sublistName}Item`;\n const fieldEntries = Object.entries(sublist.fields);\n\n const lines: string[] = [];\n lines.push(`/** ${sublist.label} line item on ${recordName}. */`);\n lines.push(`export interface ${interfaceName} {`);\n\n for (const [fieldId, field] of fieldEntries) {\n const tsType = fieldTypeToTS(field.type);\n lines.push(` /** ${field.label} */`);\n lines.push(` ${fieldId}?: ${tsType};`);\n }\n\n lines.push('}');\n return lines.join('\\n');\n}\n\n/**\n * Emit a CreateInput interface for a record.\n * Excludes readOnly fields and `id`. Required writable fields are non-optional.\n */\nfunction emitCreateInput(recordId: string, record: RecordDefinition): string {\n const name = toPascalCase(recordId);\n const sublistKeys = new Set(Object.keys(record.sublists ?? {}));\n const lines: string[] = [];\n lines.push(`/** Fields for creating a ${record.label}. */`);\n lines.push(`export interface ${name}CreateInput {`);\n\n for (const [fieldId, field] of Object.entries(record.fields)) {\n if (fieldId === 'id' || field.readOnly) continue;\n // Skip fields that collide with sublist names — sublist takes precedence\n if (sublistKeys.has(fieldId)) continue;\n const tsType = fieldTypeToTS(field.type);\n const optional = field.required ? '' : '?';\n lines.push(` /** ${field.label} */`);\n lines.push(` ${fieldId}${optional}: ${tsType};`);\n }\n\n // Sublist fields\n const sublistEntries = Object.entries(record.sublists ?? {});\n for (const [sublistId] of sublistEntries) {\n const itemType = `${name}${toPascalCase(sublistId)}Item`;\n lines.push(` /** ${toPascalCase(sublistId)} sublist. */`);\n lines.push(` ${sublistId}?: { items: ${itemType}[] };`);\n }\n\n lines.push('}');\n return lines.join('\\n');\n}\n\n/**\n * Emit an UpdateInput interface for a record.\n * Excludes readOnly fields and `id`. All fields are optional.\n */\nfunction emitUpdateInput(recordId: string, record: RecordDefinition): string {\n const name = toPascalCase(recordId);\n const sublistKeys = new Set(Object.keys(record.sublists ?? {}));\n const lines: string[] = [];\n lines.push(`/** Fields for updating a ${record.label}. */`);\n lines.push(`export interface ${name}UpdateInput {`);\n\n for (const [fieldId, field] of Object.entries(record.fields)) {\n if (fieldId === 'id' || field.readOnly) continue;\n // Skip fields that collide with sublist names — sublist takes precedence\n if (sublistKeys.has(fieldId)) continue;\n const tsType = fieldTypeToTS(field.type);\n lines.push(` /** ${field.label} */`);\n lines.push(` ${fieldId}?: ${tsType};`);\n }\n\n // Sublist fields\n const sublistEntries = Object.entries(record.sublists ?? {});\n for (const [sublistId] of sublistEntries) {\n const itemType = `${name}${toPascalCase(sublistId)}Item`;\n lines.push(` /** ${toPascalCase(sublistId)} sublist. */`);\n lines.push(` ${sublistId}?: { items: ${itemType}[] };`);\n }\n\n lines.push('}');\n return lines.join('\\n');\n}\n\n/**\n * Emit the full types.ts file content from a schema.\n */\nexport function emitTypes(schema: NormalizedSchema): string {\n const lines: string[] = [\n '// Auto-generated by @suiteportal/generator — DO NOT EDIT',\n `// Generated at: ${new Date().toISOString()}`,\n '',\n ];\n\n const recordEntries = Object.entries(schema.records);\n\n for (const [recordId, record] of recordEntries) {\n lines.push(emitRecordInterface(recordId, record));\n lines.push('');\n\n // Emit sublist item interfaces before Create/UpdateInput (they reference the item types)\n const sublistEntries = Object.entries(record.sublists ?? {});\n for (const [sublistId, sublist] of sublistEntries) {\n lines.push(emitSublistItem(recordId, sublistId, sublist));\n lines.push('');\n }\n\n lines.push(emitCreateInput(recordId, record));\n lines.push('');\n lines.push(emitUpdateInput(recordId, record));\n lines.push('');\n }\n\n // Export a union type of all record names\n if (recordEntries.length > 0) {\n const names = recordEntries.map(([id]) => `'${id}'`);\n lines.push(`/** All available record type IDs. */`);\n lines.push(`export type RecordTypeId = ${names.join(' | ')};`);\n lines.push('');\n\n // Record type map\n lines.push(`/** Map of record type IDs to their TypeScript interfaces. */`);\n lines.push(`export interface RecordTypeMap {`);\n for (const [recordId] of recordEntries) {\n lines.push(` ${recordId}: ${toPascalCase(recordId)};`);\n }\n lines.push('}');\n lines.push('');\n }\n\n return lines.join('\\n');\n}\n","import type { NormalizedSchema } from '@suiteportal/introspector';\nimport { toPascalCase } from '../naming.js';\n\n/**\n * Emit the client.ts file content — a typed wrapper around the base SuitePortalClient.\n */\nexport function emitClient(schema: NormalizedSchema): string {\n const recordEntries = Object.entries(schema.records);\n const typeImports = recordEntries.map(([id]) => toPascalCase(id));\n\n const lines: string[] = [\n '// Auto-generated by suiteportal — DO NOT EDIT',\n `// Generated at: ${new Date().toISOString()}`,\n '',\n `import type { NetSuiteConfig } from 'suiteportal';`,\n `import {`,\n ` SuitePortalClient as BaseClient,`,\n ` getClient as baseGetClient,`,\n ` destroySingleton,`,\n ` type FindManyArgs,`,\n ` type FindFirstArgs,`,\n ` type CountArgs,`,\n ` type CreateArgs,`,\n ` type UpdateArgs,`,\n ` type DeleteArgs,`,\n ` type UpsertArgs,`,\n ` type IncludeInput,`,\n ` type ClientOptions,`,\n `} from 'suiteportal';`,\n ];\n\n if (typeImports.length > 0) {\n const inputImports = recordEntries.flatMap(([id]) => {\n const name = toPascalCase(id);\n return [`${name}CreateInput`, `${name}UpdateInput`];\n });\n lines.push(`import type { ${[...typeImports, ...inputImports].join(', ')} } from './types';`);\n }\n\n lines.push('');\n\n // TypedModelDelegate interface\n lines.push('/** A typed model delegate for a specific record type. */');\n lines.push('export interface TypedModelDelegate<T, TCreate = Record<string, unknown>, TUpdate = Record<string, unknown>> {');\n lines.push(' findMany(args?: FindManyArgs): Promise<T[]>;');\n lines.push(' findFirst(args?: FindFirstArgs): Promise<T | null>;');\n lines.push(' count(args?: CountArgs): Promise<number>;');\n lines.push(' create(args: CreateArgs<TCreate>): Promise<T>;');\n lines.push(' update(args: UpdateArgs<TUpdate>): Promise<T>;');\n lines.push(' delete(args: DeleteArgs): Promise<void>;');\n lines.push(' upsert(args: UpsertArgs<TCreate>): Promise<T>;');\n lines.push('}');\n lines.push('');\n\n // SuitePortalClient interface\n lines.push('/** Typed SuitePortal client with per-record delegates. */');\n lines.push('export interface SuitePortalClient {');\n\n for (const [recordId] of recordEntries) {\n const typeName = toPascalCase(recordId);\n lines.push(` ${recordId}: TypedModelDelegate<${typeName}, ${typeName}CreateInput, ${typeName}UpdateInput>;`);\n }\n\n lines.push(' $queryRaw<T = Record<string, unknown>>(sql: string): Promise<T[]>;');\n lines.push(' $disconnect(): void;');\n lines.push(' $loadSchema(): Promise<void>;');\n lines.push('}');\n lines.push('');\n\n // createClient function\n lines.push('/**');\n lines.push(' * Create a typed SuitePortal client.');\n lines.push(' * Loads schema.json and provides typed access to all record types.');\n lines.push(' */');\n lines.push('export async function createClient(');\n lines.push(' config: NetSuiteConfig,');\n lines.push(' options?: ClientOptions,');\n lines.push('): Promise<SuitePortalClient> {');\n lines.push(' const client = new BaseClient(config, options);');\n lines.push(' await client.$loadSchema();');\n lines.push(' return client as unknown as SuitePortalClient;');\n lines.push('}');\n lines.push('');\n\n // getClient singleton\n lines.push('/**');\n lines.push(' * Get (or create) a process-wide singleton typed client.');\n lines.push(' * Safe for use across server components, server actions, and API routes.');\n lines.push(' */');\n lines.push('export async function getClient(');\n lines.push(' config: NetSuiteConfig,');\n lines.push(' options?: ClientOptions,');\n lines.push('): Promise<SuitePortalClient> {');\n lines.push(' return baseGetClient(config, options) as Promise<unknown> as Promise<SuitePortalClient>;');\n lines.push('}');\n lines.push('');\n\n // Re-export destroySingleton\n lines.push('export { destroySingleton };');\n lines.push('');\n\n // Re-export types for convenience\n lines.push('export type { FindManyArgs, FindFirstArgs, CountArgs, CreateArgs, UpdateArgs, DeleteArgs, UpsertArgs, IncludeInput } from \\'suiteportal\\';');\n lines.push('');\n\n return lines.join('\\n');\n}\n","import type { NormalizedSchema } from '@suiteportal/introspector';\nimport { toPascalCase } from '../naming.js';\n\n/**\n * Emit the index.ts barrel export file content.\n */\nexport function emitBarrel(schema: NormalizedSchema): string {\n const recordEntries = Object.entries(schema.records);\n const typeNames = recordEntries.map(([id]) => toPascalCase(id));\n\n const lines: string[] = [\n '// Auto-generated by @suiteportal/generator — DO NOT EDIT',\n `// Generated at: ${new Date().toISOString()}`,\n '',\n ];\n\n // Type exports\n if (typeNames.length > 0) {\n const inputTypes = recordEntries.flatMap(([id]) => {\n const name = toPascalCase(id);\n return [`${name}CreateInput`, `${name}UpdateInput`];\n });\n lines.push(`export type { ${[...typeNames, ...inputTypes].join(', ')}, RecordTypeId, RecordTypeMap } from './types';`);\n }\n\n // Client exports\n lines.push(`export type { SuitePortalClient, TypedModelDelegate } from './client';`);\n lines.push(`export { createClient } from './client';`);\n lines.push(`export type { FindManyArgs, FindFirstArgs, CountArgs, CreateArgs, UpdateArgs, DeleteArgs, IncludeInput } from './client';`);\n lines.push('');\n\n return lines.join('\\n');\n}\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../src/generate.ts","../src/schema-reader.ts","../src/naming.ts","../src/emitters/type-emitter.ts","../src/emitters/client-emitter.ts","../src/emitters/barrel-emitter.ts"],"sourcesContent":["import { mkdir, writeFile } from 'node:fs/promises';\nimport { join } from 'node:path';\nimport { readSchema } from './schema-reader.js';\nimport { emitTypes } from './emitters/type-emitter.js';\nimport { emitClient } from './emitters/client-emitter.js';\nimport { emitBarrel } from './emitters/barrel-emitter.js';\nimport type { GenerateOptions, GenerateResult } from './types.js';\n\nconst DEFAULT_SCHEMA_PATH = '.suiteportal/schema.json';\nconst DEFAULT_OUTPUT_DIR = '.suiteportal/client';\n\n/**\n * Generate typed client code from a schema.json file.\n *\n * Reads the introspected schema, emits TypeScript interfaces for all records,\n * a typed client wrapper, and a barrel export file.\n */\nexport async function generate(options?: GenerateOptions): Promise<GenerateResult> {\n const schemaPath = options?.schemaPath ?? DEFAULT_SCHEMA_PATH;\n const outputDir = options?.outputDir ?? DEFAULT_OUTPUT_DIR;\n\n // Read schema\n const schema = await readSchema(schemaPath);\n\n // Ensure output directory exists\n await mkdir(outputDir, { recursive: true });\n\n // Generate files\n const typesContent = emitTypes(schema);\n const clientContent = emitClient(schema);\n const barrelContent = emitBarrel(schema);\n\n // Write files\n const typesPath = join(outputDir, 'types.ts');\n const clientPath = join(outputDir, 'client.ts');\n const barrelPath = join(outputDir, 'index.ts');\n\n await Promise.all([\n writeFile(typesPath, typesContent, 'utf-8'),\n writeFile(clientPath, clientContent, 'utf-8'),\n writeFile(barrelPath, barrelContent, 'utf-8'),\n ]);\n\n // Compute stats\n const recordEntries = Object.entries(schema.records);\n const fieldCount = recordEntries.reduce(\n (sum, [, record]) => sum + Object.keys(record.fields).length,\n 0,\n );\n\n return {\n recordCount: recordEntries.length,\n fieldCount,\n files: [typesPath, clientPath, barrelPath],\n outputDir,\n };\n}\n","import { readFile } from 'node:fs/promises';\nimport type { NormalizedSchema } from '@suiteportal/introspector';\n\n/**\n * Read and parse a schema.json file.\n */\nexport async function readSchema(schemaPath: string): Promise<NormalizedSchema> {\n const raw = await readFile(schemaPath, 'utf-8');\n const schema = JSON.parse(raw) as NormalizedSchema;\n\n if (!schema.records || typeof schema.records !== 'object') {\n throw new Error(`Invalid schema: missing \"records\" in ${schemaPath}`);\n }\n\n return schema;\n}\n","import type { FieldType } from '@suiteportal/introspector';\n\n/**\n * Convert a record ID to PascalCase for use as a TypeScript interface name.\n * Examples:\n * 'customer' → 'Customer'\n * 'salesorder' → 'Salesorder'\n * 'customrecord_mytype' → 'CustomrecordMytype'\n */\nexport function toPascalCase(name: string): string {\n return name\n .split('_')\n .map((part) => (part.length > 0 ? part[0]!.toUpperCase() + part.slice(1).toLowerCase() : ''))\n .join('');\n}\n\n/**\n * Map a normalized FieldType to its TypeScript type representation.\n */\nexport function fieldTypeToTS(fieldType: FieldType): string {\n switch (fieldType) {\n case 'string':\n case 'text':\n case 'richtext':\n case 'email':\n case 'url':\n case 'phone':\n return 'string';\n\n case 'integer':\n case 'float':\n case 'currency':\n case 'percent':\n return 'number';\n\n case 'boolean':\n return 'boolean';\n\n case 'date':\n case 'datetime':\n return 'string'; // SuiteQL returns date strings\n\n case 'select':\n return 'string | number';\n\n case 'multiselect':\n return 'string';\n\n case 'unknown':\n default:\n return 'unknown';\n }\n}\n","import type { NormalizedSchema, RecordDefinition, FieldDefinition, SublistDefinition, FieldType } from '@suiteportal/introspector';\nimport { toPascalCase, fieldTypeToTS } from '../naming.js';\n\n/**\n * Map a FieldType to its filter type name and shorthand value type.\n */\nfunction fieldTypeToFilter(fieldType: FieldType): { filterType: string; shorthand: string } {\n switch (fieldType) {\n case 'string':\n case 'text':\n case 'richtext':\n case 'email':\n case 'url':\n case 'phone':\n case 'date':\n case 'datetime':\n case 'multiselect':\n return { filterType: 'StringFilter', shorthand: 'string' };\n\n case 'integer':\n case 'float':\n case 'currency':\n case 'percent':\n return { filterType: 'NumberFilter', shorthand: 'number' };\n\n case 'boolean':\n return { filterType: 'BooleanFilter', shorthand: 'boolean' };\n\n case 'select':\n return { filterType: 'SelectFilter', shorthand: 'string | number' };\n\n case 'unknown':\n default:\n return { filterType: 'StringFilter', shorthand: 'unknown' };\n }\n}\n\n/**\n * Emit shared filter type interfaces used by all per-record WhereInput types.\n */\nfunction emitFilterTypes(): string {\n return `/** String field filter operators. */\nexport interface StringFilter {\n equals?: string | null;\n not?: string | null;\n in?: string[];\n notIn?: string[];\n gt?: string;\n gte?: string;\n lt?: string;\n lte?: string;\n contains?: string;\n startsWith?: string;\n endsWith?: string;\n isNull?: boolean;\n}\n\n/** Number field filter operators. */\nexport interface NumberFilter {\n equals?: number | null;\n not?: number | null;\n in?: number[];\n notIn?: number[];\n gt?: number;\n gte?: number;\n lt?: number;\n lte?: number;\n isNull?: boolean;\n}\n\n/** Boolean field filter operators. */\nexport interface BooleanFilter {\n equals?: boolean | null;\n not?: boolean | null;\n isNull?: boolean;\n}\n\n/** Select (string | number) field filter operators. */\nexport interface SelectFilter {\n equals?: string | number | null;\n not?: string | number | null;\n in?: (string | number)[];\n notIn?: (string | number)[];\n gt?: string | number;\n gte?: string | number;\n lt?: string | number;\n lte?: string | number;\n isNull?: boolean;\n}`;\n}\n\n/**\n * Emit a per-record WhereInput type with typed fields.\n */\nfunction emitWhereInput(recordId: string, record: RecordDefinition): string {\n const name = toPascalCase(recordId);\n const lines: string[] = [];\n lines.push(`/** Where clause for ${record.label} queries. */`);\n lines.push(`export interface ${name}WhereInput {`);\n\n for (const [fieldId, field] of Object.entries(record.fields)) {\n const { filterType, shorthand } = fieldTypeToFilter(field.type);\n lines.push(` /** ${field.label} */`);\n lines.push(` ${fieldId}?: ${shorthand} | ${filterType};`);\n }\n\n lines.push(` AND?: ${name}WhereInput[];`);\n lines.push(` OR?: ${name}WhereInput[];`);\n lines.push(` NOT?: ${name}WhereInput;`);\n lines.push('}');\n return lines.join('\\n');\n}\n\n/**\n * Emit a per-record Select type.\n */\nfunction emitSelectType(recordId: string, record: RecordDefinition): string {\n const name = toPascalCase(recordId);\n const lines: string[] = [];\n lines.push(`/** Field selection for ${record.label} queries. */`);\n lines.push(`export interface ${name}Select {`);\n\n for (const [fieldId, field] of Object.entries(record.fields)) {\n lines.push(` /** ${field.label} */`);\n lines.push(` ${fieldId}?: boolean;`);\n }\n\n lines.push('}');\n return lines.join('\\n');\n}\n\n/**\n * Emit a per-record OrderByInput type.\n */\nfunction emitOrderByType(recordId: string, record: RecordDefinition): string {\n const name = toPascalCase(recordId);\n const lines: string[] = [];\n lines.push(`/** Order by clause for ${record.label} queries. */`);\n lines.push(`export interface ${name}OrderByInput {`);\n\n for (const [fieldId, field] of Object.entries(record.fields)) {\n lines.push(` /** ${field.label} */`);\n lines.push(` ${fieldId}?: 'asc' | 'desc';`);\n }\n\n lines.push('}');\n return lines.join('\\n');\n}\n\n/**\n * Emit a TypeScript interface for a single record.\n */\nfunction emitRecordInterface(recordId: string, record: RecordDefinition): string {\n const name = toPascalCase(recordId);\n const fieldEntries = Object.entries(record.fields);\n const fieldCount = fieldEntries.length;\n\n const lines: string[] = [];\n lines.push(`/** ${record.label} — ${fieldCount} fields */`);\n lines.push(`export interface ${name} {`);\n\n for (const [fieldId, field] of fieldEntries) {\n const tsType = fieldTypeToTS(field.type);\n lines.push(` /** ${field.label} */`);\n lines.push(` ${fieldId}?: ${tsType};`);\n }\n\n lines.push('}');\n return lines.join('\\n');\n}\n\n/**\n * Emit a TypeScript interface for a single sublist item.\n */\nfunction emitSublistItem(recordId: string, sublistId: string, sublist: SublistDefinition): string {\n const recordName = toPascalCase(recordId);\n const sublistName = toPascalCase(sublistId);\n const interfaceName = `${recordName}${sublistName}Item`;\n const fieldEntries = Object.entries(sublist.fields);\n\n const lines: string[] = [];\n lines.push(`/** ${sublist.label} line item on ${recordName}. */`);\n lines.push(`export interface ${interfaceName} {`);\n\n for (const [fieldId, field] of fieldEntries) {\n const tsType = fieldTypeToTS(field.type);\n lines.push(` /** ${field.label} */`);\n lines.push(` ${fieldId}?: ${tsType};`);\n }\n\n lines.push('}');\n return lines.join('\\n');\n}\n\n/**\n * Emit a CreateInput interface for a record.\n * Excludes readOnly fields and `id`. Required writable fields are non-optional.\n */\nfunction emitCreateInput(recordId: string, record: RecordDefinition): string {\n const name = toPascalCase(recordId);\n const sublistKeys = new Set(Object.keys(record.sublists ?? {}));\n const lines: string[] = [];\n lines.push(`/** Fields for creating a ${record.label}. */`);\n lines.push(`export interface ${name}CreateInput {`);\n\n for (const [fieldId, field] of Object.entries(record.fields)) {\n if (fieldId === 'id' || field.readOnly) continue;\n // Skip fields that collide with sublist names — sublist takes precedence\n if (sublistKeys.has(fieldId)) continue;\n const tsType = fieldTypeToTS(field.type);\n const optional = field.required ? '' : '?';\n lines.push(` /** ${field.label} */`);\n lines.push(` ${fieldId}${optional}: ${tsType};`);\n }\n\n // Sublist fields\n const sublistEntries = Object.entries(record.sublists ?? {});\n for (const [sublistId] of sublistEntries) {\n const itemType = `${name}${toPascalCase(sublistId)}Item`;\n lines.push(` /** ${toPascalCase(sublistId)} sublist. */`);\n lines.push(` ${sublistId}?: { items: ${itemType}[] };`);\n }\n\n lines.push('}');\n return lines.join('\\n');\n}\n\n/**\n * Emit an UpdateInput interface for a record.\n * Excludes readOnly fields and `id`. All fields are optional.\n */\nfunction emitUpdateInput(recordId: string, record: RecordDefinition): string {\n const name = toPascalCase(recordId);\n const sublistKeys = new Set(Object.keys(record.sublists ?? {}));\n const lines: string[] = [];\n lines.push(`/** Fields for updating a ${record.label}. */`);\n lines.push(`export interface ${name}UpdateInput {`);\n\n for (const [fieldId, field] of Object.entries(record.fields)) {\n if (fieldId === 'id' || field.readOnly) continue;\n // Skip fields that collide with sublist names — sublist takes precedence\n if (sublistKeys.has(fieldId)) continue;\n const tsType = fieldTypeToTS(field.type);\n lines.push(` /** ${field.label} */`);\n lines.push(` ${fieldId}?: ${tsType};`);\n }\n\n // Sublist fields\n const sublistEntries = Object.entries(record.sublists ?? {});\n for (const [sublistId] of sublistEntries) {\n const itemType = `${name}${toPascalCase(sublistId)}Item`;\n lines.push(` /** ${toPascalCase(sublistId)} sublist. */`);\n lines.push(` ${sublistId}?: { items: ${itemType}[] };`);\n }\n\n lines.push('}');\n return lines.join('\\n');\n}\n\n/**\n * Emit the full types.ts file content from a schema.\n */\nexport function emitTypes(schema: NormalizedSchema): string {\n const lines: string[] = [\n '// Auto-generated by @suiteportal/generator — DO NOT EDIT',\n `// Generated at: ${new Date().toISOString()}`,\n '',\n ];\n\n const recordEntries = Object.entries(schema.records);\n\n // Emit shared filter types first (used by all WhereInput types)\n if (recordEntries.length > 0) {\n lines.push(emitFilterTypes());\n lines.push('');\n }\n\n for (const [recordId, record] of recordEntries) {\n lines.push(emitRecordInterface(recordId, record));\n lines.push('');\n\n // Emit sublist item interfaces before Create/UpdateInput (they reference the item types)\n const sublistEntries = Object.entries(record.sublists ?? {});\n for (const [sublistId, sublist] of sublistEntries) {\n lines.push(emitSublistItem(recordId, sublistId, sublist));\n lines.push('');\n }\n\n lines.push(emitCreateInput(recordId, record));\n lines.push('');\n lines.push(emitUpdateInput(recordId, record));\n lines.push('');\n\n // Emit per-record query types (WhereInput, Select, OrderByInput)\n lines.push(emitWhereInput(recordId, record));\n lines.push('');\n lines.push(emitSelectType(recordId, record));\n lines.push('');\n lines.push(emitOrderByType(recordId, record));\n lines.push('');\n }\n\n // Export a union type of all record names\n if (recordEntries.length > 0) {\n const names = recordEntries.map(([id]) => `'${id}'`);\n lines.push(`/** All available record type IDs. */`);\n lines.push(`export type RecordTypeId = ${names.join(' | ')};`);\n lines.push('');\n\n // Record type map\n lines.push(`/** Map of record type IDs to their TypeScript interfaces. */`);\n lines.push(`export interface RecordTypeMap {`);\n for (const [recordId] of recordEntries) {\n lines.push(` ${recordId}: ${toPascalCase(recordId)};`);\n }\n lines.push('}');\n lines.push('');\n }\n\n return lines.join('\\n');\n}\n","import type { NormalizedSchema } from '@suiteportal/introspector';\nimport { toPascalCase } from '../naming.js';\n\n/**\n * Emit a per-record delegate interface with fully typed query args.\n */\nfunction emitDelegate(recordId: string): string {\n const name = toPascalCase(recordId);\n const lines: string[] = [];\n lines.push(`/** Typed delegate for ${name} records. */`);\n lines.push(`export interface ${name}Delegate {`);\n lines.push(` findMany(args?: { where?: ${name}WhereInput; select?: ${name}Select; orderBy?: ${name}OrderByInput; include?: IncludeInput; take?: number; skip?: number }): Promise<${name}[]>;`);\n lines.push(` findFirst(args?: { where?: ${name}WhereInput; select?: ${name}Select; orderBy?: ${name}OrderByInput; include?: IncludeInput; skip?: number }): Promise<${name} | null>;`);\n lines.push(` count(args?: { where?: ${name}WhereInput }): Promise<number>;`);\n lines.push(` create(args: { data: ${name}CreateInput }): Promise<${name}>;`);\n lines.push(` update(args: { where: { id: { equals: string | number } }; data: ${name}UpdateInput }): Promise<${name}>;`);\n lines.push(` delete(args: { where: { id: { equals: string | number } } }): Promise<void>;`);\n lines.push(` upsert(args: { where: { externalId: string }; data: ${name}CreateInput }): Promise<${name}>;`);\n lines.push('}');\n return lines.join('\\n');\n}\n\n/**\n * Emit the client.ts file content — a typed wrapper around the base SuitePortalClient.\n */\nexport function emitClient(schema: NormalizedSchema): string {\n const recordEntries = Object.entries(schema.records);\n const typeImports = recordEntries.map(([id]) => toPascalCase(id));\n\n const lines: string[] = [\n '// Auto-generated by suiteportal — DO NOT EDIT',\n `// Generated at: ${new Date().toISOString()}`,\n '',\n `import type { NetSuiteConfig } from 'suiteportal';`,\n `import {`,\n ` SuitePortalClient as BaseClient,`,\n ` getClient as baseGetClient,`,\n ` destroySingleton,`,\n ` type IncludeInput,`,\n ` type ClientOptions,`,\n `} from 'suiteportal';`,\n ];\n\n if (typeImports.length > 0) {\n const perRecordImports = recordEntries.flatMap(([id]) => {\n const name = toPascalCase(id);\n return [\n name,\n `${name}CreateInput`,\n `${name}UpdateInput`,\n `${name}WhereInput`,\n `${name}Select`,\n `${name}OrderByInput`,\n ];\n });\n lines.push(`import type { ${perRecordImports.join(', ')} } from './types';`);\n }\n\n lines.push('');\n\n // Per-record delegate interfaces\n for (const [recordId] of recordEntries) {\n lines.push(emitDelegate(recordId));\n lines.push('');\n }\n\n // SuitePortalClient interface\n lines.push('/** Typed SuitePortal client with per-record delegates. */');\n lines.push('export interface SuitePortalClient {');\n\n for (const [recordId] of recordEntries) {\n const typeName = toPascalCase(recordId);\n lines.push(` ${recordId}: ${typeName}Delegate;`);\n }\n\n lines.push(' $queryRaw<T = Record<string, unknown>>(sql: string): Promise<T[]>;');\n lines.push(' $disconnect(): void;');\n lines.push(' $loadSchema(): Promise<void>;');\n lines.push('}');\n lines.push('');\n\n // createClient function\n lines.push('/**');\n lines.push(' * Create a typed SuitePortal client.');\n lines.push(' * Loads schema.json and provides typed access to all record types.');\n lines.push(' */');\n lines.push('export async function createClient(');\n lines.push(' config: NetSuiteConfig,');\n lines.push(' options?: ClientOptions,');\n lines.push('): Promise<SuitePortalClient> {');\n lines.push(' const client = new BaseClient(config, options);');\n lines.push(' await client.$loadSchema();');\n lines.push(' return client as unknown as SuitePortalClient;');\n lines.push('}');\n lines.push('');\n\n // getClient singleton\n lines.push('/**');\n lines.push(' * Get (or create) a process-wide singleton typed client.');\n lines.push(' * Safe for use across server components, server actions, and API routes.');\n lines.push(' */');\n lines.push('export async function getClient(');\n lines.push(' config: NetSuiteConfig,');\n lines.push(' options?: ClientOptions,');\n lines.push('): Promise<SuitePortalClient> {');\n lines.push(' return baseGetClient(config, options) as Promise<unknown> as Promise<SuitePortalClient>;');\n lines.push('}');\n lines.push('');\n\n // Re-export destroySingleton\n lines.push('export { destroySingleton };');\n lines.push('');\n\n // Re-export types for convenience\n lines.push('export type { IncludeInput } from \\'suiteportal\\';');\n lines.push('');\n\n return lines.join('\\n');\n}\n","import type { NormalizedSchema } from '@suiteportal/introspector';\nimport { toPascalCase } from '../naming.js';\n\n/**\n * Emit the index.ts barrel export file content.\n */\nexport function emitBarrel(schema: NormalizedSchema): string {\n const recordEntries = Object.entries(schema.records);\n const typeNames = recordEntries.map(([id]) => toPascalCase(id));\n\n const lines: string[] = [\n '// Auto-generated by @suiteportal/generator — DO NOT EDIT',\n `// Generated at: ${new Date().toISOString()}`,\n '',\n ];\n\n // Type exports\n if (typeNames.length > 0) {\n const perRecordTypes = recordEntries.flatMap(([id]) => {\n const name = toPascalCase(id);\n return [\n `${name}CreateInput`,\n `${name}UpdateInput`,\n `${name}WhereInput`,\n `${name}Select`,\n `${name}OrderByInput`,\n ];\n });\n lines.push(`export type { ${[...typeNames, ...perRecordTypes].join(', ')}, RecordTypeId, RecordTypeMap } from './types';`);\n lines.push(`export type { StringFilter, NumberFilter, BooleanFilter, SelectFilter } from './types';`);\n }\n\n // Client exports\n const delegateTypes = recordEntries.map(([id]) => `${toPascalCase(id)}Delegate`);\n lines.push(`export type { SuitePortalClient${delegateTypes.length > 0 ? ', ' + delegateTypes.join(', ') : ''} } from './client';`);\n lines.push(`export { createClient } from './client';`);\n lines.push(`export type { IncludeInput } from './client';`);\n lines.push('');\n\n return lines.join('\\n');\n}\n"],"mappings":"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","names":[]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@suiteportal/generator",
3
- "version": "0.3.0",
3
+ "version": "0.5.0",
4
4
  "description": "Code generator for SuitePortal NetSuite ORM — emits typed queries, mutations, and includes from schema",
5
5
  "type": "module",
6
6
  "main": "./dist/index.cjs",
@@ -21,7 +21,7 @@
21
21
  "clean": "rm -rf dist"
22
22
  },
23
23
  "dependencies": {
24
- "@suiteportal/introspector": "^0.2.0"
24
+ "@suiteportal/introspector": "^0.5.0"
25
25
  },
26
26
  "license": "MIT",
27
27
  "author": "Trey Hulse",