@ozanarslan/corpus-cli 0.0.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.
@@ -0,0 +1,324 @@
1
+ import { createRequire } from "node:module";
2
+ import fs from "fs";
3
+ import path from "path";
4
+ //#region \0rolldown/runtime.js
5
+ var __require = /* #__PURE__ */ (() => createRequire(import.meta.url))();
6
+ //#endregion
7
+ //#region src/constants.ts
8
+ const APP_NAME = "Corpus CLI";
9
+ const EXE_NAME = "corpus";
10
+ const CONFIG_FILE_NAME = "corpus.config.ts";
11
+ const GEN_FUNC = `generateApiClient`;
12
+ const NAME_FLAG_HELP = `<name> | [--name, -n] <name>`;
13
+ const LISTEN_PATTERN = /^[ \t]*(?:void|await)?\s*\w+\.listen\(.*?\);.*$/m;
14
+ const MODEL_PATTERN = /\w*Model\w*/;
15
+ const MODEL_TYPE_PATTERN = /^type\s+(\w+)\s*=\s*\w+\.InferModel<[^;]+>;?$/m;
16
+ const INTERFACE_MODEL_PATTERN = /(?:^|\s)interface\s+(\w*Model\w*)\s*\{/;
17
+ const PATTERNS = {
18
+ import: /^import\s.+;$/,
19
+ route: /(?:const\s+\w+\s*=\s*)?new\s+(?:[\w.]+)?Route\(/,
20
+ middleware: /(?:const\s+\w+\s*=\s*)?new\s+(?:[\w.]+)?Middleware\(/,
21
+ controller: /(?:const\s+\w+\s*=\s*)?new\s+(?:[\w.]+)?Controller\(/,
22
+ service: /(?:const\s+\w+\s*=\s*)?new\s+(?:[\w.]+)?Service\(/
23
+ };
24
+ const NEVER_SCHEMAS = /* @__PURE__ */ new Set([
25
+ "type(\\\"never\\\")",
26
+ "type(\"never\")",
27
+ "z.never()",
28
+ "y.mixed().oneOf([undefined] as const)",
29
+ "y.mixed().oneOf([undefined])",
30
+ "this.never",
31
+ "never",
32
+ "undefined",
33
+ "type(\\\"undefined\\\")",
34
+ "type(\"undefined\")",
35
+ "z.undefined()"
36
+ ]);
37
+ //#endregion
38
+ //#region ../utils/is.ts
39
+ const EMPTY = Symbol("empty");
40
+ function isPresent(input) {
41
+ return input !== void 0 && input !== null && input !== EMPTY;
42
+ }
43
+ function isAbsent(input) {
44
+ return !isPresent(input);
45
+ }
46
+ function isObject(input) {
47
+ if (isAbsent(input) || typeof input !== "object" || Array.isArray(input)) return false;
48
+ return Object.getPrototypeOf(input) === Object.prototype;
49
+ }
50
+ function isEmpty(input) {
51
+ if (isAbsent(input)) return true;
52
+ if (typeof input === "string") return input.trim() === "";
53
+ if (typeof input === "number") return input === 0;
54
+ if (isObject(input)) return Object.keys(input).length === 0;
55
+ if (Array.isArray(input)) return input.length === 0;
56
+ return false;
57
+ }
58
+ function isSomeArray(input) {
59
+ return isPresent(input) && Array.isArray(input) && input.length > 0;
60
+ }
61
+ //#endregion
62
+ //#region src/internal/cache.ts
63
+ const map = /* @__PURE__ */ new Map();
64
+ const TWO_MIN = 12e4;
65
+ function cache(key, callback, ttlMs = TWO_MIN) {
66
+ return (...args) => {
67
+ const cacheKey = args.length ? `${key}:${JSON.stringify(args)}` : key;
68
+ const entry = map.get(cacheKey);
69
+ if (entry && Date.now() < entry.expiresAt) return entry.value;
70
+ const value = callback(...args);
71
+ map.set(cacheKey, {
72
+ value,
73
+ expiresAt: Date.now() + ttlMs
74
+ });
75
+ return value;
76
+ };
77
+ }
78
+ //#endregion
79
+ //#region ../utils/assert.ts
80
+ function assertBase(condition, msg) {
81
+ if (!condition) throw new Error(msg);
82
+ }
83
+ function assertPresent(value, msg) {
84
+ if (isAbsent(value)) throw new Error(msg);
85
+ }
86
+ const assert = Object.assign(assertBase, { present: assertPresent });
87
+ //#endregion
88
+ //#region src/internal/converters.ts
89
+ function toPascalCase(key) {
90
+ return key.replace(/[^a-zA-Z0-9]+/g, " ").split(" ").filter(Boolean).map((p) => p.charAt(0).toUpperCase() + p.slice(1)).join("");
91
+ }
92
+ function toCamelCase(key) {
93
+ const parts = key.replace(/([a-z])([A-Z])/g, "$1 $2").replace(/[^a-zA-Z0-9]+/g, " ").split(" ").filter(Boolean);
94
+ if (parts.length === 0) return key;
95
+ const [first, ...rest] = parts;
96
+ return first.toLowerCase() + rest.map((p) => p.charAt(0).toUpperCase() + p.slice(1)).join("");
97
+ }
98
+ function toKebabCase(key) {
99
+ return key.replace(/([a-z])([A-Z])/g, "$1-$2").replace(/[^a-zA-Z0-9]+/g, "-").replace(/^-+|-+$/g, "").toLowerCase();
100
+ }
101
+ function quote(s) {
102
+ return `"${s}"`;
103
+ }
104
+ //#endregion
105
+ //#region src/internal/resolveCwdPath.ts
106
+ function resolveCwdPath(...segments) {
107
+ const joined = segments.map((segment) => typeof segment === "number" ? segment.toString() : segment).filter((segment) => !isEmpty(segment)).flatMap((segment) => segment.split("/")).map((segment) => segment.replace(/^\/+|\/+$/g, "")).filter((segment) => segment.length > 0).join("/");
108
+ return path.resolve(process.cwd(), joined);
109
+ }
110
+ //#endregion
111
+ //#region src/internal/StringBuilder.ts
112
+ var StringBuilder = class {
113
+ complete = "";
114
+ lineCount = 0;
115
+ get currentLine() {
116
+ return this.lineCount;
117
+ }
118
+ inline(s) {
119
+ this.complete += s;
120
+ return this;
121
+ }
122
+ line(input) {
123
+ return typeof input === "number" ? (s) => this.push(" ".repeat(input) + s) : this.push(input);
124
+ }
125
+ get tab() {
126
+ this.push(" ");
127
+ return this;
128
+ }
129
+ push(s) {
130
+ if (this.complete.length === 0) this.complete += s;
131
+ else {
132
+ this.complete += "\n" + s;
133
+ this.lineCount++;
134
+ }
135
+ return this;
136
+ }
137
+ prepend(s) {
138
+ this.complete = s + "\n" + this.complete;
139
+ this.lineCount++;
140
+ return this;
141
+ }
142
+ clear() {
143
+ this.complete = "";
144
+ this.lineCount = 0;
145
+ return this;
146
+ }
147
+ replaceAll(find, change) {
148
+ this.complete = this.complete.replaceAll(find, change);
149
+ return this;
150
+ }
151
+ replace(find, change) {
152
+ this.complete = this.complete.replace(find, change);
153
+ return this;
154
+ }
155
+ replaceByIndex(find, occurrence, change) {
156
+ let i = -1;
157
+ let from = 0;
158
+ for (let n = 0; n <= occurrence; n++) {
159
+ i = this.complete.indexOf(find, from);
160
+ if (i === -1) return this;
161
+ from = i + find.length;
162
+ }
163
+ this.complete = this.complete.slice(0, i) + change + this.complete.slice(i + find.length);
164
+ return this;
165
+ }
166
+ trim() {
167
+ this.complete = this.complete.trim();
168
+ return this;
169
+ }
170
+ slice(start, end) {
171
+ this.complete = this.complete.slice(start, end);
172
+ return this;
173
+ }
174
+ get length() {
175
+ return this.complete.length;
176
+ }
177
+ get isEmpty() {
178
+ return this.complete.length === 0;
179
+ }
180
+ toString() {
181
+ return this.complete;
182
+ }
183
+ };
184
+ //#endregion
185
+ //#region ../utils/logger.ts
186
+ const col = {
187
+ reset: "\x1B[0m",
188
+ green: "\x1B[32m",
189
+ red: "\x1B[31m",
190
+ cyan: "\x1B[36m",
191
+ yellow: "\x1B[33m",
192
+ gray: "\x1B[90m",
193
+ bold: "\x1B[1m",
194
+ magenta: "\x1B[35m",
195
+ blue: "\x1B[34m"
196
+ };
197
+ function strColor(color, str) {
198
+ return col[color] + str + col.reset;
199
+ }
200
+ function makeLogger() {
201
+ const logger = {};
202
+ logger.log = (...a) => console.log(...a);
203
+ logger.bold = (...a) => console.log(col.bold, ...a, col.reset);
204
+ logger.info = (...a) => console.log(strColor("cyan", "i"), ...a);
205
+ logger.success = (...a) => console.log(strColor("green", "✓"), ...a);
206
+ logger.error = (...a) => console.error(strColor("red", "✗"), ...a);
207
+ logger.debug = (...a) => console.log(strColor("gray", "·"), ...a);
208
+ logger.warn = (...a) => console.warn(strColor("yellow", "⚠"), ...a);
209
+ logger.step = (...a) => console.log(strColor("magenta", ">"), ...a);
210
+ return logger;
211
+ }
212
+ function makeNoopLogger() {
213
+ return {
214
+ bold() {},
215
+ log() {},
216
+ info() {},
217
+ success() {},
218
+ debug() {},
219
+ warn() {},
220
+ step() {},
221
+ error() {}
222
+ };
223
+ }
224
+ let active = makeLogger();
225
+ const logger = new Proxy({}, { get(_target, prop) {
226
+ return active[prop];
227
+ } });
228
+ function setLoggerNoop() {
229
+ active = makeNoopLogger();
230
+ }
231
+ function logFatal(...args) {
232
+ if (process.env.NODE_ENV === "test") throw new Error(JSON.stringify(args));
233
+ else {
234
+ logger.error(...args);
235
+ process.exit(1);
236
+ }
237
+ }
238
+ //#endregion
239
+ //#region src/Config/getConfig.ts
240
+ function getDefaultConfig() {
241
+ return {
242
+ silent: false,
243
+ main: "./src/main.ts",
244
+ pkgPath: "@ozanarslan/corpus",
245
+ casing: "pascal",
246
+ validationLibrary: null,
247
+ output: "./src/corpus.gen.ts",
248
+ apiClient: {
249
+ disabled: false,
250
+ exportAs: "CorpusApi",
251
+ useStaticClass: false
252
+ },
253
+ ignoreGlobalPrefix: false,
254
+ defaultMethods: {
255
+ get: {
256
+ propertyKey: "get",
257
+ address: "GET /"
258
+ },
259
+ getByParams: {
260
+ propertyKey: "getByParams",
261
+ address: "GET /:id"
262
+ },
263
+ create: {
264
+ propertyKey: "create",
265
+ address: "POST /"
266
+ },
267
+ update: {
268
+ propertyKey: "update",
269
+ address: "PUT /:id"
270
+ },
271
+ remove: {
272
+ propertyKey: "remove",
273
+ address: "DELETE /:id"
274
+ }
275
+ },
276
+ folderStructure: {
277
+ model: "{resource}/{resource}-model.ts",
278
+ service: "{resource}/{resource}-service.ts",
279
+ controller: "{resource}/{resource}-controller.ts",
280
+ route: "{resource}/{resource}-route.ts"
281
+ },
282
+ exportModelsNamespace: true,
283
+ exportArgsNamespace: true
284
+ };
285
+ }
286
+ function getFileConfig() {
287
+ const extensions = [".ts", ".js"];
288
+ const base = resolveCwdPath(CONFIG_FILE_NAME.replace(".ts", ""));
289
+ const configPath = extensions.map((ext) => base + ext).find(fs.existsSync);
290
+ return configPath ? __require(configPath).default : null;
291
+ }
292
+ const getConfig = cache("getConfig", () => {
293
+ function configFileExists() {
294
+ const filePath = path.resolve(process.cwd(), CONFIG_FILE_NAME);
295
+ return fs.existsSync(filePath);
296
+ }
297
+ const fileConfig = getFileConfig();
298
+ const defaultConfig = getDefaultConfig();
299
+ const config = fileConfig ?? defaultConfig;
300
+ function writeConfigFile(config) {
301
+ const b = new StringBuilder();
302
+ b.line(`import { defineConfig } from "@ozanarslan/corpus-cli/config";`);
303
+ b.line(``);
304
+ b.line(`export default defineConfig({`);
305
+ writeConfigEntries(b, config, 1);
306
+ b.line(`});`);
307
+ const content = b.toString();
308
+ const fpath = path.resolve(process.cwd(), CONFIG_FILE_NAME);
309
+ fs.mkdirSync(path.dirname(fpath), { recursive: true });
310
+ fs.writeFileSync(fpath, content);
311
+ logger.info(`Config written to ${CONFIG_FILE_NAME}`);
312
+ }
313
+ function writeConfigEntries(b, obj, indent) {
314
+ for (const [key, val] of Object.entries(obj)) if (isObject(val)) {
315
+ b.line(indent)(`${key}: {`);
316
+ writeConfigEntries(b, val, indent + 1);
317
+ b.line(indent)(`},`);
318
+ } else b.line(indent)(`${key}: ${typeof val === "string" ? quote(val) : val},`);
319
+ }
320
+ if (!configFileExists()) writeConfigFile(config);
321
+ return config;
322
+ });
323
+ //#endregion
324
+ export { LISTEN_PATTERN as C, NEVER_SCHEMAS as D, NAME_FLAG_HELP as E, PATTERNS as O, INTERFACE_MODEL_PATTERN as S, MODEL_TYPE_PATTERN as T, isPresent as _, setLoggerNoop as a, EXE_NAME as b, quote as c, toPascalCase as d, assert as f, isObject as g, isEmpty as h, logger as i, toCamelCase as l, isAbsent as m, getDefaultConfig as n, StringBuilder as o, cache as p, logFatal as r, resolveCwdPath as s, getConfig as t, toKebabCase as u, isSomeArray as v, MODEL_PATTERN as w, GEN_FUNC as x, APP_NAME as y };