@geekmidas/cli 0.48.0 → 0.50.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 (80) 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/{dokploy-api-DvzIDxTj.mjs → dokploy-api-94KzmTVf.mjs} +4 -4
  32. package/dist/dokploy-api-94KzmTVf.mjs.map +1 -0
  33. package/dist/dokploy-api-CItuaWTq.mjs +3 -0
  34. package/dist/dokploy-api-DBNE8MDt.cjs +3 -0
  35. package/dist/{dokploy-api-BDLu0qWi.cjs → dokploy-api-YD8WCQfW.cjs} +4 -4
  36. package/dist/dokploy-api-YD8WCQfW.cjs.map +1 -0
  37. package/dist/index.cjs +2415 -1893
  38. package/dist/index.cjs.map +1 -1
  39. package/dist/index.mjs +2411 -1889
  40. package/dist/index.mjs.map +1 -1
  41. package/package.json +8 -6
  42. package/src/build/__tests__/handler-templates.spec.ts +947 -0
  43. package/src/deploy/__tests__/__fixtures__/entry-apps/async-entry.ts +24 -0
  44. package/src/deploy/__tests__/__fixtures__/entry-apps/nested-config-entry.ts +24 -0
  45. package/src/deploy/__tests__/__fixtures__/entry-apps/no-env-entry.ts +12 -0
  46. package/src/deploy/__tests__/__fixtures__/entry-apps/simple-entry.ts +14 -0
  47. package/src/deploy/__tests__/__fixtures__/entry-apps/throwing-entry.ts +16 -0
  48. package/src/deploy/__tests__/__fixtures__/env-parsers/non-function-export.ts +10 -0
  49. package/src/deploy/__tests__/__fixtures__/env-parsers/parseable-env-parser.ts +18 -0
  50. package/src/deploy/__tests__/__fixtures__/env-parsers/throwing-env-parser.ts +18 -0
  51. package/src/deploy/__tests__/__fixtures__/env-parsers/valid-env-parser.ts +16 -0
  52. package/src/deploy/__tests__/dns-verification.spec.ts +229 -0
  53. package/src/deploy/__tests__/dokploy-api.spec.ts +2 -3
  54. package/src/deploy/__tests__/domain.spec.ts +7 -3
  55. package/src/deploy/__tests__/env-resolver.spec.ts +469 -0
  56. package/src/deploy/__tests__/index.spec.ts +12 -12
  57. package/src/deploy/__tests__/secrets.spec.ts +4 -1
  58. package/src/deploy/__tests__/sniffer.spec.ts +326 -1
  59. package/src/deploy/__tests__/state.spec.ts +844 -0
  60. package/src/deploy/dns/hostinger-api.ts +4 -1
  61. package/src/deploy/dns/index.ts +113 -1
  62. package/src/deploy/docker.ts +1 -2
  63. package/src/deploy/dokploy-api.ts +18 -9
  64. package/src/deploy/domain.ts +5 -4
  65. package/src/deploy/env-resolver.ts +278 -0
  66. package/src/deploy/index.ts +525 -119
  67. package/src/deploy/secrets.ts +7 -2
  68. package/src/deploy/sniffer-envkit-patch.ts +59 -0
  69. package/src/deploy/sniffer-hooks.ts +57 -0
  70. package/src/deploy/sniffer-loader.ts +28 -0
  71. package/src/deploy/sniffer-worker.ts +74 -0
  72. package/src/deploy/sniffer.ts +170 -14
  73. package/src/deploy/state.ts +162 -1
  74. package/src/init/versions.ts +3 -3
  75. package/tsconfig.tsbuildinfo +1 -1
  76. package/tsdown.config.ts +5 -0
  77. package/dist/dokploy-api-BDLu0qWi.cjs.map +0 -1
  78. package/dist/dokploy-api-BN3V57z1.mjs +0 -3
  79. package/dist/dokploy-api-BdCKjFDA.cjs +0 -3
  80. package/dist/dokploy-api-DvzIDxTj.mjs.map +0 -1
@@ -0,0 +1,27 @@
1
+ const require_chunk = require('../chunk-CUT6urMc.cjs');
2
+ const __geekmidas_envkit_sniffer = require_chunk.__toESM(require("@geekmidas/envkit/sniffer"));
3
+
4
+ //#region src/deploy/sniffer-envkit-patch.ts
5
+ if (!globalThis.__envSniffer) globalThis.__envSniffer = new __geekmidas_envkit_sniffer.SnifferEnvironmentParser();
6
+ /**
7
+ * Patched EnvironmentParser that uses the global sniffer instance.
8
+ *
9
+ * This class wraps the global sniffer to maintain API compatibility
10
+ * with the real EnvironmentParser. The constructor accepts an env
11
+ * parameter for API compatibility but ignores it since we're sniffing.
12
+ */
13
+ var PatchedEnvironmentParser = class {
14
+ create(builder) {
15
+ return globalThis.__envSniffer.create(builder);
16
+ }
17
+ };
18
+
19
+ //#endregion
20
+ exports.EnvironmentParser = PatchedEnvironmentParser;
21
+ Object.defineProperty(exports, 'SnifferEnvironmentParser', {
22
+ enumerable: true,
23
+ get: function () {
24
+ return __geekmidas_envkit_sniffer.SnifferEnvironmentParser;
25
+ }
26
+ });
27
+ //# sourceMappingURL=sniffer-envkit-patch.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sniffer-envkit-patch.cjs","names":["SnifferEnvironmentParser","builder: (get: EnvFetcher) => TReturn"],"sources":["../../src/deploy/sniffer-envkit-patch.ts"],"sourcesContent":["/**\n * Patched @geekmidas/envkit module for entry app sniffing.\n *\n * This module re-exports the SnifferEnvironmentParser as EnvironmentParser,\n * allowing entry apps to be imported while capturing their env var usage.\n *\n * The actual sniffer instance is stored in globalThis.__envSniffer\n * so the worker script can retrieve the captured variables.\n */\n\nimport { SnifferEnvironmentParser } from '@geekmidas/envkit/sniffer';\n\n// Extend globalThis type for the sniffer instance\ndeclare global {\n\t// eslint-disable-next-line no-var\n\tvar __envSniffer: SnifferEnvironmentParser | undefined;\n}\n\n// Create a shared sniffer instance that will be used by all imports\n// This is stored globally so the worker script can access it\nif (!globalThis.__envSniffer) {\n\tglobalThis.__envSniffer = new SnifferEnvironmentParser();\n}\n\n// Type for the config parser returned by create()\ninterface ConfigParser<T> {\n\tparse(): T;\n\tsafeParse(): { success: true; data: T } | { success: false; error: Error };\n}\n\n// Type for the env fetcher function\ntype EnvFetcher = (name: string) => {\n\tstring(): { parse(): string; safeParse(): unknown };\n\tnumber(): { parse(): number; safeParse(): unknown };\n\tboolean(): { parse(): boolean; safeParse(): unknown };\n\toptional(): EnvFetcher;\n\tdefault(value: unknown): EnvFetcher;\n};\n\n/**\n * Patched EnvironmentParser that uses the global sniffer instance.\n *\n * This class wraps the global sniffer to maintain API compatibility\n * with the real EnvironmentParser. The constructor accepts an env\n * parameter for API compatibility but ignores it since we're sniffing.\n */\nclass PatchedEnvironmentParser {\n\tcreate<TReturn extends Record<string, unknown>>(\n\t\tbuilder: (get: EnvFetcher) => TReturn,\n\t): ConfigParser<TReturn> {\n\t\treturn globalThis.__envSniffer!.create(builder) as ConfigParser<TReturn>;\n\t}\n}\n\n// Export the patched parser as EnvironmentParser\nexport { PatchedEnvironmentParser as EnvironmentParser };\n\n// Re-export other envkit exports that entry apps might use\nexport { SnifferEnvironmentParser } from '@geekmidas/envkit/sniffer';\n"],"mappings":";;;;AAoBA,KAAK,WAAW,aACf,YAAW,eAAe,IAAIA;;;;;;;;AAyB/B,IAAM,2BAAN,MAA+B;CAC9B,OACCC,SACwB;AACxB,SAAO,WAAW,aAAc,OAAO,QAAQ;CAC/C;AACD"}
@@ -0,0 +1,46 @@
1
+ import { SnifferEnvironmentParser, SnifferEnvironmentParser as SnifferEnvironmentParser$1 } from "@geekmidas/envkit/sniffer";
2
+
3
+ //#region src/deploy/sniffer-envkit-patch.d.ts
4
+
5
+ declare global {
6
+ var __envSniffer: SnifferEnvironmentParser$1 | undefined;
7
+ }
8
+ interface ConfigParser<T> {
9
+ parse(): T;
10
+ safeParse(): {
11
+ success: true;
12
+ data: T;
13
+ } | {
14
+ success: false;
15
+ error: Error;
16
+ };
17
+ }
18
+ type EnvFetcher = (name: string) => {
19
+ string(): {
20
+ parse(): string;
21
+ safeParse(): unknown;
22
+ };
23
+ number(): {
24
+ parse(): number;
25
+ safeParse(): unknown;
26
+ };
27
+ boolean(): {
28
+ parse(): boolean;
29
+ safeParse(): unknown;
30
+ };
31
+ optional(): EnvFetcher;
32
+ default(value: unknown): EnvFetcher;
33
+ };
34
+ /**
35
+ * Patched EnvironmentParser that uses the global sniffer instance.
36
+ *
37
+ * This class wraps the global sniffer to maintain API compatibility
38
+ * with the real EnvironmentParser. The constructor accepts an env
39
+ * parameter for API compatibility but ignores it since we're sniffing.
40
+ */
41
+ declare class PatchedEnvironmentParser {
42
+ create<TReturn extends Record<string, unknown>>(builder: (get: EnvFetcher) => TReturn): ConfigParser<TReturn>;
43
+ }
44
+ //#endregion
45
+ export { PatchedEnvironmentParser as EnvironmentParser, SnifferEnvironmentParser };
46
+ //# sourceMappingURL=sniffer-envkit-patch.d.cts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sniffer-envkit-patch.d.cts","names":[],"sources":["../../src/deploy/sniffer-envkit-patch.ts"],"sourcesContent":[],"mappings":";;;;QA0BU,MAAA,CAAA;EAAC,IAC0B,YAAA,EAZlB,0BAYkB,GAAA,SAAA;;AAAoC,UAF/D,YAE+D,CAAA,CAAA,CAAA,CAAA;EAIpE,KAAA,EAAA,EALK,CAKL;EAAU,SAAA,EAAA,EAAA;IAIF,OAAA,EAAA,IAAA;IACa,IAAA,EATW,CASX;EAAU,CAAA,GAAA;IAU9B,OAAA,EAAA,KAAA;IAAwB,KAAA,EAnBsC,KAmBtC;EAAA,CAAA;;KAfzB,UAAA,GAiB2B,CAAA,IAAA,EAAA,MAAA,EAAA,GAAA;EAAO,MACtB,EAAA,EAAA;IAAb,KAAA,EAAA,EAAA,MAAA;IAAY,SAAA,EAAA,EAAA,OAAA;;;;;;;;;;cAdH;2BACa;;;;;;;;;cAUpB,wBAAA;yBACkB,wCACP,eAAe,UAC5B,aAAa"}
@@ -0,0 +1,46 @@
1
+ import { SnifferEnvironmentParser, SnifferEnvironmentParser as SnifferEnvironmentParser$1 } from "@geekmidas/envkit/sniffer";
2
+
3
+ //#region src/deploy/sniffer-envkit-patch.d.ts
4
+
5
+ declare global {
6
+ var __envSniffer: SnifferEnvironmentParser$1 | undefined;
7
+ }
8
+ interface ConfigParser<T> {
9
+ parse(): T;
10
+ safeParse(): {
11
+ success: true;
12
+ data: T;
13
+ } | {
14
+ success: false;
15
+ error: Error;
16
+ };
17
+ }
18
+ type EnvFetcher = (name: string) => {
19
+ string(): {
20
+ parse(): string;
21
+ safeParse(): unknown;
22
+ };
23
+ number(): {
24
+ parse(): number;
25
+ safeParse(): unknown;
26
+ };
27
+ boolean(): {
28
+ parse(): boolean;
29
+ safeParse(): unknown;
30
+ };
31
+ optional(): EnvFetcher;
32
+ default(value: unknown): EnvFetcher;
33
+ };
34
+ /**
35
+ * Patched EnvironmentParser that uses the global sniffer instance.
36
+ *
37
+ * This class wraps the global sniffer to maintain API compatibility
38
+ * with the real EnvironmentParser. The constructor accepts an env
39
+ * parameter for API compatibility but ignores it since we're sniffing.
40
+ */
41
+ declare class PatchedEnvironmentParser {
42
+ create<TReturn extends Record<string, unknown>>(builder: (get: EnvFetcher) => TReturn): ConfigParser<TReturn>;
43
+ }
44
+ //#endregion
45
+ export { PatchedEnvironmentParser as EnvironmentParser, SnifferEnvironmentParser };
46
+ //# sourceMappingURL=sniffer-envkit-patch.d.mts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sniffer-envkit-patch.d.mts","names":[],"sources":["../../src/deploy/sniffer-envkit-patch.ts"],"sourcesContent":[],"mappings":";;;;QA0BU,MAAA,CAAA;EAAC,IAC0B,YAAA,EAZlB,0BAYkB,GAAA,SAAA;;AAAoC,UAF/D,YAE+D,CAAA,CAAA,CAAA,CAAA;EAIpE,KAAA,EAAA,EALK,CAKL;EAAU,SAAA,EAAA,EAAA;IAIF,OAAA,EAAA,IAAA;IACa,IAAA,EATW,CASX;EAAU,CAAA,GAAA;IAU9B,OAAA,EAAA,KAAA;IAAwB,KAAA,EAnBsC,KAmBtC;EAAA,CAAA;;KAfzB,UAAA,GAiB2B,CAAA,IAAA,EAAA,MAAA,EAAA,GAAA;EAAO,MACtB,EAAA,EAAA;IAAb,KAAA,EAAA,EAAA,MAAA;IAAY,SAAA,EAAA,EAAA,OAAA;;;;;;;;;;cAdH;2BACa;;;;;;;;;cAUpB,wBAAA;yBACkB,wCACP,eAAe,UAC5B,aAAa"}
@@ -0,0 +1,20 @@
1
+ import { SnifferEnvironmentParser, SnifferEnvironmentParser as SnifferEnvironmentParser$1 } from "@geekmidas/envkit/sniffer";
2
+
3
+ //#region src/deploy/sniffer-envkit-patch.ts
4
+ if (!globalThis.__envSniffer) globalThis.__envSniffer = new SnifferEnvironmentParser$1();
5
+ /**
6
+ * Patched EnvironmentParser that uses the global sniffer instance.
7
+ *
8
+ * This class wraps the global sniffer to maintain API compatibility
9
+ * with the real EnvironmentParser. The constructor accepts an env
10
+ * parameter for API compatibility but ignores it since we're sniffing.
11
+ */
12
+ var PatchedEnvironmentParser = class {
13
+ create(builder) {
14
+ return globalThis.__envSniffer.create(builder);
15
+ }
16
+ };
17
+
18
+ //#endregion
19
+ export { PatchedEnvironmentParser as EnvironmentParser, SnifferEnvironmentParser };
20
+ //# sourceMappingURL=sniffer-envkit-patch.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sniffer-envkit-patch.mjs","names":["SnifferEnvironmentParser","builder: (get: EnvFetcher) => TReturn"],"sources":["../../src/deploy/sniffer-envkit-patch.ts"],"sourcesContent":["/**\n * Patched @geekmidas/envkit module for entry app sniffing.\n *\n * This module re-exports the SnifferEnvironmentParser as EnvironmentParser,\n * allowing entry apps to be imported while capturing their env var usage.\n *\n * The actual sniffer instance is stored in globalThis.__envSniffer\n * so the worker script can retrieve the captured variables.\n */\n\nimport { SnifferEnvironmentParser } from '@geekmidas/envkit/sniffer';\n\n// Extend globalThis type for the sniffer instance\ndeclare global {\n\t// eslint-disable-next-line no-var\n\tvar __envSniffer: SnifferEnvironmentParser | undefined;\n}\n\n// Create a shared sniffer instance that will be used by all imports\n// This is stored globally so the worker script can access it\nif (!globalThis.__envSniffer) {\n\tglobalThis.__envSniffer = new SnifferEnvironmentParser();\n}\n\n// Type for the config parser returned by create()\ninterface ConfigParser<T> {\n\tparse(): T;\n\tsafeParse(): { success: true; data: T } | { success: false; error: Error };\n}\n\n// Type for the env fetcher function\ntype EnvFetcher = (name: string) => {\n\tstring(): { parse(): string; safeParse(): unknown };\n\tnumber(): { parse(): number; safeParse(): unknown };\n\tboolean(): { parse(): boolean; safeParse(): unknown };\n\toptional(): EnvFetcher;\n\tdefault(value: unknown): EnvFetcher;\n};\n\n/**\n * Patched EnvironmentParser that uses the global sniffer instance.\n *\n * This class wraps the global sniffer to maintain API compatibility\n * with the real EnvironmentParser. The constructor accepts an env\n * parameter for API compatibility but ignores it since we're sniffing.\n */\nclass PatchedEnvironmentParser {\n\tcreate<TReturn extends Record<string, unknown>>(\n\t\tbuilder: (get: EnvFetcher) => TReturn,\n\t): ConfigParser<TReturn> {\n\t\treturn globalThis.__envSniffer!.create(builder) as ConfigParser<TReturn>;\n\t}\n}\n\n// Export the patched parser as EnvironmentParser\nexport { PatchedEnvironmentParser as EnvironmentParser };\n\n// Re-export other envkit exports that entry apps might use\nexport { SnifferEnvironmentParser } from '@geekmidas/envkit/sniffer';\n"],"mappings":";;;AAoBA,KAAK,WAAW,aACf,YAAW,eAAe,IAAIA;;;;;;;;AAyB/B,IAAM,2BAAN,MAA+B;CAC9B,OACCC,SACwB;AACxB,SAAO,WAAW,aAAc,OAAO,QAAQ;CAC/C;AACD"}
@@ -0,0 +1,25 @@
1
+ const require_chunk = require('../chunk-CUT6urMc.cjs');
2
+ const node_fs = require_chunk.__toESM(require("node:fs"));
3
+ const node_path = require_chunk.__toESM(require("node:path"));
4
+ const node_url = require_chunk.__toESM(require("node:url"));
5
+
6
+ //#region src/deploy/sniffer-hooks.ts
7
+ const __filename$1 = (0, node_url.fileURLToPath)(require("url").pathToFileURL(__filename).href);
8
+ const __dirname$1 = (0, node_path.dirname)(__filename$1);
9
+ const mjsPath = (0, node_path.join)(__dirname$1, "sniffer-envkit-patch.mjs");
10
+ const tsPath = (0, node_path.join)(__dirname$1, "sniffer-envkit-patch.ts");
11
+ const patchedEnvkitPath = (0, node_fs.existsSync)(mjsPath) ? mjsPath : tsPath;
12
+ /**
13
+ * Resolve hook - intercepts module resolution for @geekmidas/envkit
14
+ */
15
+ async function resolve(specifier, context, nextResolve) {
16
+ if (specifier === "@geekmidas/envkit") return {
17
+ url: `file://${patchedEnvkitPath}`,
18
+ shortCircuit: true
19
+ };
20
+ return nextResolve(specifier, context);
21
+ }
22
+
23
+ //#endregion
24
+ exports.resolve = resolve;
25
+ //# sourceMappingURL=sniffer-hooks.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sniffer-hooks.cjs","names":["__filename","__dirname","specifier: string","context: ResolveContext","nextResolve: NextResolve"],"sources":["../../src/deploy/sniffer-hooks.ts"],"sourcesContent":["/**\n * Module loader hooks for entry app sniffing.\n *\n * This module provides the resolve hook that intercepts '@geekmidas/envkit'\n * imports and redirects them to the patched sniffer version.\n *\n * This file is registered via module.register() from sniffer-loader.ts.\n */\n\nimport { existsSync } from 'node:fs';\nimport { dirname, join } from 'node:path';\nimport { fileURLToPath } from 'node:url';\n\n// Resolve path to the patched envkit module\nconst __filename = fileURLToPath(import.meta.url);\nconst __dirname = dirname(__filename);\n\n// Try .mjs first (production dist), then .ts (development)\nconst mjsPath = join(__dirname, 'sniffer-envkit-patch.mjs');\nconst tsPath = join(__dirname, 'sniffer-envkit-patch.ts');\nconst patchedEnvkitPath = existsSync(mjsPath) ? mjsPath : tsPath;\n\ntype ResolveContext = {\n\tconditions: string[];\n\timportAttributes: Record<string, string>;\n\tparentURL?: string;\n};\n\ntype ResolveResult = {\n\turl: string;\n\tshortCircuit?: boolean;\n\tformat?: string;\n};\n\ntype NextResolve = (\n\tspecifier: string,\n\tcontext: ResolveContext,\n) => Promise<ResolveResult>;\n\n/**\n * Resolve hook - intercepts module resolution for @geekmidas/envkit\n */\nexport async function resolve(\n\tspecifier: string,\n\tcontext: ResolveContext,\n\tnextResolve: NextResolve,\n): Promise<ResolveResult> {\n\t// Intercept @geekmidas/envkit imports\n\tif (specifier === '@geekmidas/envkit') {\n\t\treturn {\n\t\t\turl: `file://${patchedEnvkitPath}`,\n\t\t\tshortCircuit: true,\n\t\t};\n\t}\n\n\treturn nextResolve(specifier, context);\n}\n"],"mappings":";;;;;;AAcA,MAAMA,eAAa,0EAA8B;AACjD,MAAMC,cAAY,uBAAQD,aAAW;AAGrC,MAAM,UAAU,oBAAKC,aAAW,2BAA2B;AAC3D,MAAM,SAAS,oBAAKA,aAAW,0BAA0B;AACzD,MAAM,oBAAoB,wBAAW,QAAQ,GAAG,UAAU;;;;AAsB1D,eAAsB,QACrBC,WACAC,SACAC,aACyB;AAEzB,KAAI,cAAc,oBACjB,QAAO;EACN,MAAM,SAAS,kBAAkB;EACjC,cAAc;CACd;AAGF,QAAO,YAAY,WAAW,QAAQ;AACtC"}
@@ -0,0 +1,27 @@
1
+ //#region src/deploy/sniffer-hooks.d.ts
2
+ /**
3
+ * Module loader hooks for entry app sniffing.
4
+ *
5
+ * This module provides the resolve hook that intercepts '@geekmidas/envkit'
6
+ * imports and redirects them to the patched sniffer version.
7
+ *
8
+ * This file is registered via module.register() from sniffer-loader.ts.
9
+ */
10
+ type ResolveContext = {
11
+ conditions: string[];
12
+ importAttributes: Record<string, string>;
13
+ parentURL?: string;
14
+ };
15
+ type ResolveResult = {
16
+ url: string;
17
+ shortCircuit?: boolean;
18
+ format?: string;
19
+ };
20
+ type NextResolve = (specifier: string, context: ResolveContext) => Promise<ResolveResult>;
21
+ /**
22
+ * Resolve hook - intercepts module resolution for @geekmidas/envkit
23
+ */
24
+ declare function resolve(specifier: string, context: ResolveContext, nextResolve: NextResolve): Promise<ResolveResult>;
25
+ //#endregion
26
+ export { resolve };
27
+ //# sourceMappingURL=sniffer-hooks.d.cts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sniffer-hooks.d.cts","names":[],"sources":["../../src/deploy/sniffer-hooks.ts"],"sourcesContent":[],"mappings":";;;AAwByB;AAIP;;;;;AASN,KAfP,cAAA,GAeO;EAKU,UAAO,EAAA,MAAA,EAAA;EAAA,gBAAA,EAlBV,MAkBU,CAAA,MAAA,EAAA,MAAA,CAAA;EAAA,SAEnB,CAAA,EAAA,MAAA;CAAc;KAhBnB,aAAA,GAkBM;EAAa,GAArB,EAAA,MAAA;EAAO,YAAA,CAAA,EAAA,OAAA;;;KAZL,WAAA,gCAEK,mBACL,QAAQ;;;;iBAKS,OAAA,6BAEZ,6BACI,cACX,QAAQ"}
@@ -0,0 +1,27 @@
1
+ //#region src/deploy/sniffer-hooks.d.ts
2
+ /**
3
+ * Module loader hooks for entry app sniffing.
4
+ *
5
+ * This module provides the resolve hook that intercepts '@geekmidas/envkit'
6
+ * imports and redirects them to the patched sniffer version.
7
+ *
8
+ * This file is registered via module.register() from sniffer-loader.ts.
9
+ */
10
+ type ResolveContext = {
11
+ conditions: string[];
12
+ importAttributes: Record<string, string>;
13
+ parentURL?: string;
14
+ };
15
+ type ResolveResult = {
16
+ url: string;
17
+ shortCircuit?: boolean;
18
+ format?: string;
19
+ };
20
+ type NextResolve = (specifier: string, context: ResolveContext) => Promise<ResolveResult>;
21
+ /**
22
+ * Resolve hook - intercepts module resolution for @geekmidas/envkit
23
+ */
24
+ declare function resolve(specifier: string, context: ResolveContext, nextResolve: NextResolve): Promise<ResolveResult>;
25
+ //#endregion
26
+ export { resolve };
27
+ //# sourceMappingURL=sniffer-hooks.d.mts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sniffer-hooks.d.mts","names":[],"sources":["../../src/deploy/sniffer-hooks.ts"],"sourcesContent":[],"mappings":";;;AAwByB;AAIP;;;;;AASN,KAfP,cAAA,GAeO;EAKU,UAAO,EAAA,MAAA,EAAA;EAAA,gBAAA,EAlBV,MAkBU,CAAA,MAAA,EAAA,MAAA,CAAA;EAAA,SAEnB,CAAA,EAAA,MAAA;CAAc;KAhBnB,aAAA,GAkBM;EAAa,GAArB,EAAA,MAAA;EAAO,YAAA,CAAA,EAAA,OAAA;;;KAZL,WAAA,gCAEK,mBACL,QAAQ;;;;iBAKS,OAAA,6BAEZ,6BACI,cACX,QAAQ"}
@@ -0,0 +1,24 @@
1
+ import { existsSync } from "node:fs";
2
+ import { dirname, join } from "node:path";
3
+ import { fileURLToPath } from "node:url";
4
+
5
+ //#region src/deploy/sniffer-hooks.ts
6
+ const __filename = fileURLToPath(import.meta.url);
7
+ const __dirname = dirname(__filename);
8
+ const mjsPath = join(__dirname, "sniffer-envkit-patch.mjs");
9
+ const tsPath = join(__dirname, "sniffer-envkit-patch.ts");
10
+ const patchedEnvkitPath = existsSync(mjsPath) ? mjsPath : tsPath;
11
+ /**
12
+ * Resolve hook - intercepts module resolution for @geekmidas/envkit
13
+ */
14
+ async function resolve(specifier, context, nextResolve) {
15
+ if (specifier === "@geekmidas/envkit") return {
16
+ url: `file://${patchedEnvkitPath}`,
17
+ shortCircuit: true
18
+ };
19
+ return nextResolve(specifier, context);
20
+ }
21
+
22
+ //#endregion
23
+ export { resolve };
24
+ //# sourceMappingURL=sniffer-hooks.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sniffer-hooks.mjs","names":["specifier: string","context: ResolveContext","nextResolve: NextResolve"],"sources":["../../src/deploy/sniffer-hooks.ts"],"sourcesContent":["/**\n * Module loader hooks for entry app sniffing.\n *\n * This module provides the resolve hook that intercepts '@geekmidas/envkit'\n * imports and redirects them to the patched sniffer version.\n *\n * This file is registered via module.register() from sniffer-loader.ts.\n */\n\nimport { existsSync } from 'node:fs';\nimport { dirname, join } from 'node:path';\nimport { fileURLToPath } from 'node:url';\n\n// Resolve path to the patched envkit module\nconst __filename = fileURLToPath(import.meta.url);\nconst __dirname = dirname(__filename);\n\n// Try .mjs first (production dist), then .ts (development)\nconst mjsPath = join(__dirname, 'sniffer-envkit-patch.mjs');\nconst tsPath = join(__dirname, 'sniffer-envkit-patch.ts');\nconst patchedEnvkitPath = existsSync(mjsPath) ? mjsPath : tsPath;\n\ntype ResolveContext = {\n\tconditions: string[];\n\timportAttributes: Record<string, string>;\n\tparentURL?: string;\n};\n\ntype ResolveResult = {\n\turl: string;\n\tshortCircuit?: boolean;\n\tformat?: string;\n};\n\ntype NextResolve = (\n\tspecifier: string,\n\tcontext: ResolveContext,\n) => Promise<ResolveResult>;\n\n/**\n * Resolve hook - intercepts module resolution for @geekmidas/envkit\n */\nexport async function resolve(\n\tspecifier: string,\n\tcontext: ResolveContext,\n\tnextResolve: NextResolve,\n): Promise<ResolveResult> {\n\t// Intercept @geekmidas/envkit imports\n\tif (specifier === '@geekmidas/envkit') {\n\t\treturn {\n\t\t\turl: `file://${patchedEnvkitPath}`,\n\t\t\tshortCircuit: true,\n\t\t};\n\t}\n\n\treturn nextResolve(specifier, context);\n}\n"],"mappings":";;;;;AAcA,MAAM,aAAa,cAAc,OAAO,KAAK,IAAI;AACjD,MAAM,YAAY,QAAQ,WAAW;AAGrC,MAAM,UAAU,KAAK,WAAW,2BAA2B;AAC3D,MAAM,SAAS,KAAK,WAAW,0BAA0B;AACzD,MAAM,oBAAoB,WAAW,QAAQ,GAAG,UAAU;;;;AAsB1D,eAAsB,QACrBA,WACAC,SACAC,aACyB;AAEzB,KAAI,cAAc,oBACjB,QAAO;EACN,MAAM,SAAS,kBAAkB;EACjC,cAAc;CACd;AAGF,QAAO,YAAY,WAAW,QAAQ;AACtC"}
@@ -0,0 +1,16 @@
1
+ const require_chunk = require('../chunk-CUT6urMc.cjs');
2
+ const node_fs = require_chunk.__toESM(require("node:fs"));
3
+ const node_path = require_chunk.__toESM(require("node:path"));
4
+ const node_url = require_chunk.__toESM(require("node:url"));
5
+ const node_module = require_chunk.__toESM(require("node:module"));
6
+
7
+ //#region src/deploy/sniffer-loader.ts
8
+ const __filename$1 = (0, node_url.fileURLToPath)(require("url").pathToFileURL(__filename).href);
9
+ const __dirname$1 = (0, node_path.dirname)(__filename$1);
10
+ const mjsPath = (0, node_path.join)(__dirname$1, "sniffer-hooks.mjs");
11
+ const tsPath = (0, node_path.join)(__dirname$1, "sniffer-hooks.ts");
12
+ const hooksPath = (0, node_fs.existsSync)(mjsPath) ? mjsPath : tsPath;
13
+ (0, node_module.register)((0, node_url.pathToFileURL)(hooksPath).href, require("url").pathToFileURL(__filename).href);
14
+
15
+ //#endregion
16
+ //# sourceMappingURL=sniffer-loader.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sniffer-loader.cjs","names":["__filename","__dirname"],"sources":["../../src/deploy/sniffer-loader.ts"],"sourcesContent":["/**\n * Node.js module loader registration for entry app sniffing.\n *\n * This module registers a custom loader hook that intercepts imports of\n * '@geekmidas/envkit' and replaces the EnvironmentParser with\n * SnifferEnvironmentParser, allowing us to capture which environment\n * variables an entry app accesses.\n *\n * Usage:\n * node --import tsx --import ./sniffer-loader.mjs ./sniffer-worker.mjs /path/to/entry.ts\n */\n\nimport { existsSync } from 'node:fs';\nimport { register } from 'node:module';\nimport { dirname, join } from 'node:path';\nimport { fileURLToPath, pathToFileURL } from 'node:url';\n\n// Resolve path to the loader hooks module\nconst __filename = fileURLToPath(import.meta.url);\nconst __dirname = dirname(__filename);\n\n// Try .mjs first (production dist), then .ts (development)\nconst mjsPath = join(__dirname, 'sniffer-hooks.mjs');\nconst tsPath = join(__dirname, 'sniffer-hooks.ts');\nconst hooksPath = existsSync(mjsPath) ? mjsPath : tsPath;\n\n// Register the loader hooks\nregister(pathToFileURL(hooksPath).href, import.meta.url);\n"],"mappings":";;;;;;;AAkBA,MAAMA,eAAa,0EAA8B;AACjD,MAAMC,cAAY,uBAAQD,aAAW;AAGrC,MAAM,UAAU,oBAAKC,aAAW,oBAAoB;AACpD,MAAM,SAAS,oBAAKA,aAAW,mBAAmB;AAClD,MAAM,YAAY,wBAAW,QAAQ,GAAG,UAAU;AAGlD,0BAAS,4BAAc,UAAU,CAAC,oDAAsB"}
@@ -0,0 +1 @@
1
+ export { };
@@ -0,0 +1 @@
1
+ export { };
@@ -0,0 +1,15 @@
1
+ import { register } from "node:module";
2
+ import { existsSync } from "node:fs";
3
+ import { dirname, join } from "node:path";
4
+ import { fileURLToPath, pathToFileURL } from "node:url";
5
+
6
+ //#region src/deploy/sniffer-loader.ts
7
+ const __filename = fileURLToPath(import.meta.url);
8
+ const __dirname = dirname(__filename);
9
+ const mjsPath = join(__dirname, "sniffer-hooks.mjs");
10
+ const tsPath = join(__dirname, "sniffer-hooks.ts");
11
+ const hooksPath = existsSync(mjsPath) ? mjsPath : tsPath;
12
+ register(pathToFileURL(hooksPath).href, import.meta.url);
13
+
14
+ //#endregion
15
+ //# sourceMappingURL=sniffer-loader.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sniffer-loader.mjs","names":[],"sources":["../../src/deploy/sniffer-loader.ts"],"sourcesContent":["/**\n * Node.js module loader registration for entry app sniffing.\n *\n * This module registers a custom loader hook that intercepts imports of\n * '@geekmidas/envkit' and replaces the EnvironmentParser with\n * SnifferEnvironmentParser, allowing us to capture which environment\n * variables an entry app accesses.\n *\n * Usage:\n * node --import tsx --import ./sniffer-loader.mjs ./sniffer-worker.mjs /path/to/entry.ts\n */\n\nimport { existsSync } from 'node:fs';\nimport { register } from 'node:module';\nimport { dirname, join } from 'node:path';\nimport { fileURLToPath, pathToFileURL } from 'node:url';\n\n// Resolve path to the loader hooks module\nconst __filename = fileURLToPath(import.meta.url);\nconst __dirname = dirname(__filename);\n\n// Try .mjs first (production dist), then .ts (development)\nconst mjsPath = join(__dirname, 'sniffer-hooks.mjs');\nconst tsPath = join(__dirname, 'sniffer-hooks.ts');\nconst hooksPath = existsSync(mjsPath) ? mjsPath : tsPath;\n\n// Register the loader hooks\nregister(pathToFileURL(hooksPath).href, import.meta.url);\n"],"mappings":";;;;;;AAkBA,MAAM,aAAa,cAAc,OAAO,KAAK,IAAI;AACjD,MAAM,YAAY,QAAQ,WAAW;AAGrC,MAAM,UAAU,KAAK,WAAW,oBAAoB;AACpD,MAAM,SAAS,KAAK,WAAW,mBAAmB;AAClD,MAAM,YAAY,WAAW,QAAQ,GAAG,UAAU;AAGlD,SAAS,cAAc,UAAU,CAAC,MAAM,OAAO,KAAK,IAAI"}
@@ -0,0 +1,42 @@
1
+ const require_chunk = require('../chunk-CUT6urMc.cjs');
2
+ const node_url = require_chunk.__toESM(require("node:url"));
3
+
4
+ //#region src/deploy/sniffer-worker.ts
5
+ const entryPath = process.argv[2];
6
+ if (!entryPath) {
7
+ console.log(JSON.stringify({
8
+ envVars: [],
9
+ error: "No entry file path provided"
10
+ }));
11
+ process.exit(1);
12
+ }
13
+ const validEntryPath = entryPath;
14
+ /**
15
+ * Main sniffing function
16
+ */
17
+ async function sniff() {
18
+ let error = null;
19
+ try {
20
+ const entryUrl = (0, node_url.pathToFileURL)(validEntryPath).href;
21
+ await import(entryUrl);
22
+ } catch (e) {
23
+ error = e instanceof Error ? e.message : String(e);
24
+ }
25
+ const sniffer = globalThis.__envSniffer;
26
+ const envVars = sniffer ? sniffer.getEnvironmentVariables() : [];
27
+ console.log(JSON.stringify({
28
+ envVars,
29
+ error
30
+ }));
31
+ }
32
+ process.on("unhandledRejection", () => {});
33
+ sniff().catch((e) => {
34
+ console.log(JSON.stringify({
35
+ envVars: [],
36
+ error: e.message || String(e)
37
+ }));
38
+ process.exit(1);
39
+ });
40
+
41
+ //#endregion
42
+ //# sourceMappingURL=sniffer-worker.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sniffer-worker.cjs","names":["validEntryPath: string","error: string | null"],"sources":["../../src/deploy/sniffer-worker.ts"],"sourcesContent":["/**\n * Subprocess worker for entry app sniffing.\n *\n * This script is executed in a subprocess with the sniffer-loader.ts\n * registered, which intercepts @geekmidas/envkit imports.\n *\n * Usage:\n * node --import tsx --import ./sniffer-loader.ts ./sniffer-worker.ts /path/to/entry.ts\n *\n * Output (JSON to stdout):\n * { \"envVars\": [\"PORT\", \"DATABASE_URL\", ...], \"error\": null }\n */\n\nimport { pathToFileURL } from 'node:url';\nimport type { SnifferEnvironmentParser } from '@geekmidas/envkit/sniffer';\n\n// Extend globalThis type for the sniffer instance\ndeclare global {\n\t// eslint-disable-next-line no-var\n\tvar __envSniffer: SnifferEnvironmentParser | undefined;\n}\n\n// Get the entry file path from command line args\nconst entryPath = process.argv[2] as string | undefined;\n\nif (!entryPath) {\n\tconsole.log(\n\t\tJSON.stringify({ envVars: [], error: 'No entry file path provided' }),\n\t);\n\tprocess.exit(1);\n}\n\n// entryPath is guaranteed to be defined after the check above\nconst validEntryPath: string = entryPath;\n\n/**\n * Main sniffing function\n */\nasync function sniff(): Promise<void> {\n\tlet error: string | null = null;\n\n\ttry {\n\t\t// Import the entry file - this triggers:\n\t\t// 1. Entry imports config module\n\t\t// 2. Config module imports @geekmidas/envkit (intercepted by loader)\n\t\t// 3. Config creates EnvironmentParser (actually SnifferEnvironmentParser)\n\t\t// 4. Config calls .create() and .parse()\n\t\t// 5. Sniffer captures all accessed env var names\n\t\tconst entryUrl = pathToFileURL(validEntryPath).href;\n\t\tawait import(entryUrl);\n\t} catch (e) {\n\t\t// Entry may fail due to missing env vars or other runtime issues.\n\t\t// This is expected - we still capture the env vars that were accessed.\n\t\terror = e instanceof Error ? e.message : String(e);\n\t}\n\n\t// Retrieve captured env vars from the global sniffer\n\tconst sniffer = globalThis.__envSniffer;\n\tconst envVars = sniffer ? sniffer.getEnvironmentVariables() : [];\n\n\t// Output result as JSON\n\tconsole.log(JSON.stringify({ envVars, error }));\n}\n\n// Handle unhandled rejections (fire-and-forget promises)\nprocess.on('unhandledRejection', () => {\n\t// Silently ignore - we only care about env var capture\n});\n\n// Run the sniffer\nsniff().catch((e) => {\n\tconsole.log(JSON.stringify({ envVars: [], error: e.message || String(e) }));\n\tprocess.exit(1);\n});\n"],"mappings":";;;;AAuBA,MAAM,YAAY,QAAQ,KAAK;AAE/B,KAAK,WAAW;AACf,SAAQ,IACP,KAAK,UAAU;EAAE,SAAS,CAAE;EAAE,OAAO;CAA+B,EAAC,CACrE;AACD,SAAQ,KAAK,EAAE;AACf;AAGD,MAAMA,iBAAyB;;;;AAK/B,eAAe,QAAuB;CACrC,IAAIC,QAAuB;AAE3B,KAAI;EAOH,MAAM,WAAW,4BAAc,eAAe,CAAC;AAC/C,QAAM,OAAO;CACb,SAAQ,GAAG;AAGX,UAAQ,aAAa,QAAQ,EAAE,UAAU,OAAO,EAAE;CAClD;CAGD,MAAM,UAAU,WAAW;CAC3B,MAAM,UAAU,UAAU,QAAQ,yBAAyB,GAAG,CAAE;AAGhE,SAAQ,IAAI,KAAK,UAAU;EAAE;EAAS;CAAO,EAAC,CAAC;AAC/C;AAGD,QAAQ,GAAG,sBAAsB,MAAM,CAEtC,EAAC;AAGF,OAAO,CAAC,MAAM,CAAC,MAAM;AACpB,SAAQ,IAAI,KAAK,UAAU;EAAE,SAAS,CAAE;EAAE,OAAO,EAAE,WAAW,OAAO,EAAE;CAAE,EAAC,CAAC;AAC3E,SAAQ,KAAK,EAAE;AACf,EAAC"}
@@ -0,0 +1,9 @@
1
+ import { SnifferEnvironmentParser } from "@geekmidas/envkit/sniffer";
2
+
3
+ //#region src/deploy/sniffer-worker.d.ts
4
+
5
+ declare global {
6
+ var __envSniffer: SnifferEnvironmentParser | undefined;
7
+ }
8
+ //# sourceMappingURL=sniffer-worker.d.ts.map
9
+ //# sourceMappingURL=sniffer-worker.d.cts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sniffer-worker.d.cts","names":[],"sources":["../../src/deploy/sniffer-worker.ts"],"sourcesContent":[],"mappings":";;;;;oBAmBmB"}
@@ -0,0 +1,9 @@
1
+ import { SnifferEnvironmentParser } from "@geekmidas/envkit/sniffer";
2
+
3
+ //#region src/deploy/sniffer-worker.d.ts
4
+
5
+ declare global {
6
+ var __envSniffer: SnifferEnvironmentParser | undefined;
7
+ }
8
+ //# sourceMappingURL=sniffer-worker.d.ts.map
9
+ //# sourceMappingURL=sniffer-worker.d.mts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sniffer-worker.d.mts","names":[],"sources":["../../src/deploy/sniffer-worker.ts"],"sourcesContent":[],"mappings":";;;;;oBAmBmB"}
@@ -0,0 +1,41 @@
1
+ import { pathToFileURL } from "node:url";
2
+
3
+ //#region src/deploy/sniffer-worker.ts
4
+ const entryPath = process.argv[2];
5
+ if (!entryPath) {
6
+ console.log(JSON.stringify({
7
+ envVars: [],
8
+ error: "No entry file path provided"
9
+ }));
10
+ process.exit(1);
11
+ }
12
+ const validEntryPath = entryPath;
13
+ /**
14
+ * Main sniffing function
15
+ */
16
+ async function sniff() {
17
+ let error = null;
18
+ try {
19
+ const entryUrl = pathToFileURL(validEntryPath).href;
20
+ await import(entryUrl);
21
+ } catch (e) {
22
+ error = e instanceof Error ? e.message : String(e);
23
+ }
24
+ const sniffer = globalThis.__envSniffer;
25
+ const envVars = sniffer ? sniffer.getEnvironmentVariables() : [];
26
+ console.log(JSON.stringify({
27
+ envVars,
28
+ error
29
+ }));
30
+ }
31
+ process.on("unhandledRejection", () => {});
32
+ sniff().catch((e) => {
33
+ console.log(JSON.stringify({
34
+ envVars: [],
35
+ error: e.message || String(e)
36
+ }));
37
+ process.exit(1);
38
+ });
39
+
40
+ //#endregion
41
+ //# sourceMappingURL=sniffer-worker.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sniffer-worker.mjs","names":["validEntryPath: string","error: string | null"],"sources":["../../src/deploy/sniffer-worker.ts"],"sourcesContent":["/**\n * Subprocess worker for entry app sniffing.\n *\n * This script is executed in a subprocess with the sniffer-loader.ts\n * registered, which intercepts @geekmidas/envkit imports.\n *\n * Usage:\n * node --import tsx --import ./sniffer-loader.ts ./sniffer-worker.ts /path/to/entry.ts\n *\n * Output (JSON to stdout):\n * { \"envVars\": [\"PORT\", \"DATABASE_URL\", ...], \"error\": null }\n */\n\nimport { pathToFileURL } from 'node:url';\nimport type { SnifferEnvironmentParser } from '@geekmidas/envkit/sniffer';\n\n// Extend globalThis type for the sniffer instance\ndeclare global {\n\t// eslint-disable-next-line no-var\n\tvar __envSniffer: SnifferEnvironmentParser | undefined;\n}\n\n// Get the entry file path from command line args\nconst entryPath = process.argv[2] as string | undefined;\n\nif (!entryPath) {\n\tconsole.log(\n\t\tJSON.stringify({ envVars: [], error: 'No entry file path provided' }),\n\t);\n\tprocess.exit(1);\n}\n\n// entryPath is guaranteed to be defined after the check above\nconst validEntryPath: string = entryPath;\n\n/**\n * Main sniffing function\n */\nasync function sniff(): Promise<void> {\n\tlet error: string | null = null;\n\n\ttry {\n\t\t// Import the entry file - this triggers:\n\t\t// 1. Entry imports config module\n\t\t// 2. Config module imports @geekmidas/envkit (intercepted by loader)\n\t\t// 3. Config creates EnvironmentParser (actually SnifferEnvironmentParser)\n\t\t// 4. Config calls .create() and .parse()\n\t\t// 5. Sniffer captures all accessed env var names\n\t\tconst entryUrl = pathToFileURL(validEntryPath).href;\n\t\tawait import(entryUrl);\n\t} catch (e) {\n\t\t// Entry may fail due to missing env vars or other runtime issues.\n\t\t// This is expected - we still capture the env vars that were accessed.\n\t\terror = e instanceof Error ? e.message : String(e);\n\t}\n\n\t// Retrieve captured env vars from the global sniffer\n\tconst sniffer = globalThis.__envSniffer;\n\tconst envVars = sniffer ? sniffer.getEnvironmentVariables() : [];\n\n\t// Output result as JSON\n\tconsole.log(JSON.stringify({ envVars, error }));\n}\n\n// Handle unhandled rejections (fire-and-forget promises)\nprocess.on('unhandledRejection', () => {\n\t// Silently ignore - we only care about env var capture\n});\n\n// Run the sniffer\nsniff().catch((e) => {\n\tconsole.log(JSON.stringify({ envVars: [], error: e.message || String(e) }));\n\tprocess.exit(1);\n});\n"],"mappings":";;;AAuBA,MAAM,YAAY,QAAQ,KAAK;AAE/B,KAAK,WAAW;AACf,SAAQ,IACP,KAAK,UAAU;EAAE,SAAS,CAAE;EAAE,OAAO;CAA+B,EAAC,CACrE;AACD,SAAQ,KAAK,EAAE;AACf;AAGD,MAAMA,iBAAyB;;;;AAK/B,eAAe,QAAuB;CACrC,IAAIC,QAAuB;AAE3B,KAAI;EAOH,MAAM,WAAW,cAAc,eAAe,CAAC;AAC/C,QAAM,OAAO;CACb,SAAQ,GAAG;AAGX,UAAQ,aAAa,QAAQ,EAAE,UAAU,OAAO,EAAE;CAClD;CAGD,MAAM,UAAU,WAAW;CAC3B,MAAM,UAAU,UAAU,QAAQ,yBAAyB,GAAG,CAAE;AAGhE,SAAQ,IAAI,KAAK,UAAU;EAAE;EAAS;CAAO,EAAC,CAAC;AAC/C;AAGD,QAAQ,GAAG,sBAAsB,MAAM,CAEtC,EAAC;AAGF,OAAO,CAAC,MAAM,CAAC,MAAM;AACpB,SAAQ,IAAI,KAAK,UAAU;EAAE,SAAS,CAAE;EAAE,OAAO,EAAE,WAAW,OAAO,EAAE;CAAE,EAAC,CAAC;AAC3E,SAAQ,KAAK,EAAE;AACf,EAAC"}
@@ -260,10 +260,10 @@ var DokployApi = class {
260
260
  projectId,
261
261
  environmentId,
262
262
  appName: options?.appName ?? name.toLowerCase().replace(/[^a-z0-9-]/g, "-"),
263
- databaseName: options?.databaseName ?? "app",
263
+ databaseName: options?.databaseName,
264
264
  databaseUser: options?.databaseUser ?? "postgres",
265
265
  databasePassword: options?.databasePassword,
266
- dockerImage: options?.dockerImage ?? "postgres:16-alpine",
266
+ dockerImage: options?.dockerImage ?? "postgres:18",
267
267
  description: options?.description ?? `Postgres database for ${name}`
268
268
  });
269
269
  }
@@ -349,7 +349,7 @@ var DokployApi = class {
349
349
  environmentId,
350
350
  appName: options?.appName ?? name.toLowerCase().replace(/[^a-z0-9-]/g, "-"),
351
351
  databasePassword: options?.databasePassword,
352
- dockerImage: options?.dockerImage ?? "redis:7-alpine",
352
+ dockerImage: options?.dockerImage ?? "redis:8",
353
353
  description: options?.description ?? `Redis instance for ${name}`
354
354
  });
355
355
  }
@@ -464,4 +464,4 @@ var DokployApi = class {
464
464
 
465
465
  //#endregion
466
466
  export { DokployApi, DokployApiError };
467
- //# sourceMappingURL=dokploy-api-DvzIDxTj.mjs.map
467
+ //# sourceMappingURL=dokploy-api-94KzmTVf.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"dokploy-api-94KzmTVf.mjs","names":["message: string","status: number","statusText: string","issues?: Array<{ message: string }>","options: DokployApiOptions","endpoint: string","body?: Record<string, unknown>","method: 'GET' | 'POST' | 'PUT' | 'DELETE'","issues: Array<{ message: string }> | undefined","projectId: string","name: string","description?: string","environmentId: string","applicationId: string","updates: Partial<DokployApplicationUpdate>","env: string","dockerImage: string","options?: {\n\t\t\t/** Registry ID in Dokploy (for pre-configured registries) */\n\t\t\tregistryId?: string;\n\t\t\t/** Registry username (for direct auth) */\n\t\t\tusername?: string;\n\t\t\t/** Registry password (for direct auth) */\n\t\t\tpassword?: string;\n\t\t\t/** Registry URL (for direct auth, e.g., ghcr.io) */\n\t\t\tregistryUrl?: string;\n\t\t}","registryName: string","registryUrl: string","username: string","password: string","options?: {\n\t\t\timagePrefix?: string;\n\t\t}","registryId: string","updates: Partial<{\n\t\t\tregistryName: string;\n\t\t\tregistryUrl: string;\n\t\t\tusername: string;\n\t\t\tpassword: string;\n\t\t\timagePrefix: string;\n\t\t}>","options?: {\n\t\t\tappName?: string;\n\t\t\tdatabaseName?: string;\n\t\t\tdatabaseUser?: string;\n\t\t\tdatabasePassword?: string;\n\t\t\tdockerImage?: string;\n\t\t\tdescription?: string;\n\t\t}","options?: {\n\t\t\tdatabaseName?: string;\n\t\t\tdatabasePassword?: string;\n\t\t}","postgresId: string","externalPort: number | null","updates: Partial<DokployPostgresUpdate>","options?: {\n\t\t\tappName?: string;\n\t\t\tdatabasePassword?: string;\n\t\t\tdockerImage?: string;\n\t\t\tdescription?: string;\n\t\t}","options?: {\n\t\t\tdatabasePassword?: string;\n\t\t}","redisId: string","updates: Partial<DokployRedisUpdate>","options: DokployDomainCreate","domainId: string","updates: Partial<DokployDomainCreate>","domain: string","appName: string","serverId?: string"],"sources":["../src/deploy/dokploy-api.ts"],"sourcesContent":["/**\n * Centralized Dokploy API client\n *\n * Handles authentication, error handling, and provides typed methods for all Dokploy API endpoints.\n */\n\nexport interface DokployApiOptions {\n\t/** Dokploy server URL (e.g., https://dokploy.example.com) */\n\tbaseUrl: string;\n\t/** API token for authentication */\n\ttoken: string;\n}\n\nexport interface DokployErrorResponse {\n\tmessage?: string;\n\tissues?: Array<{ message: string }>;\n}\n\nexport class DokployApiError extends Error {\n\tconstructor(\n\t\tmessage: string,\n\t\tpublic status: number,\n\t\tpublic statusText: string,\n\t\tpublic issues?: Array<{ message: string }>,\n\t) {\n\t\tsuper(message);\n\t\tthis.name = 'DokployApiError';\n\t}\n}\n\n/**\n * Dokploy API client\n */\nexport class DokployApi {\n\tprivate baseUrl: string;\n\tprivate token: string;\n\n\tconstructor(options: DokployApiOptions) {\n\t\tthis.baseUrl = options.baseUrl.replace(/\\/$/, ''); // Remove trailing slash\n\t\tthis.token = options.token;\n\t}\n\n\t/**\n\t * Make a GET request to the Dokploy API\n\t */\n\tasync get<T>(endpoint: string): Promise<T> {\n\t\treturn this.request<T>('GET', endpoint);\n\t}\n\n\t/**\n\t * Make a POST request to the Dokploy API\n\t */\n\tasync post<T>(endpoint: string, body?: Record<string, unknown>): Promise<T> {\n\t\treturn this.request<T>('POST', endpoint, body);\n\t}\n\n\t/**\n\t * Make a request to the Dokploy API\n\t */\n\tprivate async request<T>(\n\t\tmethod: 'GET' | 'POST' | 'PUT' | 'DELETE',\n\t\tendpoint: string,\n\t\tbody?: Record<string, unknown>,\n\t): Promise<T> {\n\t\tconst url = `${this.baseUrl}/api/${endpoint}`;\n\n\t\tconst response = await fetch(url, {\n\t\t\tmethod,\n\t\t\theaders: {\n\t\t\t\t'Content-Type': 'application/json',\n\t\t\t\t'x-api-key': this.token,\n\t\t\t},\n\t\t\tbody: body ? JSON.stringify(body) : undefined,\n\t\t});\n\n\t\tif (!response.ok) {\n\t\t\tlet errorMessage = `Dokploy API error: ${response.status} ${response.statusText}`;\n\t\t\tlet issues: Array<{ message: string }> | undefined;\n\n\t\t\ttry {\n\t\t\t\tconst errorBody = (await response.json()) as DokployErrorResponse;\n\t\t\t\tif (errorBody.message) {\n\t\t\t\t\terrorMessage = `Dokploy API error: ${errorBody.message}`;\n\t\t\t\t}\n\t\t\t\tif (errorBody.issues?.length) {\n\t\t\t\t\tissues = errorBody.issues;\n\t\t\t\t\terrorMessage += `\\n Issues: ${errorBody.issues.map((i) => i.message).join(', ')}`;\n\t\t\t\t}\n\t\t\t} catch {\n\t\t\t\t// Ignore JSON parse errors\n\t\t\t}\n\n\t\t\tthrow new DokployApiError(\n\t\t\t\terrorMessage,\n\t\t\t\tresponse.status,\n\t\t\t\tresponse.statusText,\n\t\t\t\tissues,\n\t\t\t);\n\t\t}\n\n\t\t// Handle empty responses (204 No Content or empty body)\n\t\tconst text = await response.text();\n\t\tif (!text || text.trim() === '') {\n\t\t\treturn undefined as T;\n\t\t}\n\t\treturn JSON.parse(text) as T;\n\t}\n\n\t/**\n\t * Validate the API token by making a test request\n\t */\n\tasync validateToken(): Promise<boolean> {\n\t\ttry {\n\t\t\tawait this.get('project.all');\n\t\t\treturn true;\n\t\t} catch {\n\t\t\treturn false;\n\t\t}\n\t}\n\n\t// ============================================\n\t// Project endpoints\n\t// ============================================\n\n\t/**\n\t * List all projects\n\t */\n\tasync listProjects(): Promise<DokployProject[]> {\n\t\treturn this.get<DokployProject[]>('project.all');\n\t}\n\n\t/**\n\t * Get a single project by ID\n\t */\n\tasync getProject(projectId: string): Promise<DokployProjectDetails> {\n\t\treturn this.get<DokployProjectDetails>(\n\t\t\t`project.one?projectId=${projectId}`,\n\t\t);\n\t}\n\n\t/**\n\t * Create a new project\n\t */\n\tasync createProject(\n\t\tname: string,\n\t\tdescription?: string,\n\t): Promise<{ project: DokployProject; environment: DokployEnvironment }> {\n\t\treturn this.post<{\n\t\t\tproject: DokployProject;\n\t\t\tenvironment: DokployEnvironment;\n\t\t}>('project.create', {\n\t\t\tname,\n\t\t\tdescription: description ?? `Created by gkm CLI`,\n\t\t});\n\t}\n\n\t// ============================================\n\t// Environment endpoints\n\t// ============================================\n\n\t/**\n\t * Create an environment in a project\n\t */\n\tasync createEnvironment(\n\t\tprojectId: string,\n\t\tname: string,\n\t\tdescription?: string,\n\t): Promise<DokployEnvironment> {\n\t\treturn this.post<DokployEnvironment>('environment.create', {\n\t\t\tprojectId,\n\t\t\tname,\n\t\t\tdescription: description ?? `${name} environment`,\n\t\t});\n\t}\n\n\t// ============================================\n\t// Application endpoints\n\t// ============================================\n\n\t/**\n\t * List all applications in a project\n\t */\n\tasync listApplications(projectId: string): Promise<DokployApplication[]> {\n\t\ttry {\n\t\t\treturn await this.get<DokployApplication[]>(\n\t\t\t\t`application.all?projectId=${projectId}`,\n\t\t\t);\n\t\t} catch {\n\t\t\t// Fallback: endpoint might not exist in older Dokploy versions\n\t\t\treturn [];\n\t\t}\n\t}\n\n\t/**\n\t * Find an application by name in a project\n\t */\n\tasync findApplicationByName(\n\t\tprojectId: string,\n\t\tname: string,\n\t): Promise<DokployApplication | undefined> {\n\t\tconst applications = await this.listApplications(projectId);\n\t\tconst normalizedName = name.toLowerCase().replace(/[^a-z0-9-]/g, '-');\n\t\treturn applications.find(\n\t\t\t(app) => app.name === name || app.appName === normalizedName,\n\t\t);\n\t}\n\n\t/**\n\t * Create a new application\n\t */\n\tasync createApplication(\n\t\tname: string,\n\t\tprojectId: string,\n\t\tenvironmentId: string,\n\t): Promise<DokployApplication> {\n\t\treturn this.post<DokployApplication>('application.create', {\n\t\t\tname,\n\t\t\tprojectId,\n\t\t\tenvironmentId,\n\t\t\tappName: name.toLowerCase().replace(/[^a-z0-9-]/g, '-'),\n\t\t});\n\t}\n\n\t/**\n\t * Find or create an application by name\n\t */\n\tasync findOrCreateApplication(\n\t\tname: string,\n\t\tprojectId: string,\n\t\tenvironmentId: string,\n\t): Promise<{ application: DokployApplication; created: boolean }> {\n\t\tconst existing = await this.findApplicationByName(projectId, name);\n\t\tif (existing) {\n\t\t\treturn { application: existing, created: false };\n\t\t}\n\t\tconst application = await this.createApplication(\n\t\t\tname,\n\t\t\tprojectId,\n\t\t\tenvironmentId,\n\t\t);\n\t\treturn { application, created: true };\n\t}\n\n\t/**\n\t * Get an application by ID\n\t */\n\tasync getApplication(\n\t\tapplicationId: string,\n\t): Promise<DokployApplication | null> {\n\t\ttry {\n\t\t\treturn await this.get<DokployApplication>(\n\t\t\t\t`application.one?applicationId=${applicationId}`,\n\t\t\t);\n\t\t} catch {\n\t\t\t// Application not found\n\t\t\treturn null;\n\t\t}\n\t}\n\n\t/**\n\t * Update an application\n\t */\n\tasync updateApplication(\n\t\tapplicationId: string,\n\t\tupdates: Partial<DokployApplicationUpdate>,\n\t): Promise<void> {\n\t\tawait this.post('application.update', {\n\t\t\tapplicationId,\n\t\t\t...updates,\n\t\t});\n\t}\n\n\t/**\n\t * Save environment variables for an application\n\t */\n\tasync saveApplicationEnv(applicationId: string, env: string): Promise<void> {\n\t\tawait this.post('application.saveEnvironment', {\n\t\t\tapplicationId,\n\t\t\tenv,\n\t\t});\n\t}\n\n\t/**\n\t * Configure application to use Docker provider (pull from registry)\n\t *\n\t * For private registries, either:\n\t * - Use `registryId` if the registry is configured in Dokploy\n\t * - Or provide `username`, `password`, and `registryUrl` directly\n\t */\n\tasync saveDockerProvider(\n\t\tapplicationId: string,\n\t\tdockerImage: string,\n\t\toptions?: {\n\t\t\t/** Registry ID in Dokploy (for pre-configured registries) */\n\t\t\tregistryId?: string;\n\t\t\t/** Registry username (for direct auth) */\n\t\t\tusername?: string;\n\t\t\t/** Registry password (for direct auth) */\n\t\t\tpassword?: string;\n\t\t\t/** Registry URL (for direct auth, e.g., ghcr.io) */\n\t\t\tregistryUrl?: string;\n\t\t},\n\t): Promise<void> {\n\t\tawait this.post('application.saveDockerProvider', {\n\t\t\tapplicationId,\n\t\t\tdockerImage,\n\t\t\t...options,\n\t\t});\n\t}\n\n\t/**\n\t * Deploy an application\n\t */\n\tasync deployApplication(applicationId: string): Promise<void> {\n\t\tawait this.post('application.deploy', { applicationId });\n\t}\n\n\t// ============================================\n\t// Registry endpoints\n\t// ============================================\n\n\t/**\n\t * List all registries\n\t */\n\tasync listRegistries(): Promise<DokployRegistry[]> {\n\t\treturn this.get<DokployRegistry[]>('registry.all');\n\t}\n\n\t/**\n\t * Create a new registry\n\t */\n\tasync createRegistry(\n\t\tregistryName: string,\n\t\tregistryUrl: string,\n\t\tusername: string,\n\t\tpassword: string,\n\t\toptions?: {\n\t\t\timagePrefix?: string;\n\t\t},\n\t): Promise<DokployRegistry> {\n\t\treturn this.post<DokployRegistry>('registry.create', {\n\t\t\tregistryName,\n\t\t\tregistryUrl,\n\t\t\tusername,\n\t\t\tpassword,\n\t\t\timagePrefix: options?.imagePrefix,\n\t\t});\n\t}\n\n\t/**\n\t * Get a registry by ID\n\t */\n\tasync getRegistry(registryId: string): Promise<DokployRegistry> {\n\t\treturn this.get<DokployRegistry>(`registry.one?registryId=${registryId}`);\n\t}\n\n\t/**\n\t * Update a registry\n\t */\n\tasync updateRegistry(\n\t\tregistryId: string,\n\t\tupdates: Partial<{\n\t\t\tregistryName: string;\n\t\t\tregistryUrl: string;\n\t\t\tusername: string;\n\t\t\tpassword: string;\n\t\t\timagePrefix: string;\n\t\t}>,\n\t): Promise<void> {\n\t\tawait this.post('registry.update', { registryId, ...updates });\n\t}\n\n\t/**\n\t * Delete a registry\n\t */\n\tasync deleteRegistry(registryId: string): Promise<void> {\n\t\tawait this.post('registry.remove', { registryId });\n\t}\n\n\t// ============================================\n\t// Postgres endpoints\n\t// ============================================\n\n\t/**\n\t * List all Postgres databases in a project\n\t */\n\tasync listPostgres(projectId: string): Promise<DokployPostgres[]> {\n\t\ttry {\n\t\t\treturn await this.get<DokployPostgres[]>(\n\t\t\t\t`postgres.all?projectId=${projectId}`,\n\t\t\t);\n\t\t} catch {\n\t\t\t// Fallback: endpoint might not exist in older Dokploy versions\n\t\t\treturn [];\n\t\t}\n\t}\n\n\t/**\n\t * Find a Postgres database by name in a project\n\t */\n\tasync findPostgresByName(\n\t\tprojectId: string,\n\t\tname: string,\n\t): Promise<DokployPostgres | undefined> {\n\t\tconst databases = await this.listPostgres(projectId);\n\t\tconst normalizedName = name.toLowerCase().replace(/[^a-z0-9-]/g, '-');\n\t\treturn databases.find(\n\t\t\t(db) => db.name === name || db.appName === normalizedName,\n\t\t);\n\t}\n\n\t/**\n\t * Create a new Postgres database\n\t */\n\tasync createPostgres(\n\t\tname: string,\n\t\tprojectId: string,\n\t\tenvironmentId: string,\n\t\toptions?: {\n\t\t\tappName?: string;\n\t\t\tdatabaseName?: string;\n\t\t\tdatabaseUser?: string;\n\t\t\tdatabasePassword?: string;\n\t\t\tdockerImage?: string;\n\t\t\tdescription?: string;\n\t\t},\n\t): Promise<DokployPostgres> {\n\t\treturn this.post<DokployPostgres>('postgres.create', {\n\t\t\tname,\n\t\t\tprojectId,\n\t\t\tenvironmentId,\n\t\t\tappName:\n\t\t\t\toptions?.appName ?? name.toLowerCase().replace(/[^a-z0-9-]/g, '-'),\n\t\t\tdatabaseName: options?.databaseName,\n\t\t\tdatabaseUser: options?.databaseUser ?? 'postgres',\n\t\t\tdatabasePassword: options?.databasePassword,\n\t\t\tdockerImage: options?.dockerImage ?? 'postgres:18',\n\t\t\tdescription: options?.description ?? `Postgres database for ${name}`,\n\t\t});\n\t}\n\n\t/**\n\t * Find or create a Postgres database by name\n\t */\n\tasync findOrCreatePostgres(\n\t\tname: string,\n\t\tprojectId: string,\n\t\tenvironmentId: string,\n\t\toptions?: {\n\t\t\tdatabaseName?: string;\n\t\t\tdatabasePassword?: string;\n\t\t},\n\t): Promise<{ postgres: DokployPostgres; created: boolean }> {\n\t\tconst existing = await this.findPostgresByName(projectId, name);\n\t\tif (existing) {\n\t\t\treturn { postgres: existing, created: false };\n\t\t}\n\t\tconst postgres = await this.createPostgres(\n\t\t\tname,\n\t\t\tprojectId,\n\t\t\tenvironmentId,\n\t\t\toptions,\n\t\t);\n\t\treturn { postgres, created: true };\n\t}\n\n\t/**\n\t * Get a Postgres database by ID\n\t */\n\tasync getPostgres(postgresId: string): Promise<DokployPostgres> {\n\t\treturn this.get<DokployPostgres>(`postgres.one?postgresId=${postgresId}`);\n\t}\n\n\t/**\n\t * Deploy a Postgres database\n\t */\n\tasync deployPostgres(postgresId: string): Promise<void> {\n\t\tawait this.post('postgres.deploy', { postgresId });\n\t}\n\n\t/**\n\t * Save environment variables for Postgres\n\t */\n\tasync savePostgresEnv(postgresId: string, env: string): Promise<void> {\n\t\tawait this.post('postgres.saveEnvironment', { postgresId, env });\n\t}\n\n\t/**\n\t * Set external port for Postgres (for external access)\n\t */\n\tasync savePostgresExternalPort(\n\t\tpostgresId: string,\n\t\texternalPort: number | null,\n\t): Promise<void> {\n\t\tawait this.post('postgres.saveExternalPort', { postgresId, externalPort });\n\t}\n\n\t/**\n\t * Update Postgres configuration\n\t */\n\tasync updatePostgres(\n\t\tpostgresId: string,\n\t\tupdates: Partial<DokployPostgresUpdate>,\n\t): Promise<void> {\n\t\tawait this.post('postgres.update', { postgresId, ...updates });\n\t}\n\n\t// ============================================\n\t// Redis endpoints\n\t// ============================================\n\n\t/**\n\t * List all Redis instances in a project\n\t */\n\tasync listRedis(projectId: string): Promise<DokployRedis[]> {\n\t\ttry {\n\t\t\treturn await this.get<DokployRedis[]>(`redis.all?projectId=${projectId}`);\n\t\t} catch {\n\t\t\t// Fallback: endpoint might not exist in older Dokploy versions\n\t\t\treturn [];\n\t\t}\n\t}\n\n\t/**\n\t * Find a Redis instance by name in a project\n\t */\n\tasync findRedisByName(\n\t\tprojectId: string,\n\t\tname: string,\n\t): Promise<DokployRedis | undefined> {\n\t\tconst instances = await this.listRedis(projectId);\n\t\tconst normalizedName = name.toLowerCase().replace(/[^a-z0-9-]/g, '-');\n\t\treturn instances.find(\n\t\t\t(redis) => redis.name === name || redis.appName === normalizedName,\n\t\t);\n\t}\n\n\t/**\n\t * Create a new Redis instance\n\t */\n\tasync createRedis(\n\t\tname: string,\n\t\tprojectId: string,\n\t\tenvironmentId: string,\n\t\toptions?: {\n\t\t\tappName?: string;\n\t\t\tdatabasePassword?: string;\n\t\t\tdockerImage?: string;\n\t\t\tdescription?: string;\n\t\t},\n\t): Promise<DokployRedis> {\n\t\treturn this.post<DokployRedis>('redis.create', {\n\t\t\tname,\n\t\t\tprojectId,\n\t\t\tenvironmentId,\n\t\t\tappName:\n\t\t\t\toptions?.appName ?? name.toLowerCase().replace(/[^a-z0-9-]/g, '-'),\n\t\t\tdatabasePassword: options?.databasePassword,\n\t\t\tdockerImage: options?.dockerImage ?? 'redis:8',\n\t\t\tdescription: options?.description ?? `Redis instance for ${name}`,\n\t\t});\n\t}\n\n\t/**\n\t * Find or create a Redis instance by name\n\t */\n\tasync findOrCreateRedis(\n\t\tname: string,\n\t\tprojectId: string,\n\t\tenvironmentId: string,\n\t\toptions?: {\n\t\t\tdatabasePassword?: string;\n\t\t},\n\t): Promise<{ redis: DokployRedis; created: boolean }> {\n\t\tconst existing = await this.findRedisByName(projectId, name);\n\t\tif (existing) {\n\t\t\treturn { redis: existing, created: false };\n\t\t}\n\t\tconst redis = await this.createRedis(\n\t\t\tname,\n\t\t\tprojectId,\n\t\t\tenvironmentId,\n\t\t\toptions,\n\t\t);\n\t\treturn { redis, created: true };\n\t}\n\n\t/**\n\t * Get a Redis instance by ID\n\t */\n\tasync getRedis(redisId: string): Promise<DokployRedis> {\n\t\treturn this.get<DokployRedis>(`redis.one?redisId=${redisId}`);\n\t}\n\n\t/**\n\t * Deploy a Redis instance\n\t */\n\tasync deployRedis(redisId: string): Promise<void> {\n\t\tawait this.post('redis.deploy', { redisId });\n\t}\n\n\t/**\n\t * Save environment variables for Redis\n\t */\n\tasync saveRedisEnv(redisId: string, env: string): Promise<void> {\n\t\tawait this.post('redis.saveEnvironment', { redisId, env });\n\t}\n\n\t/**\n\t * Set external port for Redis (for external access)\n\t */\n\tasync saveRedisExternalPort(\n\t\tredisId: string,\n\t\texternalPort: number | null,\n\t): Promise<void> {\n\t\tawait this.post('redis.saveExternalPort', { redisId, externalPort });\n\t}\n\n\t/**\n\t * Update Redis configuration\n\t */\n\tasync updateRedis(\n\t\tredisId: string,\n\t\tupdates: Partial<DokployRedisUpdate>,\n\t): Promise<void> {\n\t\tawait this.post('redis.update', { redisId, ...updates });\n\t}\n\n\t// ============================================\n\t// Domain endpoints\n\t// ============================================\n\n\t/**\n\t * Create a new domain for an application\n\t */\n\tasync createDomain(options: DokployDomainCreate): Promise<DokployDomain> {\n\t\treturn this.post<DokployDomain>(\n\t\t\t'domain.create',\n\t\t\toptions as unknown as Record<string, unknown>,\n\t\t);\n\t}\n\n\t/**\n\t * Update an existing domain\n\t */\n\tasync updateDomain(\n\t\tdomainId: string,\n\t\tupdates: Partial<DokployDomainCreate>,\n\t): Promise<void> {\n\t\tawait this.post('domain.update', { domainId, ...updates });\n\t}\n\n\t/**\n\t * Delete a domain\n\t */\n\tasync deleteDomain(domainId: string): Promise<void> {\n\t\tawait this.post('domain.delete', { domainId });\n\t}\n\n\t/**\n\t * Get a domain by ID\n\t */\n\tasync getDomain(domainId: string): Promise<DokployDomain> {\n\t\treturn this.get<DokployDomain>(`domain.one?domainId=${domainId}`);\n\t}\n\n\t/**\n\t * Get all domains for an application\n\t */\n\tasync getDomainsByApplicationId(\n\t\tapplicationId: string,\n\t): Promise<DokployDomain[]> {\n\t\treturn this.get<DokployDomain[]>(\n\t\t\t`domain.byApplicationId?applicationId=${applicationId}`,\n\t\t);\n\t}\n\n\t/**\n\t * Validate a domain and trigger SSL certificate generation\n\t *\n\t * This should be called after DNS records are created and propagated.\n\t * It triggers Let's Encrypt certificate generation for HTTPS domains.\n\t *\n\t * @param domain - The domain hostname to validate (e.g., 'api.example.com')\n\t */\n\tasync validateDomain(\n\t\tdomain: string,\n\t): Promise<{ isValid: boolean; resolvedIp: string }> {\n\t\treturn this.post<{ isValid: boolean; resolvedIp: string }>(\n\t\t\t'domain.validateDomain',\n\t\t\t{ domain },\n\t\t);\n\t}\n\n\t/**\n\t * Auto-generate a domain name for an application\n\t */\n\tasync generateDomain(\n\t\tappName: string,\n\t\tserverId?: string,\n\t): Promise<{ domain: string }> {\n\t\treturn this.post<{ domain: string }>('domain.generateDomain', {\n\t\t\tappName,\n\t\t\tserverId,\n\t\t});\n\t}\n}\n\n// ============================================\n// Type definitions for Dokploy API responses\n// ============================================\n\nexport interface DokployProject {\n\tprojectId: string;\n\tname: string;\n\tdescription: string | null;\n\tcreatedAt?: string;\n\tadminId?: string;\n}\n\nexport interface DokployEnvironment {\n\tenvironmentId: string;\n\tname: string;\n\tdescription: string | null;\n}\n\nexport interface DokployProjectDetails extends DokployProject {\n\tenvironments: DokployEnvironment[];\n}\n\nexport interface DokployApplication {\n\tapplicationId: string;\n\tname: string;\n\tappName: string;\n\tprojectId: string;\n\tenvironmentId?: string;\n}\n\nexport interface DokployApplicationUpdate {\n\tregistryId: string;\n\tdockerImage: string;\n\tsourceType: 'docker';\n}\n\nexport interface DokployRegistry {\n\tregistryId: string;\n\tregistryName: string;\n\tregistryUrl: string;\n\tusername: string;\n\timagePrefix: string | null;\n}\n\nexport interface DokployPostgres {\n\tpostgresId: string;\n\tname: string;\n\tappName: string;\n\tdatabaseName: string;\n\tdatabaseUser: string;\n\tdatabasePassword: string;\n\tdockerImage: string;\n\tdescription: string | null;\n\tprojectId: string;\n\tenvironmentId: string;\n\tapplicationStatus: 'idle' | 'running' | 'done' | 'error';\n\texternalPort: number | null;\n\tcreatedAt?: string;\n}\n\nexport interface DokployPostgresUpdate {\n\tname: string;\n\tappName: string;\n\tdatabaseName: string;\n\tdatabaseUser: string;\n\tdatabasePassword: string;\n\tdockerImage: string;\n\tdescription: string;\n}\n\nexport interface DokployRedis {\n\tredisId: string;\n\tname: string;\n\tappName: string;\n\tdatabasePassword: string;\n\tdockerImage: string;\n\tdescription: string | null;\n\tprojectId: string;\n\tenvironmentId: string;\n\tapplicationStatus: 'idle' | 'running' | 'done' | 'error';\n\texternalPort: number | null;\n\tcreatedAt?: string;\n}\n\nexport interface DokployRedisUpdate {\n\tname: string;\n\tappName: string;\n\tdatabasePassword: string;\n\tdockerImage: string;\n\tdescription: string;\n}\n\nexport type DokployCertificateType = 'letsencrypt' | 'none' | 'custom';\nexport type DokployDomainType = 'application' | 'compose' | 'preview';\n\nexport interface DokployDomainCreate {\n\t/** Domain hostname (e.g., 'api.example.com') */\n\thost: string;\n\t/** URL path (optional, e.g., '/api') */\n\tpath?: string | null;\n\t/** Container port to route to (1-65535) */\n\tport?: number | null;\n\t/** Enable HTTPS */\n\thttps?: boolean;\n\t/** Associated application ID */\n\tapplicationId?: string | null;\n\t/** Certificate type for HTTPS */\n\tcertificateType?: DokployCertificateType;\n\t/** Custom certificate resolver name */\n\tcustomCertResolver?: string | null;\n\t/** Docker Compose service ID */\n\tcomposeId?: string | null;\n\t/** Service name for compose */\n\tserviceName?: string | null;\n\t/** Domain type */\n\tdomainType?: DokployDomainType | null;\n\t/** Preview deployment ID */\n\tpreviewDeploymentId?: string | null;\n\t/** Internal routing path */\n\tinternalPath?: string | null;\n\t/** Strip path from forwarded requests */\n\tstripPath?: boolean;\n}\n\nexport interface DokployDomain extends DokployDomainCreate {\n\tdomainId: string;\n\tcreatedAt?: string;\n}\n\n/**\n * Create a Dokploy API client from stored credentials or environment\n */\nexport async function createDokployApi(\n\tendpoint?: string,\n): Promise<DokployApi | null> {\n\tconst { getDokployCredentials } = await import('../auth/credentials');\n\n\t// Try environment variable first\n\tconst envToken = process.env.DOKPLOY_API_TOKEN;\n\tconst envEndpoint = endpoint || process.env.DOKPLOY_ENDPOINT;\n\n\tif (envToken && envEndpoint) {\n\t\treturn new DokployApi({ baseUrl: envEndpoint, token: envToken });\n\t}\n\n\t// Fall back to stored credentials\n\tconst creds = await getDokployCredentials();\n\tif (creds) {\n\t\treturn new DokployApi({\n\t\t\tbaseUrl: endpoint || creds.endpoint,\n\t\t\ttoken: creds.token,\n\t\t});\n\t}\n\n\treturn null;\n}\n"],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ import { DokployApi, DokployApiError } from "./dokploy-api-94KzmTVf.mjs";
2
+
3
+ export { DokployApi };
@@ -0,0 +1,3 @@
1
+ const require_dokploy_api = require('./dokploy-api-YD8WCQfW.cjs');
2
+
3
+ exports.DokployApi = require_dokploy_api.DokployApi;
@@ -261,10 +261,10 @@ var DokployApi = class {
261
261
  projectId,
262
262
  environmentId,
263
263
  appName: options?.appName ?? name.toLowerCase().replace(/[^a-z0-9-]/g, "-"),
264
- databaseName: options?.databaseName ?? "app",
264
+ databaseName: options?.databaseName,
265
265
  databaseUser: options?.databaseUser ?? "postgres",
266
266
  databasePassword: options?.databasePassword,
267
- dockerImage: options?.dockerImage ?? "postgres:16-alpine",
267
+ dockerImage: options?.dockerImage ?? "postgres:18",
268
268
  description: options?.description ?? `Postgres database for ${name}`
269
269
  });
270
270
  }
@@ -350,7 +350,7 @@ var DokployApi = class {
350
350
  environmentId,
351
351
  appName: options?.appName ?? name.toLowerCase().replace(/[^a-z0-9-]/g, "-"),
352
352
  databasePassword: options?.databasePassword,
353
- dockerImage: options?.dockerImage ?? "redis:7-alpine",
353
+ dockerImage: options?.dockerImage ?? "redis:8",
354
354
  description: options?.description ?? `Redis instance for ${name}`
355
355
  });
356
356
  }
@@ -476,4 +476,4 @@ Object.defineProperty(exports, 'DokployApiError', {
476
476
  return DokployApiError;
477
477
  }
478
478
  });
479
- //# sourceMappingURL=dokploy-api-BDLu0qWi.cjs.map
479
+ //# sourceMappingURL=dokploy-api-YD8WCQfW.cjs.map