@spfn/core 0.1.0-alpha.63 → 0.1.0-alpha.64

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,12 +1,12 @@
1
- import { join, dirname } from 'path';
1
+ import { join } from 'path';
2
2
  import { existsSync, mkdirSync, accessSync, constants, writeFileSync, unlinkSync, createWriteStream, statSync, readdirSync, renameSync, readFileSync } from 'fs';
3
- import { mkdir, writeFile, readdir, stat } from 'fs/promises';
3
+ import { readdir, stat, mkdir, writeFile } from 'fs/promises';
4
4
  import * as ts from 'typescript';
5
5
  import pino from 'pino';
6
6
 
7
7
  // src/codegen/generators/contract-generator.ts
8
- async function scanContracts(routesDir) {
9
- const contractFiles = await scanContractFiles(routesDir);
8
+ async function scanContracts(contractsDir) {
9
+ const contractFiles = await scanContractFiles(contractsDir);
10
10
  const mappings = [];
11
11
  for (let i = 0; i < contractFiles.length; i++) {
12
12
  const filePath = contractFiles[i];
@@ -24,7 +24,6 @@ async function scanContracts(routesDir) {
24
24
  contractName: contractExport.name,
25
25
  contractImportPath: getImportPath(filePath),
26
26
  routeFile: "",
27
- // Not needed anymore
28
27
  contractFile: filePath,
29
28
  hasQuery: contractExport.hasQuery,
30
29
  hasBody: contractExport.hasBody,
@@ -37,19 +36,14 @@ async function scanContracts(routesDir) {
37
36
  async function scanContractFiles(dir, files = []) {
38
37
  try {
39
38
  const entries = await readdir(dir);
40
- const isLibContracts = dir.includes("/lib/contracts");
41
39
  for (let i = 0; i < entries.length; i++) {
42
40
  const entry = entries[i];
43
41
  const fullPath = join(dir, entry);
44
42
  const fileStat = await stat(fullPath);
45
43
  if (fileStat.isDirectory()) {
46
44
  await scanContractFiles(fullPath, files);
47
- } else if (isLibContracts) {
48
- if ((entry.endsWith(".ts") || entry.endsWith(".js") || entry.endsWith(".mjs")) && !entry.endsWith(".d.ts") && !entry.endsWith(".test.ts") && !entry.endsWith(".test.js") && !entry.endsWith(".test.mjs")) {
49
- files.push(fullPath);
50
- }
51
45
  } else {
52
- if (entry === "contract.ts") {
46
+ if ((entry.endsWith(".ts") || entry.endsWith(".js") || entry.endsWith(".mjs")) && !entry.endsWith(".d.ts") && !entry.endsWith(".test.ts") && !entry.endsWith(".test.js") && !entry.endsWith(".test.mjs")) {
53
47
  files.push(fullPath);
54
48
  }
55
49
  }
@@ -176,7 +170,7 @@ function extractContractData(objectLiteral) {
176
170
  function isContractName(name) {
177
171
  return name.indexOf("Contract") !== -1 || name.indexOf("contract") !== -1 || name.endsWith("Schema") || name.endsWith("schema");
178
172
  }
179
- function getImportPath(filePath, _scanDir) {
173
+ function getImportPath(filePath) {
180
174
  const srcIndex = filePath.indexOf("/src/");
181
175
  if (srcIndex === -1) {
182
176
  throw new Error(`Cannot determine import path for ${filePath}: /src/ directory not found`);
@@ -250,13 +244,7 @@ async function generateClient(mappings, options) {
250
244
  const startTime = Date.now();
251
245
  const grouped = groupByResource(mappings);
252
246
  const resourceNames = Object.keys(grouped);
253
- if (options.splitByResource === false) {
254
- const code = generateClientCode(mappings, grouped, options);
255
- await mkdir(dirname(options.outputPath), { recursive: true });
256
- await writeFile(options.outputPath, code, "utf-8");
257
- } else {
258
- await generateSplitClient(mappings, grouped, options);
259
- }
247
+ await generateSplitClient(mappings, grouped, options);
260
248
  return {
261
249
  routesScanned: mappings.length,
262
250
  contractsFound: mappings.length,
@@ -266,17 +254,6 @@ async function generateClient(mappings, options) {
266
254
  duration: Date.now() - startTime
267
255
  };
268
256
  }
269
- function generateClientCode(mappings, grouped, options) {
270
- let code = "";
271
- code += generateHeader();
272
- code += generateImports(mappings);
273
- {
274
- code += generateTypes(mappings);
275
- }
276
- code += generateApiObject(grouped, options);
277
- code += generateFooter();
278
- return code;
279
- }
280
257
  function generateHeader() {
281
258
  return `/**
282
259
  * Auto-generated API Client
@@ -289,28 +266,6 @@ function generateHeader() {
289
266
 
290
267
  `;
291
268
  }
292
- function generateImports(mappings, options) {
293
- let code = "";
294
- code += `import { client } from '@spfn/core/client';
295
- `;
296
- {
297
- code += `import type { InferContract } from '@spfn/core';
298
- `;
299
- }
300
- code += `
301
- `;
302
- const importGroups = groupContractsByImportPath(mappings);
303
- const importPaths = Object.keys(importGroups);
304
- for (let i = 0; i < importPaths.length; i++) {
305
- const importPath = importPaths[i];
306
- const contracts = importGroups[importPath];
307
- code += `import { ${contracts.join(", ")} } from '${importPath}';
308
- `;
309
- }
310
- code += `
311
- `;
312
- return code;
313
- }
314
269
  function groupContractsByImportPath(mappings) {
315
270
  const groups = {};
316
271
  for (let i = 0; i < mappings.length; i++) {
@@ -329,38 +284,6 @@ function groupContractsByImportPath(mappings) {
329
284
  }
330
285
  return result;
331
286
  }
332
- function generateTypes(mappings, _options) {
333
- let code = "";
334
- code += `// ============================================
335
- `;
336
- code += `// Auto-generated Types
337
- `;
338
- code += `// ============================================
339
-
340
- `;
341
- for (let i = 0; i < mappings.length; i++) {
342
- const mapping = mappings[i];
343
- const typeName = generateTypeName(mapping);
344
- const contractType = `typeof ${mapping.contractName}`;
345
- code += `export type ${typeName}Response = InferContract<${contractType}>['response'];
346
- `;
347
- if (mapping.hasQuery) {
348
- code += `export type ${typeName}Query = InferContract<${contractType}>['query'];
349
- `;
350
- }
351
- if (mapping.hasParams || mapping.path.includes(":")) {
352
- code += `export type ${typeName}Params = InferContract<${contractType}>['params'];
353
- `;
354
- }
355
- if (mapping.hasBody) {
356
- code += `export type ${typeName}Body = InferContract<${contractType}>['body'];
357
- `;
358
- }
359
- code += `
360
- `;
361
- }
362
- return code;
363
- }
364
287
  function generateTypeName(mapping) {
365
288
  let name = mapping.contractName;
366
289
  if (name.endsWith("Contract")) {
@@ -371,42 +294,13 @@ function generateTypeName(mapping) {
371
294
  }
372
295
  return name;
373
296
  }
374
- function generateApiObject(grouped, options) {
375
- let code = "";
376
- code += `/**
377
- * Type-safe API client
378
- */
379
- export const api = {
380
- `;
381
- const resourceNames = Object.keys(grouped);
382
- for (let i = 0; i < resourceNames.length; i++) {
383
- const resourceName = resourceNames[i];
384
- const routes = grouped[resourceName];
385
- code += ` ${resourceName}: {
386
- `;
387
- for (let j = 0; j < routes.length; j++) {
388
- const route = routes[j];
389
- code += generateMethodCode(route, options);
390
- }
391
- code += ` }`;
392
- if (i < resourceNames.length - 1) {
393
- code += `,`;
394
- }
395
- code += `
396
- `;
397
- }
398
- code += `} as const;
399
-
400
- `;
401
- return code;
402
- }
403
297
  function generateMethodCode(mapping, options) {
404
298
  const methodName = generateMethodName(mapping);
405
299
  const hasParams = mapping.hasParams || mapping.path.includes(":");
406
300
  const hasQuery = mapping.hasQuery || false;
407
301
  const hasBody = mapping.hasBody || false;
408
302
  let code = "";
409
- if (options.includeJsDoc !== false) {
303
+ {
410
304
  code += ` /**
411
305
  `;
412
306
  code += ` * ${mapping.method} ${mapping.path}
@@ -461,27 +355,6 @@ function generateMethodName(mapping) {
461
355
  }
462
356
  return method;
463
357
  }
464
- function generateFooter() {
465
- return `/**
466
- * Export client instance for advanced usage
467
- *
468
- * Use this to add interceptors or customize the client:
469
- *
470
- * @example
471
- * \`\`\`ts
472
- * import { client } from './api';
473
- * import { createAuthInterceptor } from '@spfn/auth/nextjs';
474
- * import { NextJSCookieProvider } from '@spfn/auth/nextjs';
475
- *
476
- * client.use(createAuthInterceptor({
477
- * cookieProvider: new NextJSCookieProvider(),
478
- * encryptionKey: process.env.ENCRYPTION_KEY!
479
- * }));
480
- * \`\`\`
481
- */
482
- export { client };
483
- `;
484
- }
485
358
  function countUniqueContractFiles(mappings) {
486
359
  const files = /* @__PURE__ */ new Set();
487
360
  for (let i = 0; i < mappings.length; i++) {
@@ -499,7 +372,7 @@ async function generateSplitClient(_mappings, grouped, options) {
499
372
  for (let i = 0; i < resourceNames.length; i++) {
500
373
  const resourceName = resourceNames[i];
501
374
  const routes = grouped[resourceName];
502
- const code = generateResourceFile(resourceName, routes, options);
375
+ const code = generateResourceFile(resourceName, routes);
503
376
  const filePath = `${outputDir}/${resourceName}.ts`;
504
377
  await writeFile(filePath, code, "utf-8");
505
378
  }
@@ -568,7 +441,7 @@ function generateResourceFile(resourceName, routes, options) {
568
441
  `;
569
442
  for (let i = 0; i < routes.length; i++) {
570
443
  const route = routes[i];
571
- code += generateMethodCode(route, options);
444
+ code += generateMethodCode(route);
572
445
  }
573
446
  code += `} as const;
574
447
  `;
@@ -1408,10 +1281,7 @@ function createContractGenerator(config = {}) {
1408
1281
  return;
1409
1282
  }
1410
1283
  const stats = await generateClient(allContracts, {
1411
- // For backwards compatibility
1412
- outputPath,
1413
- includeJsDoc: true
1414
- });
1284
+ outputPath});
1415
1285
  if (options.debug) {
1416
1286
  contractLogger.info("Client generated", {
1417
1287
  endpoints: stats.methodsGenerated,