@suiteportal/generator 0.1.0 → 0.1.1

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
@@ -140,7 +140,7 @@ function emitClient(schema) {
140
140
  `} from '@suiteportal/client-runtime';`
141
141
  ];
142
142
  if (typeImports.length > 0) {
143
- lines.push(`import type { ${typeImports.join(", ")} } from './types.js';`);
143
+ lines.push(`import type { ${typeImports.join(", ")} } from './types';`);
144
144
  }
145
145
  lines.push("");
146
146
  lines.push("/** A typed model delegate for a specific record type. */");
@@ -189,11 +189,11 @@ function emitBarrel(schema) {
189
189
  ""
190
190
  ];
191
191
  if (typeNames.length > 0) {
192
- lines.push(`export type { ${typeNames.join(", ")}, RecordTypeId, RecordTypeMap } from './types.js';`);
192
+ lines.push(`export type { ${typeNames.join(", ")}, RecordTypeId, RecordTypeMap } from './types';`);
193
193
  }
194
- lines.push(`export type { SuitePortalClient, TypedModelDelegate } from './client.js';`);
195
- lines.push(`export { createClient } from './client.js';`);
196
- lines.push(`export type { FindManyArgs, FindFirstArgs, CountArgs } from './client.js';`);
194
+ lines.push(`export type { SuitePortalClient, TypedModelDelegate } from './client';`);
195
+ lines.push(`export { createClient } from './client';`);
196
+ lines.push(`export type { FindManyArgs, FindFirstArgs, CountArgs } from './client';`);
197
197
  lines.push("");
198
198
  return lines.join("\n");
199
199
  }
@@ -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 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\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 ClientOptions,`,\n `} from '@suiteportal/client-runtime';`,\n ];\n\n if (typeImports.length > 0) {\n lines.push(`import type { ${typeImports.join(', ')} } from './types.js';`);\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> {');\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('}');\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}>;`);\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 } 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 lines.push(`export type { ${typeNames.join(', ')}, RecordTypeId, RecordTypeMap } from './types.js';`);\n }\n\n // Client exports\n lines.push(`export type { SuitePortalClient, TypedModelDelegate } from './client.js';`);\n lines.push(`export { createClient } from './client.js';`);\n lines.push(`export type { FindManyArgs, FindFirstArgs, CountArgs } from './client.js';`);\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 } 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 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\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 ClientOptions,`,\n `} from '@suiteportal/client-runtime';`,\n ];\n\n if (typeImports.length > 0) {\n lines.push(`import type { ${typeImports.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> {');\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('}');\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}>;`);\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 } 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 lines.push(`export type { ${typeNames.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 } 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
@@ -108,7 +108,7 @@ function emitClient(schema) {
108
108
  `} from '@suiteportal/client-runtime';`
109
109
  ];
110
110
  if (typeImports.length > 0) {
111
- lines.push(`import type { ${typeImports.join(", ")} } from './types.js';`);
111
+ lines.push(`import type { ${typeImports.join(", ")} } from './types';`);
112
112
  }
113
113
  lines.push("");
114
114
  lines.push("/** A typed model delegate for a specific record type. */");
@@ -157,11 +157,11 @@ function emitBarrel(schema) {
157
157
  ""
158
158
  ];
159
159
  if (typeNames.length > 0) {
160
- lines.push(`export type { ${typeNames.join(", ")}, RecordTypeId, RecordTypeMap } from './types.js';`);
160
+ lines.push(`export type { ${typeNames.join(", ")}, RecordTypeId, RecordTypeMap } from './types';`);
161
161
  }
162
- lines.push(`export type { SuitePortalClient, TypedModelDelegate } from './client.js';`);
163
- lines.push(`export { createClient } from './client.js';`);
164
- lines.push(`export type { FindManyArgs, FindFirstArgs, CountArgs } from './client.js';`);
162
+ lines.push(`export type { SuitePortalClient, TypedModelDelegate } from './client';`);
163
+ lines.push(`export { createClient } from './client';`);
164
+ lines.push(`export type { FindManyArgs, FindFirstArgs, CountArgs } from './client';`);
165
165
  lines.push("");
166
166
  return lines.join("\n");
167
167
  }
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 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\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 ClientOptions,`,\n `} from '@suiteportal/client-runtime';`,\n ];\n\n if (typeImports.length > 0) {\n lines.push(`import type { ${typeImports.join(', ')} } from './types.js';`);\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> {');\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('}');\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}>;`);\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 } 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 lines.push(`export type { ${typeNames.join(', ')}, RecordTypeId, RecordTypeMap } from './types.js';`);\n }\n\n // Client exports\n lines.push(`export type { SuitePortalClient, TypedModelDelegate } from './client.js';`);\n lines.push(`export { createClient } from './client.js';`);\n lines.push(`export type { FindManyArgs, FindFirstArgs, CountArgs } from './client.js';`);\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 } 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 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\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 ClientOptions,`,\n `} from '@suiteportal/client-runtime';`,\n ];\n\n if (typeImports.length > 0) {\n lines.push(`import type { ${typeImports.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> {');\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('}');\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}>;`);\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 } 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 lines.push(`export type { ${typeNames.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 } 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.1.0",
3
+ "version": "0.1.1",
4
4
  "description": "Code generator for SuitePortal NetSuite ORM — emits TypeScript types from schema",
5
5
  "type": "module",
6
6
  "main": "./dist/index.cjs",