@geekmidas/cli 0.0.25 → 0.1.0

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.
Files changed (142) hide show
  1. package/FUNCTION_CRON_SUPPORT.md +266 -0
  2. package/README.md +21 -4
  3. package/dist/CronGenerator-ClbRcmz_.mjs +53 -0
  4. package/dist/CronGenerator-ClbRcmz_.mjs.map +1 -0
  5. package/dist/CronGenerator-Ctl4USy4.cjs +59 -0
  6. package/dist/CronGenerator-Ctl4USy4.cjs.map +1 -0
  7. package/dist/EndpointGenerator-Dj7AumHi.cjs +164 -0
  8. package/dist/EndpointGenerator-Dj7AumHi.cjs.map +1 -0
  9. package/dist/EndpointGenerator-uBA1ixUw.mjs +158 -0
  10. package/dist/EndpointGenerator-uBA1ixUw.mjs.map +1 -0
  11. package/dist/FunctionGenerator-DN681IUn.cjs +58 -0
  12. package/dist/FunctionGenerator-DN681IUn.cjs.map +1 -0
  13. package/dist/FunctionGenerator-crAa-JC7.mjs +52 -0
  14. package/dist/FunctionGenerator-crAa-JC7.mjs.map +1 -0
  15. package/dist/Generator-C3tYSTQY.cjs +47 -0
  16. package/dist/Generator-C3tYSTQY.cjs.map +1 -0
  17. package/dist/Generator-CDt4pB3W.mjs +41 -0
  18. package/dist/Generator-CDt4pB3W.mjs.map +1 -0
  19. package/dist/__tests__/config.spec.cjs +98 -0
  20. package/dist/__tests__/config.spec.cjs.map +1 -0
  21. package/dist/__tests__/config.spec.mjs +97 -0
  22. package/dist/__tests__/config.spec.mjs.map +1 -0
  23. package/dist/__tests__/test-helpers.cjs +14 -0
  24. package/dist/__tests__/test-helpers.mjs +4 -0
  25. package/dist/build/__tests__/index-new.spec.cjs +286 -0
  26. package/dist/build/__tests__/index-new.spec.cjs.map +1 -0
  27. package/dist/build/__tests__/index-new.spec.mjs +285 -0
  28. package/dist/build/__tests__/index-new.spec.mjs.map +1 -0
  29. package/dist/build/index.cjs +11 -0
  30. package/dist/build/index.mjs +11 -0
  31. package/dist/build/manifests.cjs +3 -0
  32. package/dist/build/manifests.mjs +3 -0
  33. package/dist/build/providerResolver.cjs +5 -0
  34. package/dist/build/providerResolver.mjs +3 -0
  35. package/dist/build/types.cjs +0 -0
  36. package/dist/build/types.mjs +0 -0
  37. package/dist/build-BZdwxCLW.mjs +64 -0
  38. package/dist/build-BZdwxCLW.mjs.map +1 -0
  39. package/dist/build-BfQFnU5-.cjs +70 -0
  40. package/dist/build-BfQFnU5-.cjs.map +1 -0
  41. package/dist/{chunk-CUT6urMc.cjs → chunk-CsX-DzYB.cjs} +12 -0
  42. package/dist/config-CXxYmz_o.mjs +30 -0
  43. package/dist/config-CXxYmz_o.mjs.map +1 -0
  44. package/dist/config-RcNESK0T.cjs +36 -0
  45. package/dist/config-RcNESK0T.cjs.map +1 -0
  46. package/dist/config.cjs +1 -1
  47. package/dist/config.mjs +1 -1
  48. package/dist/esm-9eeZntth.mjs +3777 -0
  49. package/dist/esm-9eeZntth.mjs.map +1 -0
  50. package/dist/esm-Crmo4h9t.cjs +4392 -0
  51. package/dist/esm-Crmo4h9t.cjs.map +1 -0
  52. package/dist/esm-CsJbr7gi.mjs +3 -0
  53. package/dist/esm-w09tAC4l.cjs +8 -0
  54. package/dist/generators/CronGenerator.cjs +4 -0
  55. package/dist/generators/CronGenerator.mjs +4 -0
  56. package/dist/generators/EndpointGenerator.cjs +4 -0
  57. package/dist/generators/EndpointGenerator.mjs +4 -0
  58. package/dist/generators/FunctionGenerator.cjs +4 -0
  59. package/dist/generators/FunctionGenerator.mjs +4 -0
  60. package/dist/generators/Generator.cjs +3 -0
  61. package/dist/generators/Generator.mjs +3 -0
  62. package/dist/generators/__tests__/CronGenerator.spec.cjs +216 -0
  63. package/dist/generators/__tests__/CronGenerator.spec.cjs.map +1 -0
  64. package/dist/generators/__tests__/CronGenerator.spec.mjs +215 -0
  65. package/dist/generators/__tests__/CronGenerator.spec.mjs.map +1 -0
  66. package/dist/generators/__tests__/EndpointGenerator.spec.cjs +182 -0
  67. package/dist/generators/__tests__/EndpointGenerator.spec.cjs.map +1 -0
  68. package/dist/generators/__tests__/EndpointGenerator.spec.mjs +181 -0
  69. package/dist/generators/__tests__/EndpointGenerator.spec.mjs.map +1 -0
  70. package/dist/generators/__tests__/FunctionGenerator.spec.cjs +152 -0
  71. package/dist/generators/__tests__/FunctionGenerator.spec.cjs.map +1 -0
  72. package/dist/generators/__tests__/FunctionGenerator.spec.mjs +151 -0
  73. package/dist/generators/__tests__/FunctionGenerator.spec.mjs.map +1 -0
  74. package/dist/generators/index.cjs +10 -0
  75. package/dist/generators/index.mjs +7 -0
  76. package/dist/generators-CsLujGXs.mjs +0 -0
  77. package/dist/generators-_pY7sHy1.cjs +0 -0
  78. package/dist/index.cjs +68 -26
  79. package/dist/index.cjs.map +1 -0
  80. package/dist/index.mjs +67 -25
  81. package/dist/index.mjs.map +1 -0
  82. package/dist/manifests-BTtfDMX8.cjs +26 -0
  83. package/dist/manifests-BTtfDMX8.cjs.map +1 -0
  84. package/dist/manifests-HX4z4kkz.mjs +20 -0
  85. package/dist/manifests-HX4z4kkz.mjs.map +1 -0
  86. package/dist/{openapi-CksVdkh2.mjs → openapi-BivnatiC.mjs} +8 -6
  87. package/dist/openapi-BivnatiC.mjs.map +1 -0
  88. package/dist/{openapi-D4QQJUPY.cjs → openapi-DW-qF3oW.cjs} +9 -7
  89. package/dist/openapi-DW-qF3oW.cjs.map +1 -0
  90. package/dist/{openapi-react-query-C1JLYUOs.cjs → openapi-react-query-J0BzBHhN.cjs} +4 -3
  91. package/dist/openapi-react-query-J0BzBHhN.cjs.map +1 -0
  92. package/dist/{openapi-react-query-DpT3XHFC.mjs → openapi-react-query-lgS7AVEz.mjs} +3 -2
  93. package/dist/openapi-react-query-lgS7AVEz.mjs.map +1 -0
  94. package/dist/openapi-react-query.cjs +1 -1
  95. package/dist/openapi-react-query.mjs +1 -1
  96. package/dist/openapi.cjs +4 -3
  97. package/dist/openapi.mjs +4 -3
  98. package/dist/providerResolver-B_TjNF0_.mjs +96 -0
  99. package/dist/providerResolver-B_TjNF0_.mjs.map +1 -0
  100. package/dist/providerResolver-Cs-0YCaP.cjs +114 -0
  101. package/dist/providerResolver-Cs-0YCaP.cjs.map +1 -0
  102. package/dist/test-helpers-ARd8GDgx.cjs +199 -0
  103. package/dist/test-helpers-ARd8GDgx.cjs.map +1 -0
  104. package/dist/test-helpers-DdVBk23F.mjs +133 -0
  105. package/dist/test-helpers-DdVBk23F.mjs.map +1 -0
  106. package/examples/cron-example.ts +45 -0
  107. package/examples/function-example.ts +40 -0
  108. package/examples/gkm.config.json +22 -0
  109. package/examples/gkm.minimal.config.json +7 -0
  110. package/examples/gkm.production.config.json +27 -0
  111. package/package.json +35 -14
  112. package/src/__tests__/config.spec.ts +110 -0
  113. package/src/__tests__/test-helpers.ts +178 -0
  114. package/src/build/__tests__/index-new.spec.ts +578 -0
  115. package/src/build/index.ts +136 -0
  116. package/src/build/manifests.ts +32 -0
  117. package/src/build/providerResolver.ts +184 -0
  118. package/src/build/types.ts +37 -0
  119. package/src/config.ts +14 -6
  120. package/src/generators/CronGenerator.ts +97 -0
  121. package/src/generators/EndpointGenerator.ts +290 -0
  122. package/src/generators/FunctionGenerator.ts +96 -0
  123. package/src/generators/Generator.ts +95 -0
  124. package/src/generators/__tests__/CronGenerator.spec.ts +445 -0
  125. package/src/generators/__tests__/EndpointGenerator.spec.ts +372 -0
  126. package/src/generators/__tests__/FunctionGenerator.spec.ts +257 -0
  127. package/src/generators/index.ts +8 -0
  128. package/src/index.ts +57 -22
  129. package/src/openapi.ts +4 -3
  130. package/src/types.ts +73 -2
  131. package/dist/build-BTggTCYL.cjs +0 -176
  132. package/dist/build-Ca4P6_lY.mjs +0 -170
  133. package/dist/build.cjs +0 -5
  134. package/dist/build.mjs +0 -5
  135. package/dist/config-BNqUMsvc.cjs +0 -24
  136. package/dist/config-BciAdY6_.mjs +0 -18
  137. package/dist/loadEndpoints-BBIavB9h.cjs +0 -37
  138. package/dist/loadEndpoints-DAZ53Og2.mjs +0 -31
  139. package/dist/loadEndpoints.cjs +0 -3
  140. package/dist/loadEndpoints.mjs +0 -3
  141. package/src/build.ts +0 -305
  142. package/src/loadEndpoints.ts +0 -48
@@ -0,0 +1,199 @@
1
+ const require_chunk = require('./chunk-CsX-DzYB.cjs');
2
+ const require_esm = require('./esm-Crmo4h9t.cjs');
3
+ const node_fs_promises = require_chunk.__toESM(require("node:fs/promises"));
4
+ const node_path = require_chunk.__toESM(require("node:path"));
5
+ const __geekmidas_api_constructs = require_chunk.__toESM(require("@geekmidas/api/constructs"));
6
+ const __geekmidas_api_server = require_chunk.__toESM(require("@geekmidas/api/server"));
7
+ const node_os = require_chunk.__toESM(require("node:os"));
8
+
9
+ //#region src/__tests__/test-helpers.ts
10
+ /**
11
+ * Creates a temporary directory for testing
12
+ */
13
+ async function createTempDir(prefix = "cli-test-") {
14
+ const tempPath = (0, node_path.join)((0, node_os.tmpdir)(), `${prefix}${Date.now()}-${Math.random().toString(36).slice(2)}`);
15
+ await (0, node_fs_promises.mkdir)(tempPath, { recursive: true });
16
+ return tempPath;
17
+ }
18
+ /**
19
+ * Cleans up a directory
20
+ */
21
+ async function cleanupDir(path) {
22
+ try {
23
+ await (0, node_fs_promises.rm)(path, {
24
+ recursive: true,
25
+ force: true
26
+ });
27
+ } catch (error) {}
28
+ }
29
+ /**
30
+ * Creates a test file with content
31
+ */
32
+ async function createTestFile(dir, filename, content) {
33
+ const filePath = (0, node_path.join)(dir, filename);
34
+ await (0, node_fs_promises.mkdir)((0, node_path.dirname)(filePath), { recursive: true });
35
+ await (0, node_fs_promises.writeFile)(filePath, content);
36
+ return filePath;
37
+ }
38
+ /**
39
+ * Creates a mock endpoint file with real endpoint construct
40
+ */
41
+ async function createMockEndpointFile(dir, filename, exportName, path = "/test", method = "GET") {
42
+ const content = `
43
+ import { e } from '@geekmidas/api/server';
44
+ import { z } from 'zod';
45
+
46
+ export const ${exportName} = e
47
+ .${method.toLowerCase()}('${path}')
48
+ .output(z.object({ message: z.string() }))
49
+ .handle(async () => ({ message: 'Hello from ${exportName}' }));
50
+ `;
51
+ return createTestFile(dir, filename, content);
52
+ }
53
+ /**
54
+ * Creates a mock function file with real function construct
55
+ */
56
+ async function createMockFunctionFile(dir, filename, exportName, timeout = 30) {
57
+ const content = `
58
+ import { FunctionBuilder } from '@geekmidas/api/constructs';
59
+ import { z } from 'zod';
60
+
61
+ export const ${exportName} = new FunctionBuilder()
62
+ .input(z.object({ name: z.string() }))
63
+ .output(z.object({ greeting: z.string() }))
64
+ .timeout(${timeout})
65
+ .handle(async ({ input }) => ({ greeting: \`Hello, \${input.name}!\` }));
66
+ `;
67
+ return createTestFile(dir, filename, content);
68
+ }
69
+ /**
70
+ * Creates a mock cron file with real cron construct
71
+ */
72
+ async function createMockCronFile(dir, filename, exportName, schedule = "rate(1 hour)") {
73
+ const content = `
74
+ import { CronBuilder } from '@geekmidas/api/constructs';
75
+ import { z } from 'zod';
76
+
77
+ export const ${exportName} = new CronBuilder()
78
+ .schedule('${schedule}')
79
+ .output(z.object({ processed: z.number() }))
80
+ .handle(async () => {
81
+ console.log('Running cron job: ${exportName}');
82
+ return { processed: 10 };
83
+ });
84
+ `;
85
+ return createTestFile(dir, filename, content);
86
+ }
87
+ /**
88
+ * Helper functions to create real constructs for testing
89
+ */
90
+ function createTestEndpoint(path, method = "GET") {
91
+ const m = method.toLowerCase();
92
+ const builder = __geekmidas_api_server.e[m](path);
93
+ builder.output(require_esm.objectType({ message: require_esm.stringType() }));
94
+ return builder.handle(async () => ({ message: `Hello from ${path}` }));
95
+ }
96
+ function createTestFunction(timeout = 30) {
97
+ const builder = new __geekmidas_api_constructs.FunctionBuilder();
98
+ builder.input(require_esm.objectType({ name: require_esm.stringType() }));
99
+ builder.output(require_esm.objectType({ greeting: require_esm.stringType() }));
100
+ builder.timeout(timeout);
101
+ return builder.handle(async ({ input }) => ({ greeting: `Hello, ${input.name}!` }));
102
+ }
103
+ function createTestCron(schedule = "rate(1 hour)", timeout = 30) {
104
+ const builder = new __geekmidas_api_constructs.CronBuilder();
105
+ builder.schedule(schedule);
106
+ builder.output(require_esm.objectType({ processed: require_esm.numberType() }));
107
+ builder.timeout(timeout);
108
+ return builder.handle(async () => {
109
+ return { processed: 10 };
110
+ });
111
+ }
112
+ /**
113
+ * Creates a mock build context
114
+ */
115
+ function createMockBuildContext() {
116
+ return {
117
+ envParserPath: "./env",
118
+ envParserImportPattern: "envParser",
119
+ loggerPath: "./logger",
120
+ loggerImportPattern: "logger"
121
+ };
122
+ }
123
+ /**
124
+ * Waits for a condition to be true
125
+ */
126
+ async function waitFor(condition, timeout = 5e3, interval = 100) {
127
+ const start = Date.now();
128
+ while (!condition() && Date.now() - start < timeout) await new Promise((resolve) => setTimeout(resolve, interval));
129
+ if (!condition()) throw new Error("Timeout waiting for condition");
130
+ }
131
+
132
+ //#endregion
133
+ Object.defineProperty(exports, 'cleanupDir', {
134
+ enumerable: true,
135
+ get: function () {
136
+ return cleanupDir;
137
+ }
138
+ });
139
+ Object.defineProperty(exports, 'createMockBuildContext', {
140
+ enumerable: true,
141
+ get: function () {
142
+ return createMockBuildContext;
143
+ }
144
+ });
145
+ Object.defineProperty(exports, 'createMockCronFile', {
146
+ enumerable: true,
147
+ get: function () {
148
+ return createMockCronFile;
149
+ }
150
+ });
151
+ Object.defineProperty(exports, 'createMockEndpointFile', {
152
+ enumerable: true,
153
+ get: function () {
154
+ return createMockEndpointFile;
155
+ }
156
+ });
157
+ Object.defineProperty(exports, 'createMockFunctionFile', {
158
+ enumerable: true,
159
+ get: function () {
160
+ return createMockFunctionFile;
161
+ }
162
+ });
163
+ Object.defineProperty(exports, 'createTempDir', {
164
+ enumerable: true,
165
+ get: function () {
166
+ return createTempDir;
167
+ }
168
+ });
169
+ Object.defineProperty(exports, 'createTestCron', {
170
+ enumerable: true,
171
+ get: function () {
172
+ return createTestCron;
173
+ }
174
+ });
175
+ Object.defineProperty(exports, 'createTestEndpoint', {
176
+ enumerable: true,
177
+ get: function () {
178
+ return createTestEndpoint;
179
+ }
180
+ });
181
+ Object.defineProperty(exports, 'createTestFile', {
182
+ enumerable: true,
183
+ get: function () {
184
+ return createTestFile;
185
+ }
186
+ });
187
+ Object.defineProperty(exports, 'createTestFunction', {
188
+ enumerable: true,
189
+ get: function () {
190
+ return createTestFunction;
191
+ }
192
+ });
193
+ Object.defineProperty(exports, 'waitFor', {
194
+ enumerable: true,
195
+ get: function () {
196
+ return waitFor;
197
+ }
198
+ });
199
+ //# sourceMappingURL=test-helpers-ARd8GDgx.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"test-helpers-ARd8GDgx.cjs","names":["path: string","dir: string","filename: string","content: string","exportName: string","method: string","method: HttpMethod","timeout: number","FunctionBuilder","schedule: ScheduleExpression","CronBuilder","condition: () => boolean"],"sources":["../src/__tests__/test-helpers.ts"],"sourcesContent":["import { mkdir, rm, writeFile } from 'node:fs/promises';\nimport { tmpdir } from 'node:os';\nimport { join } from 'node:path';\nimport {\n CronBuilder,\n FunctionBuilder,\n type ScheduleExpression,\n} from '@geekmidas/api/constructs';\nimport { e } from '@geekmidas/api/server';\nimport { z } from 'zod';\n\n/**\n * Creates a temporary directory for testing\n */\nexport async function createTempDir(prefix = 'cli-test-'): Promise<string> {\n const tempPath = join(\n tmpdir(),\n `${prefix}${Date.now()}-${Math.random().toString(36).slice(2)}`,\n );\n await mkdir(tempPath, { recursive: true });\n return tempPath;\n}\n\n/**\n * Cleans up a directory\n */\nexport async function cleanupDir(path: string): Promise<void> {\n try {\n await rm(path, { recursive: true, force: true });\n } catch (error) {\n // Ignore errors during cleanup\n }\n}\n\n/**\n * Creates a test file with content\n */\nexport async function createTestFile(\n dir: string,\n filename: string,\n content: string,\n): Promise<string> {\n const filePath = join(dir, filename);\n await mkdir(dirname(filePath), { recursive: true });\n await writeFile(filePath, content);\n return filePath;\n}\n\n/**\n * Creates a mock endpoint file with real endpoint construct\n */\nexport async function createMockEndpointFile(\n dir: string,\n filename: string,\n exportName: string,\n path: string = '/test',\n method: string = 'GET',\n): Promise<string> {\n const content = `\nimport { e } from '@geekmidas/api/server';\nimport { z } from 'zod';\n\nexport const ${exportName} = e\n .${method.toLowerCase()}('${path}')\n .output(z.object({ message: z.string() }))\n .handle(async () => ({ message: 'Hello from ${exportName}' }));\n`;\n return createTestFile(dir, filename, content);\n}\n\n/**\n * Creates a mock function file with real function construct\n */\nexport async function createMockFunctionFile(\n dir: string,\n filename: string,\n exportName: string,\n timeout = 30,\n): Promise<string> {\n const content = `\nimport { FunctionBuilder } from '@geekmidas/api/constructs';\nimport { z } from 'zod';\n\nexport const ${exportName} = new FunctionBuilder()\n .input(z.object({ name: z.string() }))\n .output(z.object({ greeting: z.string() }))\n .timeout(${timeout})\n .handle(async ({ input }) => ({ greeting: \\`Hello, \\${input.name}!\\` }));\n`;\n return createTestFile(dir, filename, content);\n}\n\n/**\n * Creates a mock cron file with real cron construct\n */\nexport async function createMockCronFile(\n dir: string,\n filename: string,\n exportName: string,\n schedule = 'rate(1 hour)',\n): Promise<string> {\n const content = `\nimport { CronBuilder } from '@geekmidas/api/constructs';\nimport { z } from 'zod';\n\nexport const ${exportName} = new CronBuilder()\n .schedule('${schedule}')\n .output(z.object({ processed: z.number() }))\n .handle(async () => {\n console.log('Running cron job: ${exportName}');\n return { processed: 10 };\n });\n`;\n return createTestFile(dir, filename, content);\n}\n\n/**\n * Helper functions to create real constructs for testing\n */\nexport function createTestEndpoint(path: string, method: HttpMethod = 'GET') {\n const m = method.toLowerCase() as Lowercase<HttpMethod>;\n const builder = e[m](path);\n builder.output(z.object({ message: z.string() }));\n return builder.handle(async () => ({ message: `Hello from ${path}` }));\n}\n\nexport function createTestFunction(timeout: number = 30) {\n const builder = new FunctionBuilder();\n builder.input(z.object({ name: z.string() }));\n builder.output(z.object({ greeting: z.string() }));\n builder.timeout(timeout);\n return builder.handle(async ({ input }: any) => ({ greeting: `Hello, ${input.name}!` }));\n}\n\nexport function createTestCron(\n schedule: ScheduleExpression = 'rate(1 hour)',\n timeout: number = 30,\n) {\n const builder = new CronBuilder();\n builder.schedule(schedule);\n builder.output(z.object({ processed: z.number() }));\n builder.timeout(timeout);\n return builder.handle(async () => {\n return { processed: 10 };\n });\n}\n\n/**\n * Creates a mock build context\n */\nexport function createMockBuildContext() {\n return {\n envParserPath: './env',\n envParserImportPattern: 'envParser',\n loggerPath: './logger',\n loggerImportPattern: 'logger',\n };\n}\n\n/**\n * Waits for a condition to be true\n */\nexport async function waitFor(\n condition: () => boolean,\n timeout = 5000,\n interval = 100,\n): Promise<void> {\n const start = Date.now();\n while (!condition() && Date.now() - start < timeout) {\n await new Promise((resolve) => setTimeout(resolve, interval));\n }\n if (!condition()) {\n throw new Error('Timeout waiting for condition');\n }\n}\n\nimport { dirname } from 'node:path';\nimport type { HttpMethod } from '../../../api/src/constructs/types';\n"],"mappings":";;;;;;;;;;;;AAcA,eAAsB,cAAc,SAAS,aAA8B;CACzE,MAAM,WAAW,oBACf,qBAAQ,GACP,EAAE,OAAO,EAAE,KAAK,KAAK,CAAC,GAAG,KAAK,QAAQ,CAAC,SAAS,GAAG,CAAC,MAAM,EAAE,CAAC,EAC/D;AACD,OAAM,4BAAM,UAAU,EAAE,WAAW,KAAM,EAAC;AAC1C,QAAO;AACR;;;;AAKD,eAAsB,WAAWA,MAA6B;AAC5D,KAAI;AACF,QAAM,yBAAG,MAAM;GAAE,WAAW;GAAM,OAAO;EAAM,EAAC;CACjD,SAAQ,OAAO,CAEf;AACF;;;;AAKD,eAAsB,eACpBC,KACAC,UACAC,SACiB;CACjB,MAAM,WAAW,oBAAK,KAAK,SAAS;AACpC,OAAM,4BAAM,uBAAQ,SAAS,EAAE,EAAE,WAAW,KAAM,EAAC;AACnD,OAAM,gCAAU,UAAU,QAAQ;AAClC,QAAO;AACR;;;;AAKD,eAAsB,uBACpBF,KACAC,UACAE,YACAJ,OAAe,SACfK,SAAiB,OACA;CACjB,MAAM,WAAW;;;;eAIJ,WAAW;KACrB,OAAO,aAAa,CAAC,IAAI,KAAK;;gDAEa,WAAW;;AAEzD,QAAO,eAAe,KAAK,UAAU,QAAQ;AAC9C;;;;AAKD,eAAsB,uBACpBJ,KACAC,UACAE,YACA,UAAU,IACO;CACjB,MAAM,WAAW;;;;eAIJ,WAAW;;;aAGb,QAAQ;;;AAGnB,QAAO,eAAe,KAAK,UAAU,QAAQ;AAC9C;;;;AAKD,eAAsB,mBACpBH,KACAC,UACAE,YACA,WAAW,gBACM;CACjB,MAAM,WAAW;;;;eAIJ,WAAW;eACX,SAAS;;;qCAGa,WAAW;;;;AAI9C,QAAO,eAAe,KAAK,UAAU,QAAQ;AAC9C;;;;AAKD,SAAgB,mBAAmBJ,MAAcM,SAAqB,OAAO;CAC3E,MAAM,IAAI,OAAO,aAAa;CAC9B,MAAM,UAAU,yBAAE,GAAG,KAAK;AAC1B,SAAQ,OAAO,uBAAS,EAAE,SAAS,wBAAU,CAAE,EAAC,CAAC;AACjD,QAAO,QAAQ,OAAO,aAAa,EAAE,UAAU,aAAa,KAAK,EAAG,GAAE;AACvE;AAED,SAAgB,mBAAmBC,UAAkB,IAAI;CACvD,MAAM,UAAU,IAAIC;AACpB,SAAQ,MAAM,uBAAS,EAAE,MAAM,wBAAU,CAAE,EAAC,CAAC;AAC7C,SAAQ,OAAO,uBAAS,EAAE,UAAU,wBAAU,CAAE,EAAC,CAAC;AAClD,SAAQ,QAAQ,QAAQ;AACxB,QAAO,QAAQ,OAAO,OAAO,EAAE,OAAY,MAAM,EAAE,WAAW,SAAS,MAAM,KAAK,GAAI,GAAE;AACzF;AAED,SAAgB,eACdC,WAA+B,gBAC/BF,UAAkB,IAClB;CACA,MAAM,UAAU,IAAIG;AACpB,SAAQ,SAAS,SAAS;AAC1B,SAAQ,OAAO,uBAAS,EAAE,WAAW,wBAAU,CAAE,EAAC,CAAC;AACnD,SAAQ,QAAQ,QAAQ;AACxB,QAAO,QAAQ,OAAO,YAAY;AAChC,SAAO,EAAE,WAAW,GAAI;CACzB,EAAC;AACH;;;;AAKD,SAAgB,yBAAyB;AACvC,QAAO;EACL,eAAe;EACf,wBAAwB;EACxB,YAAY;EACZ,qBAAqB;CACtB;AACF;;;;AAKD,eAAsB,QACpBC,WACA,UAAU,KACV,WAAW,KACI;CACf,MAAM,QAAQ,KAAK,KAAK;AACxB,SAAQ,WAAW,IAAI,KAAK,KAAK,GAAG,QAAQ,QAC1C,OAAM,IAAI,QAAQ,CAAC,YAAY,WAAW,SAAS,SAAS;AAE9D,MAAK,WAAW,CACd,OAAM,IAAI,MAAM;AAEnB"}
@@ -0,0 +1,133 @@
1
+ import { numberType, objectType, stringType } from "./esm-9eeZntth.mjs";
2
+ import { mkdir, rm, writeFile } from "node:fs/promises";
3
+ import { dirname, join } from "node:path";
4
+ import { CronBuilder, FunctionBuilder } from "@geekmidas/api/constructs";
5
+ import { e } from "@geekmidas/api/server";
6
+ import { tmpdir } from "node:os";
7
+
8
+ //#region src/__tests__/test-helpers.ts
9
+ /**
10
+ * Creates a temporary directory for testing
11
+ */
12
+ async function createTempDir(prefix = "cli-test-") {
13
+ const tempPath = join(tmpdir(), `${prefix}${Date.now()}-${Math.random().toString(36).slice(2)}`);
14
+ await mkdir(tempPath, { recursive: true });
15
+ return tempPath;
16
+ }
17
+ /**
18
+ * Cleans up a directory
19
+ */
20
+ async function cleanupDir(path) {
21
+ try {
22
+ await rm(path, {
23
+ recursive: true,
24
+ force: true
25
+ });
26
+ } catch (error) {}
27
+ }
28
+ /**
29
+ * Creates a test file with content
30
+ */
31
+ async function createTestFile(dir, filename, content) {
32
+ const filePath = join(dir, filename);
33
+ await mkdir(dirname(filePath), { recursive: true });
34
+ await writeFile(filePath, content);
35
+ return filePath;
36
+ }
37
+ /**
38
+ * Creates a mock endpoint file with real endpoint construct
39
+ */
40
+ async function createMockEndpointFile(dir, filename, exportName, path = "/test", method = "GET") {
41
+ const content = `
42
+ import { e } from '@geekmidas/api/server';
43
+ import { z } from 'zod';
44
+
45
+ export const ${exportName} = e
46
+ .${method.toLowerCase()}('${path}')
47
+ .output(z.object({ message: z.string() }))
48
+ .handle(async () => ({ message: 'Hello from ${exportName}' }));
49
+ `;
50
+ return createTestFile(dir, filename, content);
51
+ }
52
+ /**
53
+ * Creates a mock function file with real function construct
54
+ */
55
+ async function createMockFunctionFile(dir, filename, exportName, timeout = 30) {
56
+ const content = `
57
+ import { FunctionBuilder } from '@geekmidas/api/constructs';
58
+ import { z } from 'zod';
59
+
60
+ export const ${exportName} = new FunctionBuilder()
61
+ .input(z.object({ name: z.string() }))
62
+ .output(z.object({ greeting: z.string() }))
63
+ .timeout(${timeout})
64
+ .handle(async ({ input }) => ({ greeting: \`Hello, \${input.name}!\` }));
65
+ `;
66
+ return createTestFile(dir, filename, content);
67
+ }
68
+ /**
69
+ * Creates a mock cron file with real cron construct
70
+ */
71
+ async function createMockCronFile(dir, filename, exportName, schedule = "rate(1 hour)") {
72
+ const content = `
73
+ import { CronBuilder } from '@geekmidas/api/constructs';
74
+ import { z } from 'zod';
75
+
76
+ export const ${exportName} = new CronBuilder()
77
+ .schedule('${schedule}')
78
+ .output(z.object({ processed: z.number() }))
79
+ .handle(async () => {
80
+ console.log('Running cron job: ${exportName}');
81
+ return { processed: 10 };
82
+ });
83
+ `;
84
+ return createTestFile(dir, filename, content);
85
+ }
86
+ /**
87
+ * Helper functions to create real constructs for testing
88
+ */
89
+ function createTestEndpoint(path, method = "GET") {
90
+ const m = method.toLowerCase();
91
+ const builder = e[m](path);
92
+ builder.output(objectType({ message: stringType() }));
93
+ return builder.handle(async () => ({ message: `Hello from ${path}` }));
94
+ }
95
+ function createTestFunction(timeout = 30) {
96
+ const builder = new FunctionBuilder();
97
+ builder.input(objectType({ name: stringType() }));
98
+ builder.output(objectType({ greeting: stringType() }));
99
+ builder.timeout(timeout);
100
+ return builder.handle(async ({ input }) => ({ greeting: `Hello, ${input.name}!` }));
101
+ }
102
+ function createTestCron(schedule = "rate(1 hour)", timeout = 30) {
103
+ const builder = new CronBuilder();
104
+ builder.schedule(schedule);
105
+ builder.output(objectType({ processed: numberType() }));
106
+ builder.timeout(timeout);
107
+ return builder.handle(async () => {
108
+ return { processed: 10 };
109
+ });
110
+ }
111
+ /**
112
+ * Creates a mock build context
113
+ */
114
+ function createMockBuildContext() {
115
+ return {
116
+ envParserPath: "./env",
117
+ envParserImportPattern: "envParser",
118
+ loggerPath: "./logger",
119
+ loggerImportPattern: "logger"
120
+ };
121
+ }
122
+ /**
123
+ * Waits for a condition to be true
124
+ */
125
+ async function waitFor(condition, timeout = 5e3, interval = 100) {
126
+ const start = Date.now();
127
+ while (!condition() && Date.now() - start < timeout) await new Promise((resolve) => setTimeout(resolve, interval));
128
+ if (!condition()) throw new Error("Timeout waiting for condition");
129
+ }
130
+
131
+ //#endregion
132
+ export { cleanupDir, createMockBuildContext, createMockCronFile, createMockEndpointFile, createMockFunctionFile, createTempDir, createTestCron, createTestEndpoint, createTestFile, createTestFunction, waitFor };
133
+ //# sourceMappingURL=test-helpers-DdVBk23F.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"test-helpers-DdVBk23F.mjs","names":["path: string","dir: string","filename: string","content: string","exportName: string","method: string","method: HttpMethod","timeout: number","schedule: ScheduleExpression","condition: () => boolean"],"sources":["../src/__tests__/test-helpers.ts"],"sourcesContent":["import { mkdir, rm, writeFile } from 'node:fs/promises';\nimport { tmpdir } from 'node:os';\nimport { join } from 'node:path';\nimport {\n CronBuilder,\n FunctionBuilder,\n type ScheduleExpression,\n} from '@geekmidas/api/constructs';\nimport { e } from '@geekmidas/api/server';\nimport { z } from 'zod';\n\n/**\n * Creates a temporary directory for testing\n */\nexport async function createTempDir(prefix = 'cli-test-'): Promise<string> {\n const tempPath = join(\n tmpdir(),\n `${prefix}${Date.now()}-${Math.random().toString(36).slice(2)}`,\n );\n await mkdir(tempPath, { recursive: true });\n return tempPath;\n}\n\n/**\n * Cleans up a directory\n */\nexport async function cleanupDir(path: string): Promise<void> {\n try {\n await rm(path, { recursive: true, force: true });\n } catch (error) {\n // Ignore errors during cleanup\n }\n}\n\n/**\n * Creates a test file with content\n */\nexport async function createTestFile(\n dir: string,\n filename: string,\n content: string,\n): Promise<string> {\n const filePath = join(dir, filename);\n await mkdir(dirname(filePath), { recursive: true });\n await writeFile(filePath, content);\n return filePath;\n}\n\n/**\n * Creates a mock endpoint file with real endpoint construct\n */\nexport async function createMockEndpointFile(\n dir: string,\n filename: string,\n exportName: string,\n path: string = '/test',\n method: string = 'GET',\n): Promise<string> {\n const content = `\nimport { e } from '@geekmidas/api/server';\nimport { z } from 'zod';\n\nexport const ${exportName} = e\n .${method.toLowerCase()}('${path}')\n .output(z.object({ message: z.string() }))\n .handle(async () => ({ message: 'Hello from ${exportName}' }));\n`;\n return createTestFile(dir, filename, content);\n}\n\n/**\n * Creates a mock function file with real function construct\n */\nexport async function createMockFunctionFile(\n dir: string,\n filename: string,\n exportName: string,\n timeout = 30,\n): Promise<string> {\n const content = `\nimport { FunctionBuilder } from '@geekmidas/api/constructs';\nimport { z } from 'zod';\n\nexport const ${exportName} = new FunctionBuilder()\n .input(z.object({ name: z.string() }))\n .output(z.object({ greeting: z.string() }))\n .timeout(${timeout})\n .handle(async ({ input }) => ({ greeting: \\`Hello, \\${input.name}!\\` }));\n`;\n return createTestFile(dir, filename, content);\n}\n\n/**\n * Creates a mock cron file with real cron construct\n */\nexport async function createMockCronFile(\n dir: string,\n filename: string,\n exportName: string,\n schedule = 'rate(1 hour)',\n): Promise<string> {\n const content = `\nimport { CronBuilder } from '@geekmidas/api/constructs';\nimport { z } from 'zod';\n\nexport const ${exportName} = new CronBuilder()\n .schedule('${schedule}')\n .output(z.object({ processed: z.number() }))\n .handle(async () => {\n console.log('Running cron job: ${exportName}');\n return { processed: 10 };\n });\n`;\n return createTestFile(dir, filename, content);\n}\n\n/**\n * Helper functions to create real constructs for testing\n */\nexport function createTestEndpoint(path: string, method: HttpMethod = 'GET') {\n const m = method.toLowerCase() as Lowercase<HttpMethod>;\n const builder = e[m](path);\n builder.output(z.object({ message: z.string() }));\n return builder.handle(async () => ({ message: `Hello from ${path}` }));\n}\n\nexport function createTestFunction(timeout: number = 30) {\n const builder = new FunctionBuilder();\n builder.input(z.object({ name: z.string() }));\n builder.output(z.object({ greeting: z.string() }));\n builder.timeout(timeout);\n return builder.handle(async ({ input }: any) => ({ greeting: `Hello, ${input.name}!` }));\n}\n\nexport function createTestCron(\n schedule: ScheduleExpression = 'rate(1 hour)',\n timeout: number = 30,\n) {\n const builder = new CronBuilder();\n builder.schedule(schedule);\n builder.output(z.object({ processed: z.number() }));\n builder.timeout(timeout);\n return builder.handle(async () => {\n return { processed: 10 };\n });\n}\n\n/**\n * Creates a mock build context\n */\nexport function createMockBuildContext() {\n return {\n envParserPath: './env',\n envParserImportPattern: 'envParser',\n loggerPath: './logger',\n loggerImportPattern: 'logger',\n };\n}\n\n/**\n * Waits for a condition to be true\n */\nexport async function waitFor(\n condition: () => boolean,\n timeout = 5000,\n interval = 100,\n): Promise<void> {\n const start = Date.now();\n while (!condition() && Date.now() - start < timeout) {\n await new Promise((resolve) => setTimeout(resolve, interval));\n }\n if (!condition()) {\n throw new Error('Timeout waiting for condition');\n }\n}\n\nimport { dirname } from 'node:path';\nimport type { HttpMethod } from '../../../api/src/constructs/types';\n"],"mappings":";;;;;;;;;;;AAcA,eAAsB,cAAc,SAAS,aAA8B;CACzE,MAAM,WAAW,KACf,QAAQ,GACP,EAAE,OAAO,EAAE,KAAK,KAAK,CAAC,GAAG,KAAK,QAAQ,CAAC,SAAS,GAAG,CAAC,MAAM,EAAE,CAAC,EAC/D;AACD,OAAM,MAAM,UAAU,EAAE,WAAW,KAAM,EAAC;AAC1C,QAAO;AACR;;;;AAKD,eAAsB,WAAWA,MAA6B;AAC5D,KAAI;AACF,QAAM,GAAG,MAAM;GAAE,WAAW;GAAM,OAAO;EAAM,EAAC;CACjD,SAAQ,OAAO,CAEf;AACF;;;;AAKD,eAAsB,eACpBC,KACAC,UACAC,SACiB;CACjB,MAAM,WAAW,KAAK,KAAK,SAAS;AACpC,OAAM,MAAM,QAAQ,SAAS,EAAE,EAAE,WAAW,KAAM,EAAC;AACnD,OAAM,UAAU,UAAU,QAAQ;AAClC,QAAO;AACR;;;;AAKD,eAAsB,uBACpBF,KACAC,UACAE,YACAJ,OAAe,SACfK,SAAiB,OACA;CACjB,MAAM,WAAW;;;;eAIJ,WAAW;KACrB,OAAO,aAAa,CAAC,IAAI,KAAK;;gDAEa,WAAW;;AAEzD,QAAO,eAAe,KAAK,UAAU,QAAQ;AAC9C;;;;AAKD,eAAsB,uBACpBJ,KACAC,UACAE,YACA,UAAU,IACO;CACjB,MAAM,WAAW;;;;eAIJ,WAAW;;;aAGb,QAAQ;;;AAGnB,QAAO,eAAe,KAAK,UAAU,QAAQ;AAC9C;;;;AAKD,eAAsB,mBACpBH,KACAC,UACAE,YACA,WAAW,gBACM;CACjB,MAAM,WAAW;;;;eAIJ,WAAW;eACX,SAAS;;;qCAGa,WAAW;;;;AAI9C,QAAO,eAAe,KAAK,UAAU,QAAQ;AAC9C;;;;AAKD,SAAgB,mBAAmBJ,MAAcM,SAAqB,OAAO;CAC3E,MAAM,IAAI,OAAO,aAAa;CAC9B,MAAM,UAAU,EAAE,GAAG,KAAK;AAC1B,SAAQ,OAAO,WAAS,EAAE,SAAS,YAAU,CAAE,EAAC,CAAC;AACjD,QAAO,QAAQ,OAAO,aAAa,EAAE,UAAU,aAAa,KAAK,EAAG,GAAE;AACvE;AAED,SAAgB,mBAAmBC,UAAkB,IAAI;CACvD,MAAM,UAAU,IAAI;AACpB,SAAQ,MAAM,WAAS,EAAE,MAAM,YAAU,CAAE,EAAC,CAAC;AAC7C,SAAQ,OAAO,WAAS,EAAE,UAAU,YAAU,CAAE,EAAC,CAAC;AAClD,SAAQ,QAAQ,QAAQ;AACxB,QAAO,QAAQ,OAAO,OAAO,EAAE,OAAY,MAAM,EAAE,WAAW,SAAS,MAAM,KAAK,GAAI,GAAE;AACzF;AAED,SAAgB,eACdC,WAA+B,gBAC/BD,UAAkB,IAClB;CACA,MAAM,UAAU,IAAI;AACpB,SAAQ,SAAS,SAAS;AAC1B,SAAQ,OAAO,WAAS,EAAE,WAAW,YAAU,CAAE,EAAC,CAAC;AACnD,SAAQ,QAAQ,QAAQ;AACxB,QAAO,QAAQ,OAAO,YAAY;AAChC,SAAO,EAAE,WAAW,GAAI;CACzB,EAAC;AACH;;;;AAKD,SAAgB,yBAAyB;AACvC,QAAO;EACL,eAAe;EACf,wBAAwB;EACxB,YAAY;EACZ,qBAAqB;CACtB;AACF;;;;AAKD,eAAsB,QACpBE,WACA,UAAU,KACV,WAAW,KACI;CACf,MAAM,QAAQ,KAAK,KAAK;AACxB,SAAQ,WAAW,IAAI,KAAK,KAAK,GAAG,QAAQ,QAC1C,OAAM,IAAI,QAAQ,CAAC,YAAY,WAAW,SAAS,SAAS;AAE9D,MAAK,WAAW,CACd,OAAM,IAAI,MAAM;AAEnB"}
@@ -0,0 +1,45 @@
1
+ import { cron } from '@geekmidas/api/cron';
2
+
3
+ /**
4
+ * Example cron that generates a daily report at 9 AM UTC
5
+ */
6
+ export const dailyReport = cron
7
+ .schedule('cron(0 9 * * ? *)')
8
+ .timeout(600000) // 10 minutes
9
+ .handle(async ({ services, logger }) => {
10
+ logger.info('Generating daily report');
11
+
12
+ const reportDate = new Date().toISOString().split('T')[0];
13
+
14
+ // Generate report logic here
15
+ const reportData = {
16
+ date: reportDate,
17
+ totalOrders: 150,
18
+ totalRevenue: 12500.0,
19
+ topProducts: [
20
+ { id: 'prod-1', name: 'Widget A', sales: 45 },
21
+ { id: 'prod-2', name: 'Widget B', sales: 32 },
22
+ ],
23
+ };
24
+
25
+ logger.info('Daily report generated', reportData);
26
+
27
+ return reportData;
28
+ });
29
+
30
+ /**
31
+ * Example cron that runs every hour
32
+ */
33
+ export const hourlyCleanup = cron
34
+ .schedule('rate(1 hour)')
35
+ .timeout(300000) // 5 minutes
36
+ .handle(async ({ services, logger }) => {
37
+ logger.info('Running hourly cleanup');
38
+
39
+ // Cleanup logic here
40
+ const itemsCleaned = 42;
41
+
42
+ logger.info(`Cleaned ${itemsCleaned} items`);
43
+
44
+ return { itemsCleaned };
45
+ });
@@ -0,0 +1,40 @@
1
+ import { f } from '@geekmidas/api/function';
2
+ import { z } from 'zod';
3
+
4
+ /**
5
+ * Example function that processes an order
6
+ */
7
+ export const processOrder = f
8
+ .input(
9
+ z.object({
10
+ orderId: z.string(),
11
+ items: z.array(
12
+ z.object({
13
+ id: z.string(),
14
+ quantity: z.number().int().positive(),
15
+ }),
16
+ ),
17
+ }),
18
+ )
19
+ .output(
20
+ z.object({
21
+ orderId: z.string(),
22
+ status: z.enum(['processing', 'completed', 'failed']),
23
+ processedAt: z.string().datetime(),
24
+ }),
25
+ )
26
+ .timeout(300000) // 5 minutes
27
+ .handle(async ({ input, services, logger }) => {
28
+ logger.info(`Processing order ${input.orderId}`);
29
+
30
+ // Process order logic here
31
+ for (const item of input.items) {
32
+ logger.info(`Processing item ${item.id}, quantity: ${item.quantity}`);
33
+ }
34
+
35
+ return {
36
+ orderId: input.orderId,
37
+ status: 'completed' as const,
38
+ processedAt: new Date().toISOString(),
39
+ };
40
+ });
@@ -0,0 +1,22 @@
1
+ {
2
+ "routes": "./src/endpoints/**/*.ts",
3
+ "functions": "./src/functions/**/*.ts",
4
+ "crons": "./src/crons/**/*.ts",
5
+ "envParser": "./src/env.ts#envParser",
6
+ "logger": "./src/logger.ts#logger",
7
+ "providers": {
8
+ "aws": {
9
+ "apiGateway": {
10
+ "v1": false,
11
+ "v2": true
12
+ },
13
+ "lambda": {
14
+ "functions": true,
15
+ "crons": true
16
+ }
17
+ },
18
+ "server": {
19
+ "enableOpenApi": true
20
+ }
21
+ }
22
+ }
@@ -0,0 +1,7 @@
1
+ {
2
+ "routes": "./src/endpoints/**/*.ts",
3
+ "functions": "./src/functions/**/*.ts",
4
+ "crons": "./src/crons/**/*.ts",
5
+ "envParser": "./src/env.ts#envParser",
6
+ "logger": "./src/logger.ts#logger"
7
+ }
@@ -0,0 +1,27 @@
1
+ {
2
+ "routes": "./src/endpoints/**/*.ts",
3
+ "functions": "./src/functions/**/*.ts",
4
+ "crons": "./src/crons/**/*.ts",
5
+ "envParser": "./src/env.ts#envParser",
6
+ "logger": "./src/logger.ts#logger",
7
+ "providers": {
8
+ "aws": {
9
+ "apiGateway": {
10
+ "v2": {
11
+ "enabled": true,
12
+ "outputDir": "dist/api-gateway"
13
+ }
14
+ },
15
+ "lambda": {
16
+ "functions": {
17
+ "enabled": true,
18
+ "outputDir": "dist/functions"
19
+ },
20
+ "crons": {
21
+ "enabled": true,
22
+ "outputDir": "dist/crons"
23
+ }
24
+ }
25
+ }
26
+ }
27
+ }
package/package.json CHANGED
@@ -1,26 +1,47 @@
1
1
  {
2
2
  "name": "@geekmidas/cli",
3
- "version": "0.0.25",
3
+ "version": "0.1.0",
4
4
  "private": false,
5
5
  "type": "module",
6
+ "exports": {
7
+ ".": {
8
+ "types": "./dist/index.d.ts",
9
+ "import": "./dist/index.mjs",
10
+ "require": "./dist/index.cjs"
11
+ },
12
+ "./openapi": {
13
+ "types": "./dist/openapi.d.ts",
14
+ "import": "./dist/openapi.mjs",
15
+ "require": "./dist/openapi.cjs"
16
+ },
17
+ "./openapi-react-query": {
18
+ "types": "./dist/openapi-react-query.d.ts",
19
+ "import": "./dist/openapi-react-query.mjs",
20
+ "require": "./dist/openapi-react-query.cjs"
21
+ }
22
+ },
6
23
  "bin": {
7
24
  "gkm": "./dist/index.cjs"
8
25
  },
9
- "publishConfig": {
10
- "registry": "https://registry.npmjs.org/",
11
- "access": "public"
12
- },
13
26
  "dependencies": {
14
- "commander": "~14.0.0",
15
- "lodash.get": "~4.4.2",
16
- "lodash.set": "~4.3.2",
17
- "fast-glob": "~3.3.3"
18
- },
19
- "peerDependencies": {
20
- "@geekmidas/api": "0.0.50"
27
+ "@apidevtools/swagger-parser": "^10.1.0",
28
+ "commander": "^12.1.0",
29
+ "fast-glob": "^3.3.2",
30
+ "lodash.kebabcase": "^4.1.1",
31
+ "openapi-typescript": "^7.4.2",
32
+ "@geekmidas/api": "0.1.0"
21
33
  },
22
34
  "devDependencies": {
23
- "@types/lodash.get": "~4.4.9",
24
- "@types/lodash.set": "~4.3.9"
35
+ "@types/lodash.kebabcase": "^4.1.9",
36
+ "typescript": "^5.8.2",
37
+ "vitest": "^3.2.4",
38
+ "zod": "^3.23.8",
39
+ "@geekmidas/testkit": "0.0.15"
40
+ },
41
+ "scripts": {
42
+ "ts": "tsc --noEmit --skipLibCheck src/**/*.ts",
43
+ "test": "vitest",
44
+ "test:once": "vitest run",
45
+ "test:coverage": "vitest run --coverage"
25
46
  }
26
47
  }