@codexsploitx/schemaapi 1.0.6 → 1.1.8

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/bin/schemaapi CHANGED
@@ -1,337 +1,23 @@
1
1
  #!/usr/bin/env node
2
- const fs = require("fs");
3
- const path = require("path");
4
- let schemaapi = {};
5
- try {
6
- // When installed as a package, this resolves to the SchemaApi entrypoint.
7
- // During local development, it points to the built dist file.
8
- // If it fails, we fall back to an internal minimal HTML renderer.
9
- // eslint-disable-next-line @typescript-eslint/no-var-requires
10
- schemaapi = require("..");
11
- } catch {
12
- schemaapi = {};
13
- }
14
2
 
15
- const args = process.argv.slice(2);
3
+ const fs = require('fs');
4
+ const path = require('path');
16
5
 
17
- function showHelp() {
18
- console.log("SchemaApi CLI");
19
- console.log("");
20
- console.log("Usage:");
21
- console.log(" schemaapi generate docs");
22
- console.log(" schemaapi generate sdk");
23
- console.log(" schemaapi generate tests");
24
- console.log(" schemaapi audit");
25
- console.log(" schemaapi init <adapter>");
26
- console.log("");
27
- console.log("Adapters:");
28
- console.log(" express");
29
- console.log(" next");
30
- console.log(" fastify");
31
- console.log(" remix");
32
- console.log(" nest");
33
- console.log(" deno");
34
- }
6
+ // Try to locate the compiled CLI
7
+ const cliPath = path.join(__dirname, '..', 'dist', 'cli.js');
35
8
 
36
- function loadConfig() {
37
- const cwd = process.cwd();
38
- const configPath = path.join(cwd, "schemaapi.config.json");
39
- if (!fs.existsSync(configPath)) {
40
- return null;
41
- }
9
+ if (fs.existsSync(cliPath)) {
42
10
  try {
43
- const raw = fs.readFileSync(configPath, "utf8");
44
- return JSON.parse(raw);
45
- } catch {
46
- return null;
47
- }
48
- }
49
-
50
- function loadContractsModule(contractsDir) {
51
- const cwd = process.cwd();
52
- const baseDir = path.join(cwd, contractsDir || "contracts");
53
- const candidates = ["index.js", "index.cjs"];
54
-
55
- for (const file of candidates) {
56
- const fullPath = path.join(baseDir, file);
57
- if (fs.existsSync(fullPath)) {
58
- try {
59
- return require(fullPath);
60
- } catch (error) {
61
- console.error(
62
- `Failed to load contracts module at ${fullPath}:`,
63
- (error && error.message) || error
64
- );
65
- process.exitCode = 1;
66
- return null;
67
- }
68
- }
69
- }
70
-
71
- console.error(
72
- `Could not find contracts entry in ${baseDir}. Expected one of: ${candidates.join(
73
- ", "
74
- )}`
75
- );
76
- process.exitCode = 1;
77
- return null;
11
+ const { cli } = require(cliPath);
12
+ cli(process.argv.slice(2));
13
+ } catch (error) {
14
+ console.error('Failed to run SchemaApi CLI:', error);
15
+ process.exit(1);
16
+ }
17
+ } else {
18
+ // Fallback for development if dist/cli.js is missing (e.g. running from source with ts-node)
19
+ // But for now, we expect the build to be present.
20
+ console.error('SchemaApi CLI not found. Please run "npm run build" if you are developing locally.');
21
+ console.error('Expected path:', cliPath);
22
+ process.exit(1);
78
23
  }
79
-
80
- function renderDocsHtmlFallback(docs) {
81
- const items = Array.isArray(docs.routes)
82
- ? docs.routes
83
- .map((route) => {
84
- const method = route && route.method ? String(route.method) : "";
85
- const pathValue = route && route.path ? String(route.path) : "";
86
- return `<li><code>${method} ${pathValue}</code></li>`;
87
- })
88
- .join("\n")
89
- : "";
90
-
91
- return `<!doctype html>
92
- <html lang="en">
93
- <head>
94
- <meta charset="utf-8" />
95
- <title>SchemaApi Docs</title>
96
- </head>
97
- <body>
98
- <h1>SchemaApi Docs</h1>
99
- <ul>
100
- ${items}
101
- </ul>
102
- </body>
103
- </html>`;
104
- }
105
-
106
- function generateDocsFromContracts(config) {
107
- const adapter = config && config.adapter ? String(config.adapter) : null;
108
- const contractsDir =
109
- config && config.contractsDir ? String(config.contractsDir) : "contracts";
110
-
111
- console.log("Generating docs from contract");
112
- if (adapter || contractsDir) {
113
- console.log(
114
- `Using config: adapter=${adapter || "unknown"}, contractsDir=${contractsDir}`
115
- );
116
- }
117
-
118
- const contractsModule = loadContractsModule(contractsDir);
119
- if (!contractsModule) {
120
- return;
121
- }
122
-
123
- const candidates = Object.values(contractsModule).filter(
124
- (value) =>
125
- value &&
126
- typeof value === "object" &&
127
- typeof value.docs === "function"
128
- );
129
-
130
- if (candidates.length === 0) {
131
- console.error(
132
- "No contracts with a docs() method were found in the contracts entry file."
133
- );
134
- process.exitCode = 1;
135
- return;
136
- }
137
-
138
- const combinedDocs = {
139
- routes: candidates.flatMap((contract) => {
140
- try {
141
- const docs = contract.docs();
142
- return Array.isArray(docs.routes) ? docs.routes : [];
143
- } catch {
144
- return [];
145
- }
146
- }),
147
- };
148
-
149
- if (!combinedDocs.routes.length) {
150
- console.error(
151
- "Contracts loaded, but no routes were found when calling docs()."
152
- );
153
- process.exitCode = 1;
154
- return;
155
- }
156
-
157
- const outDir = path.join(process.cwd(), "schemaapi-docs");
158
- if (!fs.existsSync(outDir)) {
159
- fs.mkdirSync(outDir, { recursive: true });
160
- }
161
- const outPath = path.join(outDir, "index.html");
162
-
163
- const hasRenderDocs =
164
- schemaapi && typeof schemaapi.renderDocs === "function";
165
- const html = hasRenderDocs
166
- ? schemaapi.renderDocs(combinedDocs, {
167
- format: "html",
168
- title: "SchemaApi Docs",
169
- theme: "dark",
170
- })
171
- : renderDocsHtmlFallback(combinedDocs);
172
-
173
- fs.writeFileSync(outPath, html, "utf8");
174
- console.log(`Docs generated at: ${path.relative(process.cwd(), outPath)}`);
175
- }
176
-
177
- function handleGenerate(target) {
178
- const config = loadConfig();
179
- const adapter = config && config.adapter ? String(config.adapter) : null;
180
- const contractsDir =
181
- config && config.contractsDir ? String(config.contractsDir) : null;
182
-
183
- if (target === "docs") {
184
- generateDocsFromContracts(config || {});
185
- return;
186
- }
187
- if (target === "sdk") {
188
- console.log("Generating SDK from contract");
189
- if (adapter || contractsDir) {
190
- console.log(
191
- `Using config: adapter=${adapter || "unknown"}, contractsDir=${contractsDir || "contracts"}`
192
- );
193
- }
194
- return;
195
- }
196
- if (target === "tests") {
197
- console.log("Generating tests from contract");
198
- if (adapter || contractsDir) {
199
- console.log(
200
- `Using config: adapter=${adapter || "unknown"}, contractsDir=${contractsDir || "contracts"}`
201
- );
202
- }
203
- return;
204
- }
205
- console.error(`Unknown generate target: ${target || ""}`);
206
- process.exitCode = 1;
207
- }
208
-
209
- function handleAudit() {
210
- console.log("Running SchemaApi audit");
211
- }
212
-
213
- function normalizeAdapter(value) {
214
- if (!value) return "generic";
215
- const v = String(value).toLowerCase();
216
- if (v === "next" || v === "nextjs") return "next";
217
- if (v === "remix") return "remix";
218
- if (v === "express") return "express";
219
- if (v === "fastify") return "fastify";
220
- if (v === "nest" || v === "nestjs") return "nest";
221
- if (v === "koa") return "koa";
222
- if (v === "hapi") return "hapi";
223
- if (v === "deno") return "deno";
224
- return v;
225
- }
226
-
227
- function handleInit(adapterArg) {
228
- const adapter = normalizeAdapter(adapterArg);
229
- const cwd = process.cwd();
230
- const contractsDir = path.join(cwd, "contracts");
231
-
232
- if (!fs.existsSync(contractsDir)) {
233
- fs.mkdirSync(contractsDir, { recursive: true });
234
- }
235
-
236
- const usersContractPath = path.join(contractsDir, "usersContract.ts");
237
- if (!fs.existsSync(usersContractPath)) {
238
- const usersContractContent = [
239
- 'import { createContract } from "@codexsploitx/schemaapi";',
240
- 'import { z } from "zod";',
241
- "",
242
- "export const usersContract = createContract({",
243
- ' "/users/:id": {',
244
- " GET: {",
245
- " params: z.object({ id: z.string() }),",
246
- " response: z.object({ id: z.string(), name: z.string() }),",
247
- " },",
248
- " },",
249
- "});",
250
- "",
251
- ].join("\n");
252
- fs.writeFileSync(usersContractPath, usersContractContent);
253
- }
254
-
255
- const indexPath = path.join(contractsDir, "index.ts");
256
- if (!fs.existsSync(indexPath)) {
257
- fs.writeFileSync(indexPath, 'export * from "./usersContract";\n');
258
- }
259
-
260
- if (adapter === "next") {
261
- const appApiUsersDir = path.join(cwd, "app", "api", "users");
262
- if (!fs.existsSync(appApiUsersDir)) {
263
- fs.mkdirSync(appApiUsersDir, { recursive: true });
264
- }
265
- const routePath = path.join(appApiUsersDir, "route.ts");
266
- if (!fs.existsSync(routePath)) {
267
- const nextRouteContent = [
268
- 'import { adapters } from "@codexsploitx/schemaapi";',
269
- 'import { usersContract } from "../../../contracts";',
270
- "",
271
- "const handlers = adapters.next.handleContract(usersContract, {",
272
- ' "GET /users/:id": async ({ params }) => {',
273
- " return {",
274
- " id: String(params && params.id),",
275
- ' name: "John Doe",',
276
- " };",
277
- " },",
278
- "});",
279
- "",
280
- "export const GET = handlers.GET;",
281
- "",
282
- ].join("\n");
283
- fs.writeFileSync(routePath, nextRouteContent);
284
- }
285
- }
286
-
287
- const configPath = path.join(cwd, "schemaapi.config.json");
288
- let existingConfig = null;
289
- if (fs.existsSync(configPath)) {
290
- try {
291
- const raw = fs.readFileSync(configPath, "utf8");
292
- existingConfig = JSON.parse(raw);
293
- } catch {
294
- existingConfig = null;
295
- }
296
- }
297
-
298
- const config = Object.assign({}, existingConfig || {}, {
299
- adapter,
300
- contractsDir: existingConfig && existingConfig.contractsDir ? existingConfig.contractsDir : "contracts",
301
- });
302
-
303
- fs.writeFileSync(configPath, JSON.stringify(config, null, 2) + "\n");
304
-
305
- console.log(`Initialized SchemaApi project for adapter: ${adapter}`);
306
- console.log("SchemaApi init completed. Contracts directory: ./contracts");
307
- }
308
-
309
- function main() {
310
- const [command, subcommand] = args;
311
-
312
- if (!command) {
313
- showHelp();
314
- return;
315
- }
316
-
317
- if (command === "generate") {
318
- handleGenerate(subcommand);
319
- return;
320
- }
321
-
322
- if (command === "audit") {
323
- handleAudit();
324
- return;
325
- }
326
-
327
- if (command === "init") {
328
- handleInit(subcommand);
329
- return;
330
- }
331
-
332
- console.error(`Unknown command: ${command}`);
333
- showHelp();
334
- process.exitCode = 1;
335
- }
336
-
337
- main();
@@ -0,0 +1 @@
1
+ export declare function generateDocs(config: any): void;
@@ -0,0 +1 @@
1
+ export declare function handleGenerate(args: string[]): void;
@@ -0,0 +1 @@
1
+ export declare function handleInit(adapterArg?: string): Promise<void>;
@@ -0,0 +1 @@
1
+ export declare function cli(args: string[]): Promise<void>;
@@ -0,0 +1 @@
1
+ export declare function generateContract(name: string): string;
@@ -0,0 +1 @@
1
+ export declare function generateDenoRoute(name: string): string;
@@ -0,0 +1 @@
1
+ export declare function generateExpressRoute(name: string): string;
@@ -0,0 +1 @@
1
+ export declare function generateFastifyRoute(name: string): string;
@@ -0,0 +1 @@
1
+ export declare function generateHapiRoute(name: string): string;
@@ -0,0 +1 @@
1
+ export declare function generateKoaRoute(name: string): string;
@@ -0,0 +1,2 @@
1
+ export declare function generateNestModule(name: string): string;
2
+ export declare function generateNestService(name: string): string;
@@ -0,0 +1 @@
1
+ export declare function generateNextRoute(name: string): string;
@@ -0,0 +1 @@
1
+ export declare function generateRemixRoute(name: string): string;
@@ -0,0 +1,6 @@
1
+ export declare function loadConfig(): any;
2
+ export declare function ensureDir(dir: string): void;
3
+ export declare function writeFile(filePath: string, content: string): void;
4
+ export declare function toPascalCase(str: string): string;
5
+ export declare function toCamelCase(str: string): string;
6
+ export declare function toKebabCase(str: string): string;