@geekmidas/cloud 10.0.0-alpha.11 → 10.0.0-alpha.13

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.cjs CHANGED
@@ -1,3 +1,3 @@
1
- const require_utils = require('./utils-B1a2UuEO.cjs');
2
-
3
- exports.buildResourceEnv = require_utils.buildResourceEnv;
1
+ Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
+ const require_utils_index = require("./utils/index.cjs");
3
+ exports.buildResourceEnv = require_utils_index.buildResourceEnv;
package/dist/index.d.cts CHANGED
@@ -1,2 +1,2 @@
1
- import { buildResourceEnv } from "./index-B5CZ1xVf.cjs";
1
+ import { buildResourceEnv } from "./utils/index.cjs";
2
2
  export { buildResourceEnv };
package/dist/index.d.mts CHANGED
@@ -1,2 +1,2 @@
1
- import { buildResourceEnv } from "./index-DhHRjduZ.mjs";
1
+ import { buildResourceEnv } from "./utils/index.mjs";
2
2
  export { buildResourceEnv };
package/dist/index.mjs CHANGED
@@ -1,3 +1,2 @@
1
- import { buildResourceEnv } from "./utils-DMOXJ27j.mjs";
2
-
3
- export { buildResourceEnv };
1
+ import { buildResourceEnv } from "./utils/index.mjs";
2
+ export { buildResourceEnv };
@@ -1,6 +1,107 @@
1
- const require_utils = require('../utils-B1a2UuEO.cjs');
1
+ Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
+ //#region \0rolldown/runtime.js
3
+ var __create = Object.create;
4
+ var __defProp = Object.defineProperty;
5
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
6
+ var __getOwnPropNames = Object.getOwnPropertyNames;
7
+ var __getProtoOf = Object.getPrototypeOf;
8
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
9
+ var __copyProps = (to, from, except, desc) => {
10
+ if (from && typeof from === "object" || typeof from === "function") for (var keys = __getOwnPropNames(from), i = 0, n = keys.length, key; i < n; i++) {
11
+ key = keys[i];
12
+ if (!__hasOwnProp.call(to, key) && key !== except) __defProp(to, key, {
13
+ get: ((k) => from[k]).bind(null, key),
14
+ enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable
15
+ });
16
+ }
17
+ return to;
18
+ };
19
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(isNodeMode || !mod || !mod.__esModule || !__hasOwnProp.call(mod, "default") ? __defProp(target, "default", {
20
+ value: mod,
21
+ enumerable: true
22
+ }) : target, mod));
23
+ //#endregion
24
+ let node_os = require("node:os");
25
+ node_os = __toESM(node_os, 1);
26
+ let lodash_snakecase = require("lodash.snakecase");
27
+ lodash_snakecase = __toESM(lodash_snakecase, 1);
28
+ //#region src/utils/index.ts
29
+ function getLocalIpAddress() {
30
+ const networkInterfaces = node_os.default.networkInterfaces();
31
+ for (const interfaceName in networkInterfaces) {
32
+ const addresses = networkInterfaces[interfaceName] || [];
33
+ for (const addressInfo of addresses) if (addressInfo.family === "IPv4" && !addressInfo.internal) return addressInfo.address;
34
+ }
35
+ return null;
36
+ }
37
+ function environmentCase(name) {
38
+ return (0, lodash_snakecase.default)(name).toUpperCase().replace(/_\d+/g, (r) => {
39
+ return r.replace("_", "");
40
+ });
41
+ }
42
+ let ResourceType = /* @__PURE__ */ function(ResourceType) {
43
+ ResourceType["ApiGatewayV2"] = "sst.aws.ApiGatewayV2";
44
+ ResourceType["Postgres"] = "sst.aws.Postgres";
45
+ ResourceType["Function"] = "sst.aws.Function";
46
+ ResourceType["ObjectStorage"] = "sst.aws.Bucket";
47
+ ResourceType["Vpc"] = "sst.aws.Vpc";
48
+ ResourceType["Secret"] = "sst.sst.Secret";
49
+ ResourceType["SSTSecret"] = "sst:sst:Secret";
50
+ ResourceType["SSTFunction"] = "sst:sst:Function";
51
+ ResourceType["SSTApiGatewayV2"] = "sst:aws:ApiGatewayV2";
52
+ ResourceType["SSTPostgres"] = "sst:aws:Postgres";
53
+ ResourceType["SSTObjectStorage"] = "sst:aws:Bucket";
54
+ ResourceType["SnsTopic"] = "sst:aws:SnsTopic";
55
+ return ResourceType;
56
+ }({});
57
+ const secret = (name, value) => ({ [environmentCase(name)]: value.value });
58
+ const postgres = (key, value) => {
59
+ const prefix = `${environmentCase(key)}`;
60
+ return {
61
+ [`${prefix}_NAME`]: value.database,
62
+ [`${prefix}_HOST`]: value.host,
63
+ [`${prefix}_PASSWORD`]: value.password,
64
+ [`${prefix}_PORT`]: value.port,
65
+ [`${prefix}_USERNAME`]: value.username
66
+ };
67
+ };
68
+ const bucket = (name, value) => {
69
+ return { [`${`${environmentCase(name)}`}_NAME`]: value.name };
70
+ };
71
+ const topic = (name, value) => {
72
+ return { [`${`${environmentCase(name)}`}_ARN`]: value.arn };
73
+ };
74
+ const noop = (_name, _value) => ({});
75
+ const processors = {
76
+ ["sst.aws.ApiGatewayV2"]: noop,
77
+ ["sst.aws.Function"]: noop,
78
+ ["sst.aws.Vpc"]: noop,
79
+ ["sst.sst.Secret"]: secret,
80
+ ["sst.aws.Postgres"]: postgres,
81
+ ["sst.aws.Bucket"]: bucket,
82
+ ["sst:sst:Secret"]: secret,
83
+ ["sst:aws:Bucket"]: bucket,
84
+ ["sst:sst:Function"]: noop,
85
+ ["sst:aws:Postgres"]: postgres,
86
+ ["sst:aws:ApiGatewayV2"]: noop,
87
+ ["sst:aws:SnsTopic"]: topic
88
+ };
89
+ function buildResourceEnv(record) {
90
+ const env = {};
91
+ for (const [k, value] of Object.entries(record)) {
92
+ if (typeof value === "string") {
93
+ env[environmentCase(k)] = value;
94
+ continue;
95
+ }
96
+ const processor = processors[value.type];
97
+ if (processor) Object.assign(env, processor(k, value));
98
+ }
99
+ return env;
100
+ }
101
+ //#endregion
102
+ exports.ResourceType = ResourceType;
103
+ exports.buildResourceEnv = buildResourceEnv;
104
+ exports.environmentCase = environmentCase;
105
+ exports.getLocalIpAddress = getLocalIpAddress;
2
106
 
3
- exports.ResourceType = require_utils.ResourceType;
4
- exports.buildResourceEnv = require_utils.buildResourceEnv;
5
- exports.environmentCase = require_utils.environmentCase;
6
- exports.getLocalIpAddress = require_utils.getLocalIpAddress;
107
+ //# sourceMappingURL=index.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.cjs","names":["os","snakecase"],"sources":["../../src/utils/index.ts"],"sourcesContent":["import os from 'node:os';\nimport snakecase from 'lodash.snakecase';\n\nexport function getLocalIpAddress() {\n\tconst networkInterfaces = os.networkInterfaces();\n\tfor (const interfaceName in networkInterfaces) {\n\t\tconst addresses = networkInterfaces[interfaceName] || [];\n\t\tfor (const addressInfo of addresses) {\n\t\t\t// Look for an IPv4 address that is not internal (loopback)\n\t\t\tif (addressInfo.family === 'IPv4' && !addressInfo.internal) {\n\t\t\t\treturn addressInfo.address;\n\t\t\t}\n\t\t}\n\t}\n\treturn null; // No suitable IP address found\n}\n\nexport function environmentCase(name: string) {\n\treturn snakecase(name)\n\t\t.toUpperCase()\n\t\t.replace(/_\\d+/g, (r) => {\n\t\t\treturn r.replace('_', '');\n\t\t});\n}\nexport enum ResourceType {\n\tApiGatewayV2 = 'sst.aws.ApiGatewayV2',\n\tPostgres = 'sst.aws.Postgres',\n\tFunction = 'sst.aws.Function',\n\tObjectStorage = 'sst.aws.Bucket',\n\tVpc = 'sst.aws.Vpc',\n\tSecret = 'sst.sst.Secret',\n\tSSTSecret = 'sst:sst:Secret',\n\tSSTFunction = 'sst:sst:Function',\n\tSSTApiGatewayV2 = 'sst:aws:ApiGatewayV2',\n\tSSTPostgres = 'sst:aws:Postgres',\n\tSSTObjectStorage = 'sst:aws:Bucket',\n\tSnsTopic = 'sst:aws:SnsTopic',\n}\n\nconst secret = (name: string, value: Secret) => ({\n\t[environmentCase(name)]: value.value,\n});\nconst postgres = (key: string, value: Postgres) => {\n\tconst prefix = `${environmentCase(key)}`;\n\treturn {\n\t\t[`${prefix}_NAME`]: value.database,\n\t\t[`${prefix}_HOST`]: value.host,\n\t\t[`${prefix}_PASSWORD`]: value.password,\n\t\t[`${prefix}_PORT`]: value.port,\n\t\t[`${prefix}_USERNAME`]: value.username,\n\t};\n};\n\nconst bucket = (name: string, value: Bucket) => {\n\tconst prefix = `${environmentCase(name)}`;\n\treturn {\n\t\t[`${prefix}_NAME`]: value.name,\n\t};\n};\n\nconst topic = (name: string, value: SnsTopic) => {\n\tconst prefix = `${environmentCase(name)}`;\n\tconst key = `${prefix}_ARN`;\n\n\treturn {\n\t\t[key]: value.arn,\n\t};\n};\n\nconst noop = (_name: string, _value: any) => ({});\n\nconst processors: Record<ResourceType, ResourceProcessor<any>> = {\n\t[ResourceType.ApiGatewayV2]: noop,\n\t[ResourceType.Function]: noop,\n\t[ResourceType.Vpc]: noop,\n\t[ResourceType.Secret]: secret,\n\t[ResourceType.Postgres]: postgres,\n\t[ResourceType.ObjectStorage]: bucket,\n\n\t[ResourceType.SSTSecret]: secret,\n\t[ResourceType.SSTObjectStorage]: bucket,\n\t[ResourceType.SSTFunction]: noop,\n\t[ResourceType.SSTPostgres]: postgres,\n\t[ResourceType.SSTApiGatewayV2]: noop,\n\t[ResourceType.SnsTopic]: topic,\n};\n\nexport function buildResourceEnv(\n\trecord: Record<string, Resource | string>,\n): Record<string, string> {\n\tconst env: Record<string, string> = {};\n\tfor (const [k, value] of Object.entries(record)) {\n\t\tif (typeof value === 'string') {\n\t\t\tenv[environmentCase(k)] = value;\n\t\t\tcontinue;\n\t\t}\n\n\t\tconst processor = processors[value.type];\n\t\tif (processor) {\n\t\t\tObject.assign(env, processor(k, value));\n\t\t} else {\n\t\t}\n\t}\n\n\treturn env;\n}\n\n/**\n * SST links a resource under one of two spellings — `sst.aws.Bucket` when it\n * comes from the state file, `sst:aws:Bucket` when it comes from the runtime —\n * and `processors` has always handled both. Only the dotted half was admitted\n * here, so the colon half could not be passed to `buildResourceEnv` without a\n * cast, and `SnsTopic` was missing from `Resource` altogether despite being the\n * only thing that produces `*_ARN`.\n */\nexport type ApiGatewayV2 = {\n\ttype: ResourceType.ApiGatewayV2 | ResourceType.SSTApiGatewayV2;\n\turl: string;\n};\n\nexport type Postgres = {\n\tdatabase: string;\n\thost: string;\n\tpassword: string;\n\tport: number;\n\ttype: ResourceType.Postgres | ResourceType.SSTPostgres;\n\tusername: string;\n};\n\nexport type Function = {\n\tname: string;\n\ttype: ResourceType.Function | ResourceType.SSTFunction;\n};\n\nexport type Bucket = {\n\tname: string;\n\ttype: ResourceType.ObjectStorage | ResourceType.SSTObjectStorage;\n};\n\nexport type SnsTopic = {\n\tarn: string;\n\ttype: ResourceType.SnsTopic;\n};\n\nexport type Vpc = {\n\tbastion: string;\n\ttype: ResourceType.Vpc;\n};\n\nexport type Secret = {\n\ttype: ResourceType.Secret | ResourceType.SSTSecret;\n\tvalue: string;\n};\n\nexport type Resource =\n\t| ApiGatewayV2\n\t| Postgres\n\t| Function\n\t| Bucket\n\t| SnsTopic\n\t| Vpc\n\t| Secret;\n\nexport type ResourceProcessor<K extends Resource> = (\n\tname: string,\n\tvalue: K,\n) => Record<string, string | number>;\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;AAGA,SAAgB,oBAAoB;CACnC,MAAM,oBAAoBA,QAAAA,QAAG,kBAAkB;CAC/C,KAAK,MAAM,iBAAiB,mBAAmB;EAC9C,MAAM,YAAY,kBAAkB,kBAAkB,CAAC;EACvD,KAAK,MAAM,eAAe,WAEzB,IAAI,YAAY,WAAW,UAAU,CAAC,YAAY,UACjD,OAAO,YAAY;CAGtB;CACA,OAAO;AACR;AAEA,SAAgB,gBAAgB,MAAc;CAC7C,QAAA,GAAOC,iBAAAA,QAAAA,CAAU,IAAI,CAAC,CACpB,YAAY,CAAC,CACb,QAAQ,UAAU,MAAM;EACxB,OAAO,EAAE,QAAQ,KAAK,EAAE;CACzB,CAAC;AACH;AACA,IAAY,eAAL,yBAAA,cAAA;CACN,aAAA,kBAAA;CACA,aAAA,cAAA;CACA,aAAA,cAAA;CACA,aAAA,mBAAA;CACA,aAAA,SAAA;CACA,aAAA,YAAA;CACA,aAAA,eAAA;CACA,aAAA,iBAAA;CACA,aAAA,qBAAA;CACA,aAAA,iBAAA;CACA,aAAA,sBAAA;CACA,aAAA,cAAA;;AACD,EAAA,CAAA,CAAA;AAEA,MAAM,UAAU,MAAc,WAAmB,GAC/C,gBAAgB,IAAI,IAAI,MAAM,MAChC;AACA,MAAM,YAAY,KAAa,UAAoB;CAClD,MAAM,SAAS,GAAG,gBAAgB,GAAG;CACrC,OAAO;GACL,GAAG,OAAO,SAAS,MAAM;GACzB,GAAG,OAAO,SAAS,MAAM;GACzB,GAAG,OAAO,aAAa,MAAM;GAC7B,GAAG,OAAO,SAAS,MAAM;GACzB,GAAG,OAAO,aAAa,MAAM;CAC/B;AACD;AAEA,MAAM,UAAU,MAAc,UAAkB;CAE/C,OAAO,GACL,GAAG,GAFa,gBAAgB,IAAI,IAE1B,SAAS,MAAM,KAC3B;AACD;AAEA,MAAM,SAAS,MAAc,UAAoB;CAIhD,OAAO,GACL,GAHa,GADG,gBAAgB,IAAI,IAChB,QAGd,MAAM,IACd;AACD;AAEA,MAAM,QAAQ,OAAe,YAAiB,CAAC;AAE/C,MAAM,aAA2D;EACnC,yBAAA;EACJ,qBAAA;EACL,gBAAA;EACG,mBAAA;EACE,qBAAA;EACK,mBAAA;EAEJ,mBAAA;EACO,mBAAA;EACL,qBAAA;EACA,qBAAA;EACI,yBAAA;EACP,qBAAA;AAC1B;AAEA,SAAgB,iBACf,QACyB;CACzB,MAAM,MAA8B,CAAC;CACrC,KAAK,MAAM,CAAC,GAAG,UAAU,OAAO,QAAQ,MAAM,GAAG;EAChD,IAAI,OAAO,UAAU,UAAU;GAC9B,IAAI,gBAAgB,CAAC,KAAK;GAC1B;EACD;EAEA,MAAM,YAAY,WAAW,MAAM;EACnC,IAAI,WACH,OAAO,OAAO,KAAK,UAAU,GAAG,KAAK,CAAC;CAGxC;CAEA,OAAO;AACR"}
@@ -1,2 +1,62 @@
1
- import { ApiGatewayV2, Bucket, Function, Postgres, Resource, ResourceProcessor, ResourceType, Secret, SnsTopic, Vpc, buildResourceEnv, environmentCase, getLocalIpAddress } from "../index-B5CZ1xVf.cjs";
2
- export { ApiGatewayV2, Bucket, Function, Postgres, Resource, ResourceProcessor, ResourceType, Secret, SnsTopic, Vpc, buildResourceEnv, environmentCase, getLocalIpAddress };
1
+ //#region src/utils/index.d.ts
2
+ export declare function getLocalIpAddress(): string | null;
3
+ export declare function environmentCase(name: string): string;
4
+ export declare enum ResourceType {
5
+ ApiGatewayV2 = "sst.aws.ApiGatewayV2",
6
+ Postgres = "sst.aws.Postgres",
7
+ Function = "sst.aws.Function",
8
+ ObjectStorage = "sst.aws.Bucket",
9
+ Vpc = "sst.aws.Vpc",
10
+ Secret = "sst.sst.Secret",
11
+ SSTSecret = "sst:sst:Secret",
12
+ SSTFunction = "sst:sst:Function",
13
+ SSTApiGatewayV2 = "sst:aws:ApiGatewayV2",
14
+ SSTPostgres = "sst:aws:Postgres",
15
+ SSTObjectStorage = "sst:aws:Bucket",
16
+ SnsTopic = "sst:aws:SnsTopic"
17
+ }
18
+ export declare function buildResourceEnv(record: Record<string, Resource | string>): Record<string, string>;
19
+ /**
20
+ * SST links a resource under one of two spellings — `sst.aws.Bucket` when it
21
+ * comes from the state file, `sst:aws:Bucket` when it comes from the runtime —
22
+ * and `processors` has always handled both. Only the dotted half was admitted
23
+ * here, so the colon half could not be passed to `buildResourceEnv` without a
24
+ * cast, and `SnsTopic` was missing from `Resource` altogether despite being the
25
+ * only thing that produces `*_ARN`.
26
+ */
27
+ export type ApiGatewayV2 = {
28
+ type: ResourceType.ApiGatewayV2 | ResourceType.SSTApiGatewayV2;
29
+ url: string;
30
+ };
31
+ export type Postgres = {
32
+ database: string;
33
+ host: string;
34
+ password: string;
35
+ port: number;
36
+ type: ResourceType.Postgres | ResourceType.SSTPostgres;
37
+ username: string;
38
+ };
39
+ export type Function = {
40
+ name: string;
41
+ type: ResourceType.Function | ResourceType.SSTFunction;
42
+ };
43
+ export type Bucket = {
44
+ name: string;
45
+ type: ResourceType.ObjectStorage | ResourceType.SSTObjectStorage;
46
+ };
47
+ export type SnsTopic = {
48
+ arn: string;
49
+ type: ResourceType.SnsTopic;
50
+ };
51
+ export type Vpc = {
52
+ bastion: string;
53
+ type: ResourceType.Vpc;
54
+ };
55
+ export type Secret = {
56
+ type: ResourceType.Secret | ResourceType.SSTSecret;
57
+ value: string;
58
+ };
59
+ export type Resource = ApiGatewayV2 | Postgres | Function | Bucket | SnsTopic | Vpc | Secret;
60
+ export type ResourceProcessor<K extends Resource> = (name: string, value: K) => Record<string, string | number>;
61
+ //#endregion
62
+ //# sourceMappingURL=index.d.cts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.cts","names":[],"sources":["../../src/utils/index.ts"],"mappings":";wBAGgB;wBAcA,gBAAgB;oBAOpB;EACX;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;wBAmDe,iBACf,QAAQ,eAAe,qBACrB;;;;;;;;;YA0BS;EACX,MAAM,aAAa,eAAe,aAAa;EAC/C;;YAGW;EACX;EACA;EACA;EACA;EACA,MAAM,aAAa,WAAW,aAAa;EAC3C;;YAGW;EACX;EACA,MAAM,aAAa,WAAW,aAAa;;YAGhC;EACX;EACA,MAAM,aAAa,gBAAgB,aAAa;;YAGrC;EACX;EACA,MAAM,aAAa;;YAGR;EACX;EACA,MAAM,aAAa;;YAGR;EACX,MAAM,aAAa,SAAS,aAAa;EACzC;;YAGW,WACT,eACA,WACA,WACA,SACA,WACA,MACA;YAES,kBAAkB,UAAU,aACvC,cACA,OAAO,MACH"}
@@ -1,2 +1,62 @@
1
- import { ApiGatewayV2, Bucket, Function, Postgres, Resource, ResourceProcessor, ResourceType, Secret, SnsTopic, Vpc, buildResourceEnv, environmentCase, getLocalIpAddress } from "../index-DhHRjduZ.mjs";
2
- export { ApiGatewayV2, Bucket, Function, Postgres, Resource, ResourceProcessor, ResourceType, Secret, SnsTopic, Vpc, buildResourceEnv, environmentCase, getLocalIpAddress };
1
+ //#region src/utils/index.d.ts
2
+ export declare function getLocalIpAddress(): string | null;
3
+ export declare function environmentCase(name: string): string;
4
+ export declare enum ResourceType {
5
+ ApiGatewayV2 = "sst.aws.ApiGatewayV2",
6
+ Postgres = "sst.aws.Postgres",
7
+ Function = "sst.aws.Function",
8
+ ObjectStorage = "sst.aws.Bucket",
9
+ Vpc = "sst.aws.Vpc",
10
+ Secret = "sst.sst.Secret",
11
+ SSTSecret = "sst:sst:Secret",
12
+ SSTFunction = "sst:sst:Function",
13
+ SSTApiGatewayV2 = "sst:aws:ApiGatewayV2",
14
+ SSTPostgres = "sst:aws:Postgres",
15
+ SSTObjectStorage = "sst:aws:Bucket",
16
+ SnsTopic = "sst:aws:SnsTopic"
17
+ }
18
+ export declare function buildResourceEnv(record: Record<string, Resource | string>): Record<string, string>;
19
+ /**
20
+ * SST links a resource under one of two spellings — `sst.aws.Bucket` when it
21
+ * comes from the state file, `sst:aws:Bucket` when it comes from the runtime —
22
+ * and `processors` has always handled both. Only the dotted half was admitted
23
+ * here, so the colon half could not be passed to `buildResourceEnv` without a
24
+ * cast, and `SnsTopic` was missing from `Resource` altogether despite being the
25
+ * only thing that produces `*_ARN`.
26
+ */
27
+ export type ApiGatewayV2 = {
28
+ type: ResourceType.ApiGatewayV2 | ResourceType.SSTApiGatewayV2;
29
+ url: string;
30
+ };
31
+ export type Postgres = {
32
+ database: string;
33
+ host: string;
34
+ password: string;
35
+ port: number;
36
+ type: ResourceType.Postgres | ResourceType.SSTPostgres;
37
+ username: string;
38
+ };
39
+ export type Function = {
40
+ name: string;
41
+ type: ResourceType.Function | ResourceType.SSTFunction;
42
+ };
43
+ export type Bucket = {
44
+ name: string;
45
+ type: ResourceType.ObjectStorage | ResourceType.SSTObjectStorage;
46
+ };
47
+ export type SnsTopic = {
48
+ arn: string;
49
+ type: ResourceType.SnsTopic;
50
+ };
51
+ export type Vpc = {
52
+ bastion: string;
53
+ type: ResourceType.Vpc;
54
+ };
55
+ export type Secret = {
56
+ type: ResourceType.Secret | ResourceType.SSTSecret;
57
+ value: string;
58
+ };
59
+ export type Resource = ApiGatewayV2 | Postgres | Function | Bucket | SnsTopic | Vpc | Secret;
60
+ export type ResourceProcessor<K extends Resource> = (name: string, value: K) => Record<string, string | number>;
61
+ //#endregion
62
+ //# sourceMappingURL=index.d.mts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.mts","names":[],"sources":["../../src/utils/index.ts"],"mappings":";wBAGgB;wBAcA,gBAAgB;oBAOpB;EACX;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;wBAmDe,iBACf,QAAQ,eAAe,qBACrB;;;;;;;;;YA0BS;EACX,MAAM,aAAa,eAAe,aAAa;EAC/C;;YAGW;EACX;EACA;EACA;EACA;EACA,MAAM,aAAa,WAAW,aAAa;EAC3C;;YAGW;EACX;EACA,MAAM,aAAa,WAAW,aAAa;;YAGhC;EACX;EACA,MAAM,aAAa,gBAAgB,aAAa;;YAGrC;EACX;EACA,MAAM,aAAa;;YAGR;EACX;EACA,MAAM,aAAa;;YAGR;EACX,MAAM,aAAa,SAAS,aAAa;EACzC;;YAGW,WACT,eACA,WACA,WACA,SACA,WACA,MACA;YAES,kBAAkB,UAAU,aACvC,cACA,OAAO,MACH"}
@@ -1,3 +1,79 @@
1
- import { ResourceType, buildResourceEnv, environmentCase, getLocalIpAddress } from "../utils-DMOXJ27j.mjs";
1
+ import os from "node:os";
2
+ import snakecase from "lodash.snakecase";
3
+ //#region src/utils/index.ts
4
+ function getLocalIpAddress() {
5
+ const networkInterfaces = os.networkInterfaces();
6
+ for (const interfaceName in networkInterfaces) {
7
+ const addresses = networkInterfaces[interfaceName] || [];
8
+ for (const addressInfo of addresses) if (addressInfo.family === "IPv4" && !addressInfo.internal) return addressInfo.address;
9
+ }
10
+ return null;
11
+ }
12
+ function environmentCase(name) {
13
+ return snakecase(name).toUpperCase().replace(/_\d+/g, (r) => {
14
+ return r.replace("_", "");
15
+ });
16
+ }
17
+ let ResourceType = /* @__PURE__ */ function(ResourceType) {
18
+ ResourceType["ApiGatewayV2"] = "sst.aws.ApiGatewayV2";
19
+ ResourceType["Postgres"] = "sst.aws.Postgres";
20
+ ResourceType["Function"] = "sst.aws.Function";
21
+ ResourceType["ObjectStorage"] = "sst.aws.Bucket";
22
+ ResourceType["Vpc"] = "sst.aws.Vpc";
23
+ ResourceType["Secret"] = "sst.sst.Secret";
24
+ ResourceType["SSTSecret"] = "sst:sst:Secret";
25
+ ResourceType["SSTFunction"] = "sst:sst:Function";
26
+ ResourceType["SSTApiGatewayV2"] = "sst:aws:ApiGatewayV2";
27
+ ResourceType["SSTPostgres"] = "sst:aws:Postgres";
28
+ ResourceType["SSTObjectStorage"] = "sst:aws:Bucket";
29
+ ResourceType["SnsTopic"] = "sst:aws:SnsTopic";
30
+ return ResourceType;
31
+ }({});
32
+ const secret = (name, value) => ({ [environmentCase(name)]: value.value });
33
+ const postgres = (key, value) => {
34
+ const prefix = `${environmentCase(key)}`;
35
+ return {
36
+ [`${prefix}_NAME`]: value.database,
37
+ [`${prefix}_HOST`]: value.host,
38
+ [`${prefix}_PASSWORD`]: value.password,
39
+ [`${prefix}_PORT`]: value.port,
40
+ [`${prefix}_USERNAME`]: value.username
41
+ };
42
+ };
43
+ const bucket = (name, value) => {
44
+ return { [`${`${environmentCase(name)}`}_NAME`]: value.name };
45
+ };
46
+ const topic = (name, value) => {
47
+ return { [`${`${environmentCase(name)}`}_ARN`]: value.arn };
48
+ };
49
+ const noop = (_name, _value) => ({});
50
+ const processors = {
51
+ ["sst.aws.ApiGatewayV2"]: noop,
52
+ ["sst.aws.Function"]: noop,
53
+ ["sst.aws.Vpc"]: noop,
54
+ ["sst.sst.Secret"]: secret,
55
+ ["sst.aws.Postgres"]: postgres,
56
+ ["sst.aws.Bucket"]: bucket,
57
+ ["sst:sst:Secret"]: secret,
58
+ ["sst:aws:Bucket"]: bucket,
59
+ ["sst:sst:Function"]: noop,
60
+ ["sst:aws:Postgres"]: postgres,
61
+ ["sst:aws:ApiGatewayV2"]: noop,
62
+ ["sst:aws:SnsTopic"]: topic
63
+ };
64
+ function buildResourceEnv(record) {
65
+ const env = {};
66
+ for (const [k, value] of Object.entries(record)) {
67
+ if (typeof value === "string") {
68
+ env[environmentCase(k)] = value;
69
+ continue;
70
+ }
71
+ const processor = processors[value.type];
72
+ if (processor) Object.assign(env, processor(k, value));
73
+ }
74
+ return env;
75
+ }
76
+ //#endregion
77
+ export { ResourceType, buildResourceEnv, environmentCase, getLocalIpAddress };
2
78
 
3
- export { ResourceType, buildResourceEnv, environmentCase, getLocalIpAddress };
79
+ //# sourceMappingURL=index.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.mjs","names":[],"sources":["../../src/utils/index.ts"],"sourcesContent":["import os from 'node:os';\nimport snakecase from 'lodash.snakecase';\n\nexport function getLocalIpAddress() {\n\tconst networkInterfaces = os.networkInterfaces();\n\tfor (const interfaceName in networkInterfaces) {\n\t\tconst addresses = networkInterfaces[interfaceName] || [];\n\t\tfor (const addressInfo of addresses) {\n\t\t\t// Look for an IPv4 address that is not internal (loopback)\n\t\t\tif (addressInfo.family === 'IPv4' && !addressInfo.internal) {\n\t\t\t\treturn addressInfo.address;\n\t\t\t}\n\t\t}\n\t}\n\treturn null; // No suitable IP address found\n}\n\nexport function environmentCase(name: string) {\n\treturn snakecase(name)\n\t\t.toUpperCase()\n\t\t.replace(/_\\d+/g, (r) => {\n\t\t\treturn r.replace('_', '');\n\t\t});\n}\nexport enum ResourceType {\n\tApiGatewayV2 = 'sst.aws.ApiGatewayV2',\n\tPostgres = 'sst.aws.Postgres',\n\tFunction = 'sst.aws.Function',\n\tObjectStorage = 'sst.aws.Bucket',\n\tVpc = 'sst.aws.Vpc',\n\tSecret = 'sst.sst.Secret',\n\tSSTSecret = 'sst:sst:Secret',\n\tSSTFunction = 'sst:sst:Function',\n\tSSTApiGatewayV2 = 'sst:aws:ApiGatewayV2',\n\tSSTPostgres = 'sst:aws:Postgres',\n\tSSTObjectStorage = 'sst:aws:Bucket',\n\tSnsTopic = 'sst:aws:SnsTopic',\n}\n\nconst secret = (name: string, value: Secret) => ({\n\t[environmentCase(name)]: value.value,\n});\nconst postgres = (key: string, value: Postgres) => {\n\tconst prefix = `${environmentCase(key)}`;\n\treturn {\n\t\t[`${prefix}_NAME`]: value.database,\n\t\t[`${prefix}_HOST`]: value.host,\n\t\t[`${prefix}_PASSWORD`]: value.password,\n\t\t[`${prefix}_PORT`]: value.port,\n\t\t[`${prefix}_USERNAME`]: value.username,\n\t};\n};\n\nconst bucket = (name: string, value: Bucket) => {\n\tconst prefix = `${environmentCase(name)}`;\n\treturn {\n\t\t[`${prefix}_NAME`]: value.name,\n\t};\n};\n\nconst topic = (name: string, value: SnsTopic) => {\n\tconst prefix = `${environmentCase(name)}`;\n\tconst key = `${prefix}_ARN`;\n\n\treturn {\n\t\t[key]: value.arn,\n\t};\n};\n\nconst noop = (_name: string, _value: any) => ({});\n\nconst processors: Record<ResourceType, ResourceProcessor<any>> = {\n\t[ResourceType.ApiGatewayV2]: noop,\n\t[ResourceType.Function]: noop,\n\t[ResourceType.Vpc]: noop,\n\t[ResourceType.Secret]: secret,\n\t[ResourceType.Postgres]: postgres,\n\t[ResourceType.ObjectStorage]: bucket,\n\n\t[ResourceType.SSTSecret]: secret,\n\t[ResourceType.SSTObjectStorage]: bucket,\n\t[ResourceType.SSTFunction]: noop,\n\t[ResourceType.SSTPostgres]: postgres,\n\t[ResourceType.SSTApiGatewayV2]: noop,\n\t[ResourceType.SnsTopic]: topic,\n};\n\nexport function buildResourceEnv(\n\trecord: Record<string, Resource | string>,\n): Record<string, string> {\n\tconst env: Record<string, string> = {};\n\tfor (const [k, value] of Object.entries(record)) {\n\t\tif (typeof value === 'string') {\n\t\t\tenv[environmentCase(k)] = value;\n\t\t\tcontinue;\n\t\t}\n\n\t\tconst processor = processors[value.type];\n\t\tif (processor) {\n\t\t\tObject.assign(env, processor(k, value));\n\t\t} else {\n\t\t}\n\t}\n\n\treturn env;\n}\n\n/**\n * SST links a resource under one of two spellings — `sst.aws.Bucket` when it\n * comes from the state file, `sst:aws:Bucket` when it comes from the runtime —\n * and `processors` has always handled both. Only the dotted half was admitted\n * here, so the colon half could not be passed to `buildResourceEnv` without a\n * cast, and `SnsTopic` was missing from `Resource` altogether despite being the\n * only thing that produces `*_ARN`.\n */\nexport type ApiGatewayV2 = {\n\ttype: ResourceType.ApiGatewayV2 | ResourceType.SSTApiGatewayV2;\n\turl: string;\n};\n\nexport type Postgres = {\n\tdatabase: string;\n\thost: string;\n\tpassword: string;\n\tport: number;\n\ttype: ResourceType.Postgres | ResourceType.SSTPostgres;\n\tusername: string;\n};\n\nexport type Function = {\n\tname: string;\n\ttype: ResourceType.Function | ResourceType.SSTFunction;\n};\n\nexport type Bucket = {\n\tname: string;\n\ttype: ResourceType.ObjectStorage | ResourceType.SSTObjectStorage;\n};\n\nexport type SnsTopic = {\n\tarn: string;\n\ttype: ResourceType.SnsTopic;\n};\n\nexport type Vpc = {\n\tbastion: string;\n\ttype: ResourceType.Vpc;\n};\n\nexport type Secret = {\n\ttype: ResourceType.Secret | ResourceType.SSTSecret;\n\tvalue: string;\n};\n\nexport type Resource =\n\t| ApiGatewayV2\n\t| Postgres\n\t| Function\n\t| Bucket\n\t| SnsTopic\n\t| Vpc\n\t| Secret;\n\nexport type ResourceProcessor<K extends Resource> = (\n\tname: string,\n\tvalue: K,\n) => Record<string, string | number>;\n"],"mappings":";;;AAGA,SAAgB,oBAAoB;CACnC,MAAM,oBAAoB,GAAG,kBAAkB;CAC/C,KAAK,MAAM,iBAAiB,mBAAmB;EAC9C,MAAM,YAAY,kBAAkB,kBAAkB,CAAC;EACvD,KAAK,MAAM,eAAe,WAEzB,IAAI,YAAY,WAAW,UAAU,CAAC,YAAY,UACjD,OAAO,YAAY;CAGtB;CACA,OAAO;AACR;AAEA,SAAgB,gBAAgB,MAAc;CAC7C,OAAO,UAAU,IAAI,CAAC,CACpB,YAAY,CAAC,CACb,QAAQ,UAAU,MAAM;EACxB,OAAO,EAAE,QAAQ,KAAK,EAAE;CACzB,CAAC;AACH;AACA,IAAY,eAAL,yBAAA,cAAA;CACN,aAAA,kBAAA;CACA,aAAA,cAAA;CACA,aAAA,cAAA;CACA,aAAA,mBAAA;CACA,aAAA,SAAA;CACA,aAAA,YAAA;CACA,aAAA,eAAA;CACA,aAAA,iBAAA;CACA,aAAA,qBAAA;CACA,aAAA,iBAAA;CACA,aAAA,sBAAA;CACA,aAAA,cAAA;;AACD,EAAA,CAAA,CAAA;AAEA,MAAM,UAAU,MAAc,WAAmB,GAC/C,gBAAgB,IAAI,IAAI,MAAM,MAChC;AACA,MAAM,YAAY,KAAa,UAAoB;CAClD,MAAM,SAAS,GAAG,gBAAgB,GAAG;CACrC,OAAO;GACL,GAAG,OAAO,SAAS,MAAM;GACzB,GAAG,OAAO,SAAS,MAAM;GACzB,GAAG,OAAO,aAAa,MAAM;GAC7B,GAAG,OAAO,SAAS,MAAM;GACzB,GAAG,OAAO,aAAa,MAAM;CAC/B;AACD;AAEA,MAAM,UAAU,MAAc,UAAkB;CAE/C,OAAO,GACL,GAAG,GAFa,gBAAgB,IAAI,IAE1B,SAAS,MAAM,KAC3B;AACD;AAEA,MAAM,SAAS,MAAc,UAAoB;CAIhD,OAAO,GACL,GAHa,GADG,gBAAgB,IAAI,IAChB,QAGd,MAAM,IACd;AACD;AAEA,MAAM,QAAQ,OAAe,YAAiB,CAAC;AAE/C,MAAM,aAA2D;EACnC,yBAAA;EACJ,qBAAA;EACL,gBAAA;EACG,mBAAA;EACE,qBAAA;EACK,mBAAA;EAEJ,mBAAA;EACO,mBAAA;EACL,qBAAA;EACA,qBAAA;EACI,yBAAA;EACP,qBAAA;AAC1B;AAEA,SAAgB,iBACf,QACyB;CACzB,MAAM,MAA8B,CAAC;CACrC,KAAK,MAAM,CAAC,GAAG,UAAU,OAAO,QAAQ,MAAM,GAAG;EAChD,IAAI,OAAO,UAAU,UAAU;GAC9B,IAAI,gBAAgB,CAAC,KAAK;GAC1B;EACD;EAEA,MAAM,YAAY,WAAW,MAAM;EACnC,IAAI,WACH,OAAO,OAAO,KAAK,UAAU,GAAG,KAAK,CAAC;CAGxC;CAEA,OAAO;AACR"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@geekmidas/cloud",
3
- "version": "10.0.0-alpha.11",
3
+ "version": "10.0.0-alpha.13",
4
4
  "type": "module",
5
5
  "files": [
6
6
  "dist",
@@ -41,8 +41,8 @@
41
41
  },
42
42
  "dependencies": {
43
43
  "lodash.snakecase": "~4.1.1",
44
- "@geekmidas/envkit": "10.0.0-alpha.11",
45
- "@geekmidas/manifest": "10.0.0-alpha.11"
44
+ "@geekmidas/envkit": "10.0.0-alpha.13",
45
+ "@geekmidas/manifest": "10.0.0-alpha.13"
46
46
  },
47
47
  "devDependencies": {
48
48
  "@types/lodash.get": "~4.4.9",
@@ -58,10 +58,10 @@
58
58
  "@pulumi/aws": ">=7.47.0",
59
59
  "@pulumi/random": ">=4.21.2",
60
60
  "@pulumi/pulumi": ">=3.263.0",
61
- "@geekmidas/manifest": "^10.0.0-alpha.11",
62
- "@geekmidas/storage": "^10.0.0-alpha.11",
63
- "@geekmidas/events": "^10.0.0-alpha.11",
64
- "@geekmidas/db": "^10.0.0-alpha.11"
61
+ "@geekmidas/manifest": "^10.0.0-alpha.13",
62
+ "@geekmidas/storage": "^10.0.0-alpha.13",
63
+ "@geekmidas/events": "^10.0.0-alpha.13",
64
+ "@geekmidas/db": "^10.0.0-alpha.13"
65
65
  },
66
66
  "peerDependenciesMeta": {
67
67
  "@geekmidas/manifest": {
@@ -241,6 +241,13 @@ export interface ApplicationArgs {
241
241
  environmentId: Input<string>;
242
242
  }
243
243
 
244
+ /**
245
+ * The provider itself, for tests: its create/read/update/delete are what talk
246
+ * to Dokploy, and a dynamic resource gives no other way to reach them without a
247
+ * Pulumi engine.
248
+ */
249
+ export { provider as applicationProvider };
250
+
244
251
  export class Application extends dynamic.Resource {
245
252
  declare readonly applicationId: Output<string>;
246
253
  declare readonly appName: Output<string>;
@@ -0,0 +1,148 @@
1
+ import { HttpResponse, http } from 'msw';
2
+ import { setupServer } from 'msw/node';
3
+ import { afterAll, afterEach, beforeAll, describe, expect, it } from 'vitest';
4
+ import { applicationProvider as provider } from '../Application';
5
+
6
+ /**
7
+ * The provider against Dokploy's tRPC API, served by MSW: what each lifecycle
8
+ * call sends, and how it reads what comes back — including "already gone".
9
+ */
10
+
11
+ const endpoint = 'https://dokploy.test';
12
+ const inputs = {
13
+ endpoint,
14
+ apiToken: 'token-1',
15
+ name: 'My API',
16
+ projectId: 'proj-1',
17
+ environmentId: 'env-1',
18
+ };
19
+ /** What state holds once the application exists: every later call gets it. */
20
+ const outs = { ...inputs, applicationId: 'app-1', appName: 'my-api' };
21
+
22
+ const server = setupServer();
23
+ beforeAll(() => server.listen({ onUnhandledRequest: 'error' }));
24
+ afterEach(() => server.resetHandlers());
25
+ afterAll(() => server.close());
26
+
27
+ /** Records the one request a call makes, and answers it. */
28
+ function answer(
29
+ method: 'get' | 'post',
30
+ path: string,
31
+ respond: () => Response,
32
+ ): { request: () => Promise<{ body: unknown; headers: Headers }> } {
33
+ let seen: Request | undefined;
34
+ server.use(
35
+ http[method](`${endpoint}/api/trpc/${path}`, ({ request }) => {
36
+ seen = request.clone();
37
+ return respond();
38
+ }),
39
+ );
40
+ return {
41
+ request: async () => ({
42
+ body: seen && method === 'post' ? await seen.json() : undefined,
43
+ headers: seen!.headers,
44
+ }),
45
+ };
46
+ }
47
+
48
+ describe('Dokploy application provider', () => {
49
+ it('creates the application under the name Dokploy derives', async () => {
50
+ const call = answer('post', 'application.create', () =>
51
+ HttpResponse.json({ applicationId: 'app-1', appName: 'my-api' }),
52
+ );
53
+
54
+ const result = await provider.create!(inputs);
55
+
56
+ const { body, headers } = await call.request();
57
+ expect(headers.get('x-api-key')).toBe('token-1');
58
+ expect(body).toEqual({
59
+ name: 'My API',
60
+ projectId: 'proj-1',
61
+ environmentId: 'env-1',
62
+ appName: 'my-api',
63
+ });
64
+ // Pulumi's id is Dokploy's, so state and the Dokploy UI name the same thing.
65
+ expect(result).toEqual({
66
+ id: 'app-1',
67
+ outs: { ...inputs, applicationId: 'app-1', appName: 'my-api' },
68
+ });
69
+ });
70
+
71
+ it('refreshes from the server, and reports one deleted by hand as gone', async () => {
72
+ answer('get', 'application.one', () =>
73
+ HttpResponse.json({ applicationId: 'app-1', appName: 'my-api-2' }),
74
+ );
75
+ expect(await provider.read!('app-1', outs)).toEqual({
76
+ id: 'app-1',
77
+ props: { ...inputs, applicationId: 'app-1', appName: 'my-api-2' },
78
+ });
79
+
80
+ server.resetHandlers();
81
+ answer('get', 'application.one', () => HttpResponse.json(null));
82
+ expect(await provider.read!('app-1', outs)).toEqual({ id: undefined });
83
+ });
84
+
85
+ it('diffs through the same rule preview uses', async () => {
86
+ expect(
87
+ await provider.diff!('app-1', outs, { ...inputs, name: 'Gateway' }),
88
+ ).toMatchObject({ changes: true, replaces: ['name'] });
89
+ });
90
+
91
+ it('renames in place, and reports the app name that follows', async () => {
92
+ const call = answer('post', 'application.update', () =>
93
+ HttpResponse.json({}),
94
+ );
95
+
96
+ const result = await provider.update!('app-1', outs, {
97
+ ...inputs,
98
+ name: 'My Api',
99
+ });
100
+
101
+ expect((await call.request()).body).toEqual({
102
+ applicationId: 'app-1',
103
+ name: 'My Api',
104
+ });
105
+ expect(result).toEqual({
106
+ outs: {
107
+ ...inputs,
108
+ name: 'My Api',
109
+ applicationId: 'app-1',
110
+ appName: 'my-api',
111
+ },
112
+ });
113
+ });
114
+
115
+ it('treats an application that is already gone as deleted', async () => {
116
+ const call = answer('post', 'application.remove', () =>
117
+ HttpResponse.text('no such application', {
118
+ status: 404,
119
+ statusText: 'Not Found',
120
+ }),
121
+ );
122
+
123
+ await expect(provider.delete!('app-1', outs)).resolves.toBeUndefined();
124
+ expect((await call.request()).body).toEqual({ applicationId: 'app-1' });
125
+ });
126
+
127
+ it('fails a delete, or any call, that Dokploy refused for another reason', async () => {
128
+ answer('post', 'application.remove', () =>
129
+ HttpResponse.text('database is locked', {
130
+ status: 500,
131
+ statusText: 'Internal Server Error',
132
+ }),
133
+ );
134
+ await expect(provider.delete!('app-1', outs)).rejects.toThrow(
135
+ 'Dokploy application.remove failed: 500 Internal Server Error — database is locked',
136
+ );
137
+
138
+ server.resetHandlers();
139
+ answer(
140
+ 'post',
141
+ 'application.create',
142
+ () => new HttpResponse(null, { status: 401, statusText: 'Unauthorized' }),
143
+ );
144
+ await expect(provider.create!(inputs)).rejects.toThrow(
145
+ 'Dokploy application.create failed: 401 Unauthorized',
146
+ );
147
+ });
148
+ });