@spfn/core 0.1.0-alpha.65 → 0.1.0-alpha.68
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/codegen/generators/index.d.ts +7 -7
- package/dist/codegen/generators/index.js +36 -35
- package/dist/codegen/generators/index.js.map +1 -1
- package/dist/codegen/index.d.ts +64 -123
- package/dist/codegen/index.js +877 -958
- package/dist/codegen/index.js.map +1 -1
- package/dist/index.js +16 -5
- package/dist/index.js.map +1 -1
- package/dist/route/index.js +16 -5
- package/dist/route/index.js.map +1 -1
- package/dist/server/index.js +16 -5
- package/dist/server/index.js.map +1 -1
- package/package.json +1 -1
- /package/dist/{generator-DHiAqhKv.d.ts → index-DHiAqhKv.d.ts} +0 -0
|
@@ -1,16 +1,16 @@
|
|
|
1
|
-
import { c as createContractGenerator } from '../../
|
|
2
|
-
export { C as ContractGeneratorConfig } from '../../
|
|
1
|
+
import { c as createContractGenerator } from '../../index-DHiAqhKv.js';
|
|
2
|
+
export { C as ContractGeneratorConfig } from '../../index-DHiAqhKv.js';
|
|
3
3
|
|
|
4
4
|
/**
|
|
5
|
-
*
|
|
5
|
+
* Built-in Generators Export
|
|
6
6
|
*
|
|
7
|
-
*
|
|
8
|
-
* e.g., @spfn/core:contract
|
|
7
|
+
* Provides a registry of all built-in generators
|
|
9
8
|
*/
|
|
10
9
|
|
|
11
10
|
/**
|
|
12
|
-
*
|
|
13
|
-
*
|
|
11
|
+
* Registry of available generators
|
|
12
|
+
*
|
|
13
|
+
* Used by package-based generator loading (e.g., "@spfn/core:contract")
|
|
14
14
|
*/
|
|
15
15
|
declare const generators: {
|
|
16
16
|
contract: typeof createContractGenerator;
|
|
@@ -1,14 +1,13 @@
|
|
|
1
|
-
import { join
|
|
1
|
+
import { join } from 'path';
|
|
2
2
|
import { existsSync, mkdirSync, accessSync, constants, writeFileSync, unlinkSync, createWriteStream, statSync, readdirSync, renameSync, readFileSync } from 'fs';
|
|
3
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
|
-
// src/codegen/
|
|
8
|
-
async function scanContracts(contractsDir) {
|
|
7
|
+
// src/codegen/built-in/contract/index.ts
|
|
8
|
+
async function scanContracts(contractsDir, packagePrefix) {
|
|
9
9
|
const contractFiles = await scanContractFiles(contractsDir);
|
|
10
10
|
const mappings = [];
|
|
11
|
-
const packagePrefix = getPackagePrefix(contractsDir);
|
|
12
11
|
for (let i = 0; i < contractFiles.length; i++) {
|
|
13
12
|
const filePath = contractFiles[i];
|
|
14
13
|
const exports = extractContractExports(filePath);
|
|
@@ -19,10 +18,14 @@ async function scanContracts(contractsDir) {
|
|
|
19
18
|
`Contract '${contractExport.name}' in ${filePath} must use absolute path. Found: '${contractExport.path}'. Use '/your-path' instead.`
|
|
20
19
|
);
|
|
21
20
|
}
|
|
22
|
-
|
|
21
|
+
if (packagePrefix && !contractExport.path.startsWith(packagePrefix)) {
|
|
22
|
+
throw new Error(
|
|
23
|
+
`Contract '${contractExport.name}' in ${filePath} must include package prefix. Expected path to start with '${packagePrefix}', but found: '${contractExport.path}'. Example: path: '${packagePrefix}/${contractExport.path}'`
|
|
24
|
+
);
|
|
25
|
+
}
|
|
23
26
|
mappings.push({
|
|
24
27
|
method: contractExport.method,
|
|
25
|
-
path:
|
|
28
|
+
path: contractExport.path,
|
|
26
29
|
contractName: contractExport.name,
|
|
27
30
|
contractImportPath: getImportPath(filePath),
|
|
28
31
|
routeFile: "",
|
|
@@ -172,24 +175,6 @@ function extractContractData(objectLiteral) {
|
|
|
172
175
|
function isContractName(name) {
|
|
173
176
|
return name.indexOf("Contract") !== -1 || name.indexOf("contract") !== -1 || name.endsWith("Schema") || name.endsWith("schema");
|
|
174
177
|
}
|
|
175
|
-
function getPackagePrefix(contractsDir) {
|
|
176
|
-
try {
|
|
177
|
-
let currentDir = dirname(contractsDir);
|
|
178
|
-
for (let i = 0; i < 5; i++) {
|
|
179
|
-
const packageJsonPath = join(currentDir, "package.json");
|
|
180
|
-
try {
|
|
181
|
-
const packageJson = JSON.parse(readFileSync(packageJsonPath, "utf-8"));
|
|
182
|
-
if (packageJson.spfn?.prefix) {
|
|
183
|
-
return packageJson.spfn.prefix;
|
|
184
|
-
}
|
|
185
|
-
} catch {
|
|
186
|
-
}
|
|
187
|
-
currentDir = dirname(currentDir);
|
|
188
|
-
}
|
|
189
|
-
} catch {
|
|
190
|
-
}
|
|
191
|
-
return "";
|
|
192
|
-
}
|
|
193
178
|
function getImportPath(filePath) {
|
|
194
179
|
const srcIndex = filePath.indexOf("/src/");
|
|
195
180
|
if (srcIndex === -1) {
|
|
@@ -206,7 +191,7 @@ function getImportPath(filePath) {
|
|
|
206
191
|
return "@/" + cleanPath;
|
|
207
192
|
}
|
|
208
193
|
|
|
209
|
-
// src/codegen/
|
|
194
|
+
// src/codegen/built-in/contract/helpers.ts
|
|
210
195
|
function groupByResource(mappings) {
|
|
211
196
|
const grouped = {};
|
|
212
197
|
for (let i = 0; i < mappings.length; i++) {
|
|
@@ -220,7 +205,11 @@ function groupByResource(mappings) {
|
|
|
220
205
|
return grouped;
|
|
221
206
|
}
|
|
222
207
|
function extractResourceName(path) {
|
|
223
|
-
|
|
208
|
+
let processedPath = path;
|
|
209
|
+
if (!processedPath.startsWith("/")) {
|
|
210
|
+
processedPath = "/" + processedPath;
|
|
211
|
+
}
|
|
212
|
+
const segments = processedPath.slice(1).split("/").filter((s) => s && s !== "*");
|
|
224
213
|
const staticSegments = [];
|
|
225
214
|
for (let i = 0; i < segments.length; i++) {
|
|
226
215
|
const seg = segments[i];
|
|
@@ -258,6 +247,8 @@ function toCamelCase(str, capitalize) {
|
|
|
258
247
|
}
|
|
259
248
|
return result.join("");
|
|
260
249
|
}
|
|
250
|
+
|
|
251
|
+
// src/codegen/built-in/contract/emitter.ts
|
|
261
252
|
async function generateClient(mappings, options) {
|
|
262
253
|
const startTime = Date.now();
|
|
263
254
|
const grouped = groupByResource(mappings);
|
|
@@ -382,6 +373,12 @@ function countUniqueContractFiles(mappings) {
|
|
|
382
373
|
}
|
|
383
374
|
return files.size;
|
|
384
375
|
}
|
|
376
|
+
function toKebabCase(str) {
|
|
377
|
+
if (str.length === 0) {
|
|
378
|
+
return str;
|
|
379
|
+
}
|
|
380
|
+
return str.replace(/([a-z])([A-Z])/g, "$1-$2").toLowerCase();
|
|
381
|
+
}
|
|
385
382
|
async function generateSplitClient(_mappings, grouped, options) {
|
|
386
383
|
const outputPath = options.outputPath;
|
|
387
384
|
const outputDir = outputPath.endsWith(".ts") || outputPath.endsWith(".js") ? outputPath.replace(/\.[jt]s$/, "") : outputPath;
|
|
@@ -391,7 +388,8 @@ async function generateSplitClient(_mappings, grouped, options) {
|
|
|
391
388
|
const resourceName = resourceNames[i];
|
|
392
389
|
const routes = grouped[resourceName];
|
|
393
390
|
const code = generateResourceFile(resourceName, routes, options);
|
|
394
|
-
const
|
|
391
|
+
const kebabName = toKebabCase(resourceName);
|
|
392
|
+
const filePath = `${outputDir}/${kebabName}.ts`;
|
|
395
393
|
await writeFile(filePath, code, "utf-8");
|
|
396
394
|
}
|
|
397
395
|
const indexCode = generateIndexFile(resourceNames, options);
|
|
@@ -480,14 +478,16 @@ function generateIndexFile(resourceNames, options) {
|
|
|
480
478
|
`;
|
|
481
479
|
for (let i = 0; i < resourceNames.length; i++) {
|
|
482
480
|
const resourceName = resourceNames[i];
|
|
483
|
-
|
|
481
|
+
const kebabName = toKebabCase(resourceName);
|
|
482
|
+
code += `export * from './${kebabName}.js';
|
|
484
483
|
`;
|
|
485
484
|
}
|
|
486
485
|
code += `
|
|
487
486
|
`;
|
|
488
487
|
for (let i = 0; i < resourceNames.length; i++) {
|
|
489
488
|
const resourceName = resourceNames[i];
|
|
490
|
-
|
|
489
|
+
const kebabName = toKebabCase(resourceName);
|
|
490
|
+
code += `import { ${resourceName} } from './${kebabName}.js';
|
|
491
491
|
`;
|
|
492
492
|
}
|
|
493
493
|
code += `
|
|
@@ -1281,7 +1281,7 @@ function initializeLogger() {
|
|
|
1281
1281
|
}
|
|
1282
1282
|
var logger = initializeLogger();
|
|
1283
1283
|
|
|
1284
|
-
// src/codegen/
|
|
1284
|
+
// src/codegen/built-in/contract/index.ts
|
|
1285
1285
|
var contractLogger = logger.child("contract-gen");
|
|
1286
1286
|
var DEFAULT_CONTRACTS_DIR = "src/lib/contracts";
|
|
1287
1287
|
var DEFAULT_OUTPUT_PATH = "src/lib/api";
|
|
@@ -1343,6 +1343,8 @@ function createContractGenerator(config = {}) {
|
|
|
1343
1343
|
const cwd = options.cwd;
|
|
1344
1344
|
const fullContractsDir = join(cwd, contractsDir);
|
|
1345
1345
|
const fullOutputPath = join(cwd, outputPath);
|
|
1346
|
+
const prefix = readPrefixFromPackageJson(cwd);
|
|
1347
|
+
const apiName = generateApiName(prefix);
|
|
1346
1348
|
try {
|
|
1347
1349
|
if (!existsSync(fullContractsDir)) {
|
|
1348
1350
|
if (options.debug) {
|
|
@@ -1364,6 +1366,7 @@ function createContractGenerator(config = {}) {
|
|
|
1364
1366
|
outputPath: fullOutputPath,
|
|
1365
1367
|
changedFilePath: changedFile.path,
|
|
1366
1368
|
baseUrl: config.baseUrl,
|
|
1369
|
+
apiName,
|
|
1367
1370
|
debug: options.debug
|
|
1368
1371
|
});
|
|
1369
1372
|
if (success) {
|
|
@@ -1376,7 +1379,7 @@ function createContractGenerator(config = {}) {
|
|
|
1376
1379
|
contractLogger.info("Incremental update failed, doing full regen");
|
|
1377
1380
|
}
|
|
1378
1381
|
}
|
|
1379
|
-
const allContracts = await scanContracts(fullContractsDir);
|
|
1382
|
+
const allContracts = await scanContracts(fullContractsDir, prefix);
|
|
1380
1383
|
if (allContracts.length === 0) {
|
|
1381
1384
|
if (options.debug) {
|
|
1382
1385
|
contractLogger.warn("No contracts found");
|
|
@@ -1384,8 +1387,6 @@ function createContractGenerator(config = {}) {
|
|
|
1384
1387
|
contractCache = null;
|
|
1385
1388
|
return;
|
|
1386
1389
|
}
|
|
1387
|
-
const prefix = readPrefixFromPackageJson(cwd);
|
|
1388
|
-
const apiName = generateApiName(prefix);
|
|
1389
1390
|
const clientOptions = createClientOptions(fullContractsDir, fullOutputPath, config.baseUrl, apiName);
|
|
1390
1391
|
const stats = await generateClient(allContracts, clientOptions);
|
|
1391
1392
|
contractCache = {
|
|
@@ -1409,7 +1410,7 @@ function createContractGenerator(config = {}) {
|
|
|
1409
1410
|
};
|
|
1410
1411
|
}
|
|
1411
1412
|
async function attemptIncrementalUpdate(options) {
|
|
1412
|
-
const { cwd, contractsDir, outputPath, changedFilePath, baseUrl, debug } = options;
|
|
1413
|
+
const { cwd, contractsDir, outputPath, changedFilePath, baseUrl, apiName, debug } = options;
|
|
1413
1414
|
if (!contractCache) {
|
|
1414
1415
|
return false;
|
|
1415
1416
|
}
|
|
@@ -1434,7 +1435,7 @@ async function attemptIncrementalUpdate(options) {
|
|
|
1434
1435
|
}
|
|
1435
1436
|
return true;
|
|
1436
1437
|
}
|
|
1437
|
-
const clientOptions = createClientOptions(contractsDir, outputPath, baseUrl);
|
|
1438
|
+
const clientOptions = createClientOptions(contractsDir, outputPath, baseUrl, apiName);
|
|
1438
1439
|
const stats = await generateClient(updatedContracts, clientOptions);
|
|
1439
1440
|
contractCache = {
|
|
1440
1441
|
contracts: updatedContracts,
|