@suiteportal/generator 0.2.1 → 0.2.3
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 +36 -1
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +36 -1
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
package/dist/index.cjs
CHANGED
|
@@ -95,6 +95,22 @@ function emitRecordInterface(recordId, record) {
|
|
|
95
95
|
lines.push("}");
|
|
96
96
|
return lines.join("\n");
|
|
97
97
|
}
|
|
98
|
+
function emitSublistItem(recordId, sublistId, sublist) {
|
|
99
|
+
const recordName = toPascalCase(recordId);
|
|
100
|
+
const sublistName = toPascalCase(sublistId);
|
|
101
|
+
const interfaceName = `${recordName}${sublistName}Item`;
|
|
102
|
+
const fieldEntries = Object.entries(sublist.fields);
|
|
103
|
+
const lines = [];
|
|
104
|
+
lines.push(`/** ${sublist.label} line item on ${recordName}. */`);
|
|
105
|
+
lines.push(`export interface ${interfaceName} {`);
|
|
106
|
+
for (const [fieldId, field] of fieldEntries) {
|
|
107
|
+
const tsType = fieldTypeToTS(field.type);
|
|
108
|
+
lines.push(` /** ${field.label} */`);
|
|
109
|
+
lines.push(` ${fieldId}?: ${tsType};`);
|
|
110
|
+
}
|
|
111
|
+
lines.push("}");
|
|
112
|
+
return lines.join("\n");
|
|
113
|
+
}
|
|
98
114
|
function emitCreateInput(recordId, record) {
|
|
99
115
|
const name = toPascalCase(recordId);
|
|
100
116
|
const lines = [];
|
|
@@ -107,6 +123,12 @@ function emitCreateInput(recordId, record) {
|
|
|
107
123
|
lines.push(` /** ${field.label} */`);
|
|
108
124
|
lines.push(` ${fieldId}${optional}: ${tsType};`);
|
|
109
125
|
}
|
|
126
|
+
const sublistEntries = Object.entries(record.sublists ?? {});
|
|
127
|
+
for (const [sublistId] of sublistEntries) {
|
|
128
|
+
const itemType = `${name}${toPascalCase(sublistId)}Item`;
|
|
129
|
+
lines.push(` /** ${toPascalCase(sublistId)} sublist. */`);
|
|
130
|
+
lines.push(` ${sublistId}?: { items: ${itemType}[] };`);
|
|
131
|
+
}
|
|
110
132
|
lines.push("}");
|
|
111
133
|
return lines.join("\n");
|
|
112
134
|
}
|
|
@@ -121,6 +143,12 @@ function emitUpdateInput(recordId, record) {
|
|
|
121
143
|
lines.push(` /** ${field.label} */`);
|
|
122
144
|
lines.push(` ${fieldId}?: ${tsType};`);
|
|
123
145
|
}
|
|
146
|
+
const sublistEntries = Object.entries(record.sublists ?? {});
|
|
147
|
+
for (const [sublistId] of sublistEntries) {
|
|
148
|
+
const itemType = `${name}${toPascalCase(sublistId)}Item`;
|
|
149
|
+
lines.push(` /** ${toPascalCase(sublistId)} sublist. */`);
|
|
150
|
+
lines.push(` ${sublistId}?: { items: ${itemType}[] };`);
|
|
151
|
+
}
|
|
124
152
|
lines.push("}");
|
|
125
153
|
return lines.join("\n");
|
|
126
154
|
}
|
|
@@ -134,6 +162,11 @@ function emitTypes(schema) {
|
|
|
134
162
|
for (const [recordId, record] of recordEntries) {
|
|
135
163
|
lines.push(emitRecordInterface(recordId, record));
|
|
136
164
|
lines.push("");
|
|
165
|
+
const sublistEntries = Object.entries(record.sublists ?? {});
|
|
166
|
+
for (const [sublistId, sublist] of sublistEntries) {
|
|
167
|
+
lines.push(emitSublistItem(recordId, sublistId, sublist));
|
|
168
|
+
lines.push("");
|
|
169
|
+
}
|
|
137
170
|
lines.push(emitCreateInput(recordId, record));
|
|
138
171
|
lines.push("");
|
|
139
172
|
lines.push(emitUpdateInput(recordId, record));
|
|
@@ -172,6 +205,7 @@ function emitClient(schema) {
|
|
|
172
205
|
` type CreateArgs,`,
|
|
173
206
|
` type UpdateArgs,`,
|
|
174
207
|
` type DeleteArgs,`,
|
|
208
|
+
` type UpsertArgs,`,
|
|
175
209
|
` type IncludeInput,`,
|
|
176
210
|
` type ClientOptions,`,
|
|
177
211
|
`} from '@suiteportal/client-runtime';`
|
|
@@ -192,6 +226,7 @@ function emitClient(schema) {
|
|
|
192
226
|
lines.push(" create(args: CreateArgs<TCreate>): Promise<T>;");
|
|
193
227
|
lines.push(" update(args: UpdateArgs<TUpdate>): Promise<T>;");
|
|
194
228
|
lines.push(" delete(args: DeleteArgs): Promise<void>;");
|
|
229
|
+
lines.push(" upsert(args: UpsertArgs<TCreate>): Promise<T>;");
|
|
195
230
|
lines.push("}");
|
|
196
231
|
lines.push("");
|
|
197
232
|
lines.push("/** Typed SuitePortal client with per-record delegates. */");
|
|
@@ -218,7 +253,7 @@ function emitClient(schema) {
|
|
|
218
253
|
lines.push(" return client as unknown as SuitePortalClient;");
|
|
219
254
|
lines.push("}");
|
|
220
255
|
lines.push("");
|
|
221
|
-
lines.push("export type { FindManyArgs, FindFirstArgs, CountArgs, CreateArgs, UpdateArgs, DeleteArgs, IncludeInput } from '@suiteportal/client-runtime';");
|
|
256
|
+
lines.push("export type { FindManyArgs, FindFirstArgs, CountArgs, CreateArgs, UpdateArgs, DeleteArgs, UpsertArgs, IncludeInput } from '@suiteportal/client-runtime';");
|
|
222
257
|
lines.push("");
|
|
223
258
|
return lines.join("\n");
|
|
224
259
|
}
|
package/dist/index.cjs.map
CHANGED
|
@@ -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 } 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 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 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 const tsType = fieldTypeToTS(field.type);\n const optional = field.required ? '' : '?';\n lines.push(` /** ${field.label} */`);\n lines.push(` ${fieldId}${optional}: ${tsType};`);\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 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 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 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 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/generator — DO NOT EDIT',\n `// Generated at: ${new Date().toISOString()}`,\n '',\n `import type { NetSuiteConfig } from '@suiteportal/connector';`,\n `import {`,\n ` SuitePortalClient as BaseClient,`,\n ` type FindManyArgs,`,\n ` type FindFirstArgs,`,\n ` type CountArgs,`,\n ` type CreateArgs,`,\n ` type UpdateArgs,`,\n ` type DeleteArgs,`,\n ` type IncludeInput,`,\n ` type ClientOptions,`,\n `} from '@suiteportal/client-runtime';`,\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('}');\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 // Re-export types for convenience\n lines.push('export type { FindManyArgs, FindFirstArgs, CountArgs, CreateArgs, UpdateArgs, DeleteArgs, IncludeInput } from \\'@suiteportal/client-runtime\\';');\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, 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 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 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 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 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/generator — DO NOT EDIT',\n `// Generated at: ${new Date().toISOString()}`,\n '',\n `import type { NetSuiteConfig } from '@suiteportal/connector';`,\n `import {`,\n ` SuitePortalClient as BaseClient,`,\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/client-runtime';`,\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 // Re-export types for convenience\n lines.push('export type { FindManyArgs, FindFirstArgs, CountArgs, CreateArgs, UpdateArgs, DeleteArgs, UpsertArgs, IncludeInput } from \\'@suiteportal/client-runtime\\';');\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"]}
|
package/dist/index.js
CHANGED
|
@@ -63,6 +63,22 @@ function emitRecordInterface(recordId, record) {
|
|
|
63
63
|
lines.push("}");
|
|
64
64
|
return lines.join("\n");
|
|
65
65
|
}
|
|
66
|
+
function emitSublistItem(recordId, sublistId, sublist) {
|
|
67
|
+
const recordName = toPascalCase(recordId);
|
|
68
|
+
const sublistName = toPascalCase(sublistId);
|
|
69
|
+
const interfaceName = `${recordName}${sublistName}Item`;
|
|
70
|
+
const fieldEntries = Object.entries(sublist.fields);
|
|
71
|
+
const lines = [];
|
|
72
|
+
lines.push(`/** ${sublist.label} line item on ${recordName}. */`);
|
|
73
|
+
lines.push(`export interface ${interfaceName} {`);
|
|
74
|
+
for (const [fieldId, field] of fieldEntries) {
|
|
75
|
+
const tsType = fieldTypeToTS(field.type);
|
|
76
|
+
lines.push(` /** ${field.label} */`);
|
|
77
|
+
lines.push(` ${fieldId}?: ${tsType};`);
|
|
78
|
+
}
|
|
79
|
+
lines.push("}");
|
|
80
|
+
return lines.join("\n");
|
|
81
|
+
}
|
|
66
82
|
function emitCreateInput(recordId, record) {
|
|
67
83
|
const name = toPascalCase(recordId);
|
|
68
84
|
const lines = [];
|
|
@@ -75,6 +91,12 @@ function emitCreateInput(recordId, record) {
|
|
|
75
91
|
lines.push(` /** ${field.label} */`);
|
|
76
92
|
lines.push(` ${fieldId}${optional}: ${tsType};`);
|
|
77
93
|
}
|
|
94
|
+
const sublistEntries = Object.entries(record.sublists ?? {});
|
|
95
|
+
for (const [sublistId] of sublistEntries) {
|
|
96
|
+
const itemType = `${name}${toPascalCase(sublistId)}Item`;
|
|
97
|
+
lines.push(` /** ${toPascalCase(sublistId)} sublist. */`);
|
|
98
|
+
lines.push(` ${sublistId}?: { items: ${itemType}[] };`);
|
|
99
|
+
}
|
|
78
100
|
lines.push("}");
|
|
79
101
|
return lines.join("\n");
|
|
80
102
|
}
|
|
@@ -89,6 +111,12 @@ function emitUpdateInput(recordId, record) {
|
|
|
89
111
|
lines.push(` /** ${field.label} */`);
|
|
90
112
|
lines.push(` ${fieldId}?: ${tsType};`);
|
|
91
113
|
}
|
|
114
|
+
const sublistEntries = Object.entries(record.sublists ?? {});
|
|
115
|
+
for (const [sublistId] of sublistEntries) {
|
|
116
|
+
const itemType = `${name}${toPascalCase(sublistId)}Item`;
|
|
117
|
+
lines.push(` /** ${toPascalCase(sublistId)} sublist. */`);
|
|
118
|
+
lines.push(` ${sublistId}?: { items: ${itemType}[] };`);
|
|
119
|
+
}
|
|
92
120
|
lines.push("}");
|
|
93
121
|
return lines.join("\n");
|
|
94
122
|
}
|
|
@@ -102,6 +130,11 @@ function emitTypes(schema) {
|
|
|
102
130
|
for (const [recordId, record] of recordEntries) {
|
|
103
131
|
lines.push(emitRecordInterface(recordId, record));
|
|
104
132
|
lines.push("");
|
|
133
|
+
const sublistEntries = Object.entries(record.sublists ?? {});
|
|
134
|
+
for (const [sublistId, sublist] of sublistEntries) {
|
|
135
|
+
lines.push(emitSublistItem(recordId, sublistId, sublist));
|
|
136
|
+
lines.push("");
|
|
137
|
+
}
|
|
105
138
|
lines.push(emitCreateInput(recordId, record));
|
|
106
139
|
lines.push("");
|
|
107
140
|
lines.push(emitUpdateInput(recordId, record));
|
|
@@ -140,6 +173,7 @@ function emitClient(schema) {
|
|
|
140
173
|
` type CreateArgs,`,
|
|
141
174
|
` type UpdateArgs,`,
|
|
142
175
|
` type DeleteArgs,`,
|
|
176
|
+
` type UpsertArgs,`,
|
|
143
177
|
` type IncludeInput,`,
|
|
144
178
|
` type ClientOptions,`,
|
|
145
179
|
`} from '@suiteportal/client-runtime';`
|
|
@@ -160,6 +194,7 @@ function emitClient(schema) {
|
|
|
160
194
|
lines.push(" create(args: CreateArgs<TCreate>): Promise<T>;");
|
|
161
195
|
lines.push(" update(args: UpdateArgs<TUpdate>): Promise<T>;");
|
|
162
196
|
lines.push(" delete(args: DeleteArgs): Promise<void>;");
|
|
197
|
+
lines.push(" upsert(args: UpsertArgs<TCreate>): Promise<T>;");
|
|
163
198
|
lines.push("}");
|
|
164
199
|
lines.push("");
|
|
165
200
|
lines.push("/** Typed SuitePortal client with per-record delegates. */");
|
|
@@ -186,7 +221,7 @@ function emitClient(schema) {
|
|
|
186
221
|
lines.push(" return client as unknown as SuitePortalClient;");
|
|
187
222
|
lines.push("}");
|
|
188
223
|
lines.push("");
|
|
189
|
-
lines.push("export type { FindManyArgs, FindFirstArgs, CountArgs, CreateArgs, UpdateArgs, DeleteArgs, IncludeInput } from '@suiteportal/client-runtime';");
|
|
224
|
+
lines.push("export type { FindManyArgs, FindFirstArgs, CountArgs, CreateArgs, UpdateArgs, DeleteArgs, UpsertArgs, IncludeInput } from '@suiteportal/client-runtime';");
|
|
190
225
|
lines.push("");
|
|
191
226
|
return lines.join("\n");
|
|
192
227
|
}
|
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 } 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 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 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 const tsType = fieldTypeToTS(field.type);\n const optional = field.required ? '' : '?';\n lines.push(` /** ${field.label} */`);\n lines.push(` ${fieldId}${optional}: ${tsType};`);\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 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 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 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 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/generator — DO NOT EDIT',\n `// Generated at: ${new Date().toISOString()}`,\n '',\n `import type { NetSuiteConfig } from '@suiteportal/connector';`,\n `import {`,\n ` SuitePortalClient as BaseClient,`,\n ` type FindManyArgs,`,\n ` type FindFirstArgs,`,\n ` type CountArgs,`,\n ` type CreateArgs,`,\n ` type UpdateArgs,`,\n ` type DeleteArgs,`,\n ` type IncludeInput,`,\n ` type ClientOptions,`,\n `} from '@suiteportal/client-runtime';`,\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('}');\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 // Re-export types for convenience\n lines.push('export type { FindManyArgs, FindFirstArgs, CountArgs, CreateArgs, UpdateArgs, DeleteArgs, IncludeInput } from \\'@suiteportal/client-runtime\\';');\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":";AAAA,SAAS,OAAO,iBAAiB;AACjC,SAAS,YAAY;;;ACDrB,SAAS,gBAAgB;AAMzB,eAAsB,WAAW,YAA+C;AAC9E,QAAM,MAAM,MAAM,SAAS,YAAY,OAAO;AAC9C,QAAM,SAAS,KAAK,MAAM,GAAG;AAE7B,MAAI,CAAC,OAAO,WAAW,OAAO,OAAO,YAAY,UAAU;AACzD,UAAM,IAAI,MAAM,wCAAwC,UAAU,EAAE;AAAA,EACtE;AAEA,SAAO;AACT;;;ACNO,SAAS,aAAa,MAAsB;AACjD,SAAO,KACJ,MAAM,GAAG,EACT,IAAI,CAAC,SAAU,KAAK,SAAS,IAAI,KAAK,CAAC,EAAG,YAAY,IAAI,KAAK,MAAM,CAAC,EAAE,YAAY,IAAI,EAAG,EAC3F,KAAK,EAAE;AACZ;AAKO,SAAS,cAAc,WAA8B;AAC1D,UAAQ,WAAW;AAAA,IACjB,KAAK;AAAA,IACL,KAAK;AAAA,IACL,KAAK;AAAA,IACL,KAAK;AAAA,IACL,KAAK;AAAA,IACL,KAAK;AACH,aAAO;AAAA,IAET,KAAK;AAAA,IACL,KAAK;AAAA,IACL,KAAK;AAAA,IACL,KAAK;AACH,aAAO;AAAA,IAET,KAAK;AACH,aAAO;AAAA,IAET,KAAK;AAAA,IACL,KAAK;AACH,aAAO;AAAA;AAAA,IAET,KAAK;AACH,aAAO;AAAA,IAET,KAAK;AACH,aAAO;AAAA,IAET,KAAK;AAAA,IACL;AACE,aAAO;AAAA,EACX;AACF;;;AC9CA,SAAS,oBAAoB,UAAkB,QAAkC;AAC/E,QAAM,OAAO,aAAa,QAAQ;AAClC,QAAM,eAAe,OAAO,QAAQ,OAAO,MAAM;AACjD,QAAM,aAAa,aAAa;AAEhC,QAAM,QAAkB,CAAC;AACzB,QAAM,KAAK,OAAO,OAAO,KAAK,WAAM,UAAU,YAAY;AAC1D,QAAM,KAAK,oBAAoB,IAAI,IAAI;AAEvC,aAAW,CAAC,SAAS,KAAK,KAAK,cAAc;AAC3C,UAAM,SAAS,cAAc,MAAM,IAAI;AACvC,UAAM,KAAK,SAAS,MAAM,KAAK,KAAK;AACpC,UAAM,KAAK,KAAK,OAAO,MAAM,MAAM,GAAG;AAAA,EACxC;AAEA,QAAM,KAAK,GAAG;AACd,SAAO,MAAM,KAAK,IAAI;AACxB;AAMA,SAAS,gBAAgB,UAAkB,QAAkC;AAC3E,QAAM,OAAO,aAAa,QAAQ;AAClC,QAAM,QAAkB,CAAC;AACzB,QAAM,KAAK,6BAA6B,OAAO,KAAK,MAAM;AAC1D,QAAM,KAAK,oBAAoB,IAAI,eAAe;AAElD,aAAW,CAAC,SAAS,KAAK,KAAK,OAAO,QAAQ,OAAO,MAAM,GAAG;AAC5D,QAAI,YAAY,QAAQ,MAAM,SAAU;AACxC,UAAM,SAAS,cAAc,MAAM,IAAI;AACvC,UAAM,WAAW,MAAM,WAAW,KAAK;AACvC,UAAM,KAAK,SAAS,MAAM,KAAK,KAAK;AACpC,UAAM,KAAK,KAAK,OAAO,GAAG,QAAQ,KAAK,MAAM,GAAG;AAAA,EAClD;AAEA,QAAM,KAAK,GAAG;AACd,SAAO,MAAM,KAAK,IAAI;AACxB;AAMA,SAAS,gBAAgB,UAAkB,QAAkC;AAC3E,QAAM,OAAO,aAAa,QAAQ;AAClC,QAAM,QAAkB,CAAC;AACzB,QAAM,KAAK,6BAA6B,OAAO,KAAK,MAAM;AAC1D,QAAM,KAAK,oBAAoB,IAAI,eAAe;AAElD,aAAW,CAAC,SAAS,KAAK,KAAK,OAAO,QAAQ,OAAO,MAAM,GAAG;AAC5D,QAAI,YAAY,QAAQ,MAAM,SAAU;AACxC,UAAM,SAAS,cAAc,MAAM,IAAI;AACvC,UAAM,KAAK,SAAS,MAAM,KAAK,KAAK;AACpC,UAAM,KAAK,KAAK,OAAO,MAAM,MAAM,GAAG;AAAA,EACxC;AAEA,QAAM,KAAK,GAAG;AACd,SAAO,MAAM,KAAK,IAAI;AACxB;AAKO,SAAS,UAAU,QAAkC;AAC1D,QAAM,QAAkB;AAAA,IACtB;AAAA,IACA,qBAAoB,oBAAI,KAAK,GAAE,YAAY,CAAC;AAAA,IAC5C;AAAA,EACF;AAEA,QAAM,gBAAgB,OAAO,QAAQ,OAAO,OAAO;AAEnD,aAAW,CAAC,UAAU,MAAM,KAAK,eAAe;AAC9C,UAAM,KAAK,oBAAoB,UAAU,MAAM,CAAC;AAChD,UAAM,KAAK,EAAE;AACb,UAAM,KAAK,gBAAgB,UAAU,MAAM,CAAC;AAC5C,UAAM,KAAK,EAAE;AACb,UAAM,KAAK,gBAAgB,UAAU,MAAM,CAAC;AAC5C,UAAM,KAAK,EAAE;AAAA,EACf;AAGA,MAAI,cAAc,SAAS,GAAG;AAC5B,UAAM,QAAQ,cAAc,IAAI,CAAC,CAAC,EAAE,MAAM,IAAI,EAAE,GAAG;AACnD,UAAM,KAAK,uCAAuC;AAClD,UAAM,KAAK,8BAA8B,MAAM,KAAK,KAAK,CAAC,GAAG;AAC7D,UAAM,KAAK,EAAE;AAGb,UAAM,KAAK,+DAA+D;AAC1E,UAAM,KAAK,kCAAkC;AAC7C,eAAW,CAAC,QAAQ,KAAK,eAAe;AACtC,YAAM,KAAK,KAAK,QAAQ,KAAK,aAAa,QAAQ,CAAC,GAAG;AAAA,IACxD;AACA,UAAM,KAAK,GAAG;AACd,UAAM,KAAK,EAAE;AAAA,EACf;AAEA,SAAO,MAAM,KAAK,IAAI;AACxB;;;ACrGO,SAAS,WAAW,QAAkC;AAC3D,QAAM,gBAAgB,OAAO,QAAQ,OAAO,OAAO;AACnD,QAAM,cAAc,cAAc,IAAI,CAAC,CAAC,EAAE,MAAM,aAAa,EAAE,CAAC;AAEhE,QAAM,QAAkB;AAAA,IACtB;AAAA,IACA,qBAAoB,oBAAI,KAAK,GAAE,YAAY,CAAC;AAAA,IAC5C;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF;AAEA,MAAI,YAAY,SAAS,GAAG;AAC1B,UAAM,eAAe,cAAc,QAAQ,CAAC,CAAC,EAAE,MAAM;AACnD,YAAM,OAAO,aAAa,EAAE;AAC5B,aAAO,CAAC,GAAG,IAAI,eAAe,GAAG,IAAI,aAAa;AAAA,IACpD,CAAC;AACD,UAAM,KAAK,iBAAiB,CAAC,GAAG,aAAa,GAAG,YAAY,EAAE,KAAK,IAAI,CAAC,oBAAoB;AAAA,EAC9F;AAEA,QAAM,KAAK,EAAE;AAGb,QAAM,KAAK,2DAA2D;AACtE,QAAM,KAAK,gHAAgH;AAC3H,QAAM,KAAK,gDAAgD;AAC3D,QAAM,KAAK,uDAAuD;AAClE,QAAM,KAAK,6CAA6C;AACxD,QAAM,KAAK,kDAAkD;AAC7D,QAAM,KAAK,kDAAkD;AAC7D,QAAM,KAAK,4CAA4C;AACvD,QAAM,KAAK,GAAG;AACd,QAAM,KAAK,EAAE;AAGb,QAAM,KAAK,4DAA4D;AACvE,QAAM,KAAK,sCAAsC;AAEjD,aAAW,CAAC,QAAQ,KAAK,eAAe;AACtC,UAAM,WAAW,aAAa,QAAQ;AACtC,UAAM,KAAK,KAAK,QAAQ,wBAAwB,QAAQ,KAAK,QAAQ,gBAAgB,QAAQ,eAAe;AAAA,EAC9G;AAEA,QAAM,KAAK,sEAAsE;AACjF,QAAM,KAAK,wBAAwB;AACnC,QAAM,KAAK,iCAAiC;AAC5C,QAAM,KAAK,GAAG;AACd,QAAM,KAAK,EAAE;AAGb,QAAM,KAAK,KAAK;AAChB,QAAM,KAAK,uCAAuC;AAClD,QAAM,KAAK,qEAAqE;AAChF,QAAM,KAAK,KAAK;AAChB,QAAM,KAAK,qCAAqC;AAChD,QAAM,KAAK,2BAA2B;AACtC,QAAM,KAAK,4BAA4B;AACvC,QAAM,KAAK,iCAAiC;AAC5C,QAAM,KAAK,mDAAmD;AAC9D,QAAM,KAAK,+BAA+B;AAC1C,QAAM,KAAK,kDAAkD;AAC7D,QAAM,KAAK,GAAG;AACd,QAAM,KAAK,EAAE;AAGb,QAAM,KAAK,8IAAgJ;AAC3J,QAAM,KAAK,EAAE;AAEb,SAAO,MAAM,KAAK,IAAI;AACxB;;;AC/EO,SAAS,WAAW,QAAkC;AAC3D,QAAM,gBAAgB,OAAO,QAAQ,OAAO,OAAO;AACnD,QAAM,YAAY,cAAc,IAAI,CAAC,CAAC,EAAE,MAAM,aAAa,EAAE,CAAC;AAE9D,QAAM,QAAkB;AAAA,IACtB;AAAA,IACA,qBAAoB,oBAAI,KAAK,GAAE,YAAY,CAAC;AAAA,IAC5C;AAAA,EACF;AAGA,MAAI,UAAU,SAAS,GAAG;AACxB,UAAM,aAAa,cAAc,QAAQ,CAAC,CAAC,EAAE,MAAM;AACjD,YAAM,OAAO,aAAa,EAAE;AAC5B,aAAO,CAAC,GAAG,IAAI,eAAe,GAAG,IAAI,aAAa;AAAA,IACpD,CAAC;AACD,UAAM,KAAK,iBAAiB,CAAC,GAAG,WAAW,GAAG,UAAU,EAAE,KAAK,IAAI,CAAC,iDAAiD;AAAA,EACvH;AAGA,QAAM,KAAK,wEAAwE;AACnF,QAAM,KAAK,0CAA0C;AACrD,QAAM,KAAK,2HAA2H;AACtI,QAAM,KAAK,EAAE;AAEb,SAAO,MAAM,KAAK,IAAI;AACxB;;;ALxBA,IAAM,sBAAsB;AAC5B,IAAM,qBAAqB;AAQ3B,eAAsB,SAAS,SAAoD;AACjF,QAAM,aAAa,SAAS,cAAc;AAC1C,QAAM,YAAY,SAAS,aAAa;AAGxC,QAAM,SAAS,MAAM,WAAW,UAAU;AAG1C,QAAM,MAAM,WAAW,EAAE,WAAW,KAAK,CAAC;AAG1C,QAAM,eAAe,UAAU,MAAM;AACrC,QAAM,gBAAgB,WAAW,MAAM;AACvC,QAAM,gBAAgB,WAAW,MAAM;AAGvC,QAAM,YAAY,KAAK,WAAW,UAAU;AAC5C,QAAM,aAAa,KAAK,WAAW,WAAW;AAC9C,QAAM,aAAa,KAAK,WAAW,UAAU;AAE7C,QAAM,QAAQ,IAAI;AAAA,IAChB,UAAU,WAAW,cAAc,OAAO;AAAA,IAC1C,UAAU,YAAY,eAAe,OAAO;AAAA,IAC5C,UAAU,YAAY,eAAe,OAAO;AAAA,EAC9C,CAAC;AAGD,QAAM,gBAAgB,OAAO,QAAQ,OAAO,OAAO;AACnD,QAAM,aAAa,cAAc;AAAA,IAC/B,CAAC,KAAK,CAAC,EAAE,MAAM,MAAM,MAAM,OAAO,KAAK,OAAO,MAAM,EAAE;AAAA,IACtD;AAAA,EACF;AAEA,SAAO;AAAA,IACL,aAAa,cAAc;AAAA,IAC3B;AAAA,IACA,OAAO,CAAC,WAAW,YAAY,UAAU;AAAA,IACzC;AAAA,EACF;AACF;","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, 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 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 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 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 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/generator — DO NOT EDIT',\n `// Generated at: ${new Date().toISOString()}`,\n '',\n `import type { NetSuiteConfig } from '@suiteportal/connector';`,\n `import {`,\n ` SuitePortalClient as BaseClient,`,\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/client-runtime';`,\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 // Re-export types for convenience\n lines.push('export type { FindManyArgs, FindFirstArgs, CountArgs, CreateArgs, UpdateArgs, DeleteArgs, UpsertArgs, IncludeInput } from \\'@suiteportal/client-runtime\\';');\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":[]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@suiteportal/generator",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.3",
|
|
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.1.
|
|
24
|
+
"@suiteportal/introspector": "^0.1.2"
|
|
25
25
|
},
|
|
26
26
|
"license": "MIT",
|
|
27
27
|
"author": "Trey Hulse",
|