@geekmidas/cli 0.49.0 → 0.51.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 (41) hide show
  1. package/dist/deploy/sniffer-envkit-patch.cjs +27 -0
  2. package/dist/deploy/sniffer-envkit-patch.cjs.map +1 -0
  3. package/dist/deploy/sniffer-envkit-patch.d.cts +46 -0
  4. package/dist/deploy/sniffer-envkit-patch.d.cts.map +1 -0
  5. package/dist/deploy/sniffer-envkit-patch.d.mts +46 -0
  6. package/dist/deploy/sniffer-envkit-patch.d.mts.map +1 -0
  7. package/dist/deploy/sniffer-envkit-patch.mjs +20 -0
  8. package/dist/deploy/sniffer-envkit-patch.mjs.map +1 -0
  9. package/dist/deploy/sniffer-hooks.cjs +25 -0
  10. package/dist/deploy/sniffer-hooks.cjs.map +1 -0
  11. package/dist/deploy/sniffer-hooks.d.cts +27 -0
  12. package/dist/deploy/sniffer-hooks.d.cts.map +1 -0
  13. package/dist/deploy/sniffer-hooks.d.mts +27 -0
  14. package/dist/deploy/sniffer-hooks.d.mts.map +1 -0
  15. package/dist/deploy/sniffer-hooks.mjs +24 -0
  16. package/dist/deploy/sniffer-hooks.mjs.map +1 -0
  17. package/dist/deploy/sniffer-loader.cjs +16 -0
  18. package/dist/deploy/sniffer-loader.cjs.map +1 -0
  19. package/dist/deploy/sniffer-loader.d.cts +1 -0
  20. package/dist/deploy/sniffer-loader.d.mts +1 -0
  21. package/dist/deploy/sniffer-loader.mjs +15 -0
  22. package/dist/deploy/sniffer-loader.mjs.map +1 -0
  23. package/dist/deploy/sniffer-worker.cjs +42 -0
  24. package/dist/deploy/sniffer-worker.cjs.map +1 -0
  25. package/dist/deploy/sniffer-worker.d.cts +9 -0
  26. package/dist/deploy/sniffer-worker.d.cts.map +1 -0
  27. package/dist/deploy/sniffer-worker.d.mts +9 -0
  28. package/dist/deploy/sniffer-worker.d.mts.map +1 -0
  29. package/dist/deploy/sniffer-worker.mjs +41 -0
  30. package/dist/deploy/sniffer-worker.mjs.map +1 -0
  31. package/dist/index.cjs +26 -6
  32. package/dist/index.cjs.map +1 -1
  33. package/dist/index.mjs +26 -6
  34. package/dist/index.mjs.map +1 -1
  35. package/package.json +2 -2
  36. package/src/deploy/index.ts +5 -3
  37. package/src/deploy/sniffer-envkit-patch.ts +19 -3
  38. package/src/deploy/sniffer-hooks.ts +6 -1
  39. package/src/deploy/sniffer-loader.ts +7 -2
  40. package/src/deploy/sniffer.ts +36 -2
  41. package/tsdown.config.ts +5 -0
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@geekmidas/cli",
3
- "version": "0.49.0",
3
+ "version": "0.51.0",
4
4
  "description": "CLI tools for building Lambda handlers, server applications, and generating OpenAPI specs",
5
5
  "private": false,
6
6
  "type": "module",
@@ -49,8 +49,8 @@
49
49
  "openapi-typescript": "^7.4.2",
50
50
  "pg": "~8.17.1",
51
51
  "prompts": "~2.4.2",
52
- "@geekmidas/constructs": "~0.8.0",
53
52
  "@geekmidas/envkit": "~0.7.0",
53
+ "@geekmidas/constructs": "~0.8.0",
54
54
  "@geekmidas/errors": "~0.1.0",
55
55
  "@geekmidas/logger": "~0.4.0",
56
56
  "@geekmidas/schema": "~0.1.0"
@@ -338,9 +338,11 @@ async function initializePostgresUsers(
338
338
  // Create or update user (handles existing users)
339
339
  await client.query(`
340
340
  DO $$ BEGIN
341
- CREATE USER "${user.name}" WITH PASSWORD '${user.password}';
342
- EXCEPTION WHEN duplicate_object THEN
343
- ALTER USER "${user.name}" WITH PASSWORD '${user.password}';
341
+ IF NOT EXISTS (SELECT FROM pg_roles WHERE rolname = '${user.name}') THEN
342
+ CREATE USER "${user.name}" WITH PASSWORD '${user.password}';
343
+ ELSE
344
+ ALTER USER "${user.name}" WITH PASSWORD '${user.password}';
345
+ END IF;
344
346
  END $$;
345
347
  `);
346
348
 
@@ -22,6 +22,21 @@ if (!globalThis.__envSniffer) {
22
22
  globalThis.__envSniffer = new SnifferEnvironmentParser();
23
23
  }
24
24
 
25
+ // Type for the config parser returned by create()
26
+ interface ConfigParser<T> {
27
+ parse(): T;
28
+ safeParse(): { success: true; data: T } | { success: false; error: Error };
29
+ }
30
+
31
+ // Type for the env fetcher function
32
+ type EnvFetcher = (name: string) => {
33
+ string(): { parse(): string; safeParse(): unknown };
34
+ number(): { parse(): number; safeParse(): unknown };
35
+ boolean(): { parse(): boolean; safeParse(): unknown };
36
+ optional(): EnvFetcher;
37
+ default(value: unknown): EnvFetcher;
38
+ };
39
+
25
40
  /**
26
41
  * Patched EnvironmentParser that uses the global sniffer instance.
27
42
  *
@@ -30,9 +45,10 @@ if (!globalThis.__envSniffer) {
30
45
  * parameter for API compatibility but ignores it since we're sniffing.
31
46
  */
32
47
  class PatchedEnvironmentParser {
33
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
34
- create(builder: (get: any) => any) {
35
- return globalThis.__envSniffer!.create(builder);
48
+ create<TReturn extends Record<string, unknown>>(
49
+ builder: (get: EnvFetcher) => TReturn,
50
+ ): ConfigParser<TReturn> {
51
+ return globalThis.__envSniffer!.create(builder) as ConfigParser<TReturn>;
36
52
  }
37
53
  }
38
54
 
@@ -7,13 +7,18 @@
7
7
  * This file is registered via module.register() from sniffer-loader.ts.
8
8
  */
9
9
 
10
+ import { existsSync } from 'node:fs';
10
11
  import { dirname, join } from 'node:path';
11
12
  import { fileURLToPath } from 'node:url';
12
13
 
13
14
  // Resolve path to the patched envkit module
14
15
  const __filename = fileURLToPath(import.meta.url);
15
16
  const __dirname = dirname(__filename);
16
- const patchedEnvkitPath = join(__dirname, 'sniffer-envkit-patch.ts');
17
+
18
+ // Try .mjs first (production dist), then .ts (development)
19
+ const mjsPath = join(__dirname, 'sniffer-envkit-patch.mjs');
20
+ const tsPath = join(__dirname, 'sniffer-envkit-patch.ts');
21
+ const patchedEnvkitPath = existsSync(mjsPath) ? mjsPath : tsPath;
17
22
 
18
23
  type ResolveContext = {
19
24
  conditions: string[];
@@ -7,9 +7,10 @@
7
7
  * variables an entry app accesses.
8
8
  *
9
9
  * Usage:
10
- * node --import tsx --import ./sniffer-loader.ts ./sniffer-worker.ts /path/to/entry.ts
10
+ * node --import tsx --import ./sniffer-loader.mjs ./sniffer-worker.mjs /path/to/entry.ts
11
11
  */
12
12
 
13
+ import { existsSync } from 'node:fs';
13
14
  import { register } from 'node:module';
14
15
  import { dirname, join } from 'node:path';
15
16
  import { fileURLToPath, pathToFileURL } from 'node:url';
@@ -17,7 +18,11 @@ import { fileURLToPath, pathToFileURL } from 'node:url';
17
18
  // Resolve path to the loader hooks module
18
19
  const __filename = fileURLToPath(import.meta.url);
19
20
  const __dirname = dirname(__filename);
20
- const hooksPath = join(__dirname, 'sniffer-hooks.ts');
21
+
22
+ // Try .mjs first (production dist), then .ts (development)
23
+ const mjsPath = join(__dirname, 'sniffer-hooks.mjs');
24
+ const tsPath = join(__dirname, 'sniffer-hooks.ts');
25
+ const hooksPath = existsSync(mjsPath) ? mjsPath : tsPath;
21
26
 
22
27
  // Register the loader hooks
23
28
  register(pathToFileURL(hooksPath).href, import.meta.url);
@@ -1,3 +1,4 @@
1
+ import { existsSync } from 'node:fs';
1
2
  import { spawn } from 'node:child_process';
2
3
  import { dirname, resolve } from 'node:path';
3
4
  import { fileURLToPath, pathToFileURL } from 'node:url';
@@ -7,6 +8,39 @@ import type { NormalizedAppConfig } from '../workspace/types.js';
7
8
  const __filename = fileURLToPath(import.meta.url);
8
9
  const __dirname = dirname(__filename);
9
10
 
11
+ /**
12
+ * Resolve the path to a sniffer helper file.
13
+ * Handles both dev (.ts with tsx) and production (.mjs from dist).
14
+ *
15
+ * In production: sniffer.ts is bundled into dist/index.mjs, but sniffer helper
16
+ * files are output to dist/deploy/ as standalone modules for subprocess loading.
17
+ *
18
+ * In development: All files are in src/deploy/ and loaded via tsx.
19
+ */
20
+ function resolveSnifferFile(baseName: string): string {
21
+ // Try deploy/ subdirectory first (production: bundled code is at dist/index.mjs,
22
+ // but sniffer files are at dist/deploy/)
23
+ const deployMjsPath = resolve(__dirname, 'deploy', `${baseName}.mjs`);
24
+ if (existsSync(deployMjsPath)) {
25
+ return deployMjsPath;
26
+ }
27
+
28
+ // Try same directory .mjs (production: if running from dist/deploy/ directly)
29
+ const mjsPath = resolve(__dirname, `${baseName}.mjs`);
30
+ if (existsSync(mjsPath)) {
31
+ return mjsPath;
32
+ }
33
+
34
+ // Try same directory .ts (development with tsx: all files in src/deploy/)
35
+ const tsPath = resolve(__dirname, `${baseName}.ts`);
36
+ if (existsSync(tsPath)) {
37
+ return tsPath;
38
+ }
39
+
40
+ // Fallback to .ts (will error if neither exists)
41
+ return tsPath;
42
+ }
43
+
10
44
  // Re-export SniffResult for consumers
11
45
  export type { SniffResult } from '@geekmidas/envkit/sniffer';
12
46
 
@@ -134,8 +168,8 @@ async function sniffEntryFile(
134
168
  workspacePath: string,
135
169
  ): Promise<EntrySniffResult> {
136
170
  const fullEntryPath = resolve(workspacePath, appPath, entryPath);
137
- const loaderPath = resolve(__dirname, 'sniffer-loader.ts');
138
- const workerPath = resolve(__dirname, 'sniffer-worker.ts');
171
+ const loaderPath = resolveSnifferFile('sniffer-loader');
172
+ const workerPath = resolveSnifferFile('sniffer-worker');
139
173
 
140
174
  return new Promise((resolvePromise) => {
141
175
  const child = spawn(
package/tsdown.config.ts CHANGED
@@ -7,6 +7,11 @@ export default defineConfig({
7
7
  'src/workspace/index.ts',
8
8
  'src/openapi.ts',
9
9
  'src/openapi-react-query.ts',
10
+ // Sniffer files need to be standalone for subprocess loading via --import
11
+ 'src/deploy/sniffer-loader.ts',
12
+ 'src/deploy/sniffer-worker.ts',
13
+ 'src/deploy/sniffer-hooks.ts',
14
+ 'src/deploy/sniffer-envkit-patch.ts',
10
15
  ],
11
16
  dts: true,
12
17
  format: ['cjs', 'esm'],