@geekmidas/cloud 9.0.2 → 10.0.0-alpha.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{index-ByEJy40r.d.cts → index-B5CZ1xVf.d.cts} +17 -9
- package/dist/index-B5CZ1xVf.d.cts.map +1 -0
- package/dist/{index-DZ0QrJQr.d.mts → index-DhHRjduZ.d.mts} +17 -9
- package/dist/index-DhHRjduZ.d.mts.map +1 -0
- package/dist/index.cjs +1 -1
- package/dist/index.d.cts +1 -1
- package/dist/index.d.mts +1 -1
- package/dist/index.mjs +1 -1
- package/dist/utils/index.cjs +1 -1
- package/dist/utils/index.d.cts +1 -1
- package/dist/utils/index.d.mts +1 -1
- package/dist/utils/index.mjs +1 -1
- package/dist/{utils-CtMjuIMR.cjs → utils-B1a2UuEO.cjs} +5 -5
- package/dist/utils-B1a2UuEO.cjs.map +1 -0
- package/dist/{utils-BdKG20_m.mjs → utils-DMOXJ27j.mjs} +5 -5
- package/dist/utils-DMOXJ27j.mjs.map +1 -0
- package/package.json +44 -7
- package/src/dokploy/Application.ts +259 -0
- package/src/dokploy/__tests__/Application.spec.ts +69 -0
- package/src/dokploy/index.ts +18 -0
- package/src/sst/__tests__/LinkedEnvironment.spec.ts +4 -1
- package/src/sst/__tests__/backends.spec.ts +249 -0
- package/src/sst/__tests__/bootstrap.spec.ts +140 -0
- package/src/sst/__tests__/database.spec.ts +119 -0
- package/src/sst/__tests__/fromManifest.spec.ts +266 -0
- package/src/sst/__tests__/provides.spec.ts +107 -0
- package/src/sst/__tests__/ses.spec.ts +93 -0
- package/src/sst/__tests__/surfaces.spec.ts +132 -0
- package/src/sst/__type-tests__/authorizers.type-test.ts +2 -2
- package/src/sst/__type-tests__/manifest.type-test.ts +3 -3
- package/src/sst/__type-tests__/messaging.type-test.ts +3 -3
- package/src/sst/__type-tests__/storage.type-test.ts +2 -2
- package/src/sst/{Api.ts → aws/Api.ts} +3 -3
- package/src/sst/aws/Cache.ts +259 -0
- package/src/sst/aws/Credential.ts +28 -0
- package/src/sst/{Cron.ts → aws/Cron.ts} +2 -2
- package/src/sst/aws/Database.ts +190 -0
- package/src/sst/aws/DatabaseBootstrap.ts +309 -0
- package/src/sst/aws/DerivedDatabase.ts +117 -0
- package/src/sst/aws/Email.ts +181 -0
- package/src/sst/aws/FileServer.ts +82 -0
- package/src/sst/{Function.ts → aws/Function.ts} +3 -3
- package/src/sst/aws/ObjectStorage.ts +76 -0
- package/src/sst/aws/Queue.ts +116 -0
- package/src/sst/aws/RestApiSurface.ts +92 -0
- package/src/sst/aws/Secret.ts +76 -0
- package/src/sst/aws/StaticSite.ts +92 -0
- package/src/sst/{Storage.ts → aws/Storage.ts} +3 -3
- package/src/sst/aws/Topic.ts +68 -0
- package/src/sst/aws/bootstrap/handler.ts +110 -0
- package/src/sst/aws/ses.ts +132 -0
- package/src/sst/errors.ts +65 -0
- package/src/sst/fromManifest.ts +899 -0
- package/src/sst/index.ts +62 -7
- package/src/sst/naming.ts +37 -16
- package/src/sst/tsconfig.json +2 -2
- package/src/sst/upstash.d.ts +38 -0
- package/dist/index-ByEJy40r.d.cts.map +0 -1
- package/dist/index-DZ0QrJQr.d.mts.map +0 -1
- package/dist/utils-BdKG20_m.mjs.map +0 -1
- package/dist/utils-CtMjuIMR.cjs.map +0 -1
- package/src/sst/Queue.ts +0 -46
- package/src/sst/Topic.ts +0 -37
|
@@ -5,19 +5,27 @@ declare enum ResourceType {
|
|
|
5
5
|
ApiGatewayV2 = "sst.aws.ApiGatewayV2",
|
|
6
6
|
Postgres = "sst.aws.Postgres",
|
|
7
7
|
Function = "sst.aws.Function",
|
|
8
|
-
|
|
8
|
+
ObjectStorage = "sst.aws.Bucket",
|
|
9
9
|
Vpc = "sst.aws.Vpc",
|
|
10
10
|
Secret = "sst.sst.Secret",
|
|
11
11
|
SSTSecret = "sst:sst:Secret",
|
|
12
12
|
SSTFunction = "sst:sst:Function",
|
|
13
13
|
SSTApiGatewayV2 = "sst:aws:ApiGatewayV2",
|
|
14
14
|
SSTPostgres = "sst:aws:Postgres",
|
|
15
|
-
|
|
15
|
+
SSTObjectStorage = "sst:aws:Bucket",
|
|
16
16
|
SnsTopic = "sst:aws:SnsTopic",
|
|
17
17
|
}
|
|
18
18
|
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
|
+
*/
|
|
19
27
|
type ApiGatewayV2 = {
|
|
20
|
-
type: ResourceType.ApiGatewayV2;
|
|
28
|
+
type: ResourceType.ApiGatewayV2 | ResourceType.SSTApiGatewayV2;
|
|
21
29
|
url: string;
|
|
22
30
|
};
|
|
23
31
|
type Postgres = {
|
|
@@ -25,16 +33,16 @@ type Postgres = {
|
|
|
25
33
|
host: string;
|
|
26
34
|
password: string;
|
|
27
35
|
port: number;
|
|
28
|
-
type: ResourceType.Postgres;
|
|
36
|
+
type: ResourceType.Postgres | ResourceType.SSTPostgres;
|
|
29
37
|
username: string;
|
|
30
38
|
};
|
|
31
39
|
type Function = {
|
|
32
40
|
name: string;
|
|
33
|
-
type: ResourceType.Function;
|
|
41
|
+
type: ResourceType.Function | ResourceType.SSTFunction;
|
|
34
42
|
};
|
|
35
43
|
type Bucket = {
|
|
36
44
|
name: string;
|
|
37
|
-
type: ResourceType.
|
|
45
|
+
type: ResourceType.ObjectStorage | ResourceType.SSTObjectStorage;
|
|
38
46
|
};
|
|
39
47
|
type SnsTopic = {
|
|
40
48
|
arn: string;
|
|
@@ -45,12 +53,12 @@ type Vpc = {
|
|
|
45
53
|
type: ResourceType.Vpc;
|
|
46
54
|
};
|
|
47
55
|
type Secret = {
|
|
48
|
-
type: ResourceType.Secret;
|
|
56
|
+
type: ResourceType.Secret | ResourceType.SSTSecret;
|
|
49
57
|
value: string;
|
|
50
58
|
};
|
|
51
|
-
type Resource = ApiGatewayV2 | Postgres | Function | Bucket | Vpc | Secret;
|
|
59
|
+
type Resource = ApiGatewayV2 | Postgres | Function | Bucket | SnsTopic | Vpc | Secret;
|
|
52
60
|
type ResourceProcessor<K extends Resource> = (name: string, value: K) => Record<string, string | number>;
|
|
53
61
|
//# sourceMappingURL=index.d.ts.map
|
|
54
62
|
//#endregion
|
|
55
63
|
export { ApiGatewayV2, Bucket, Function, Postgres, Resource, ResourceProcessor, ResourceType, Secret, SnsTopic, Vpc, buildResourceEnv, environmentCase, getLocalIpAddress };
|
|
56
|
-
//# sourceMappingURL=index-
|
|
64
|
+
//# sourceMappingURL=index-B5CZ1xVf.d.cts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index-B5CZ1xVf.d.cts","names":[],"sources":["../src/utils/index.ts"],"sourcesContent":[],"mappings":";iBAGgB,iBAAA,CAAA;AAAA,iBAcA,eAAA,CAdiB,IAAA,EAAA,MAAA,CAAA,EAAA,MAAA;AAcjB,aAOJ,YAAA;EAAA,YAAA,GAAY,sBAAA;EA+DR,QAAA,GAAA,kBAAgB;EAAA,QAAA,GAAA,kBAAA;EAAA,aACR,GAAA,gBAAA;EAAQ,GAAvB,GAAA,aAAA;EAAM,MACZ,GAAA,gBAAA;EAAM,SAAA,GAAA,gBAAA;EA0BG,WAAA,GAAA,kBAAY;EAAA,eAAA,GAAA,sBAAA;EAAA,WACjB,GAAA,kBAAa;EAAY,gBAAgB,GAAA,gBAAA;EAAe,QAAA,GAAA,kBAAA;AAI/D;AAAoB,iBAjCJ,gBAAA,CAiCI,MAAA,EAhCX,MAgCW,CAAA,MAAA,EAhCI,QAgCJ,GAAA,MAAA,CAAA,CAAA,EA/BjB,MA+BiB,CAAA,MAAA,EAAA,MAAA,CAAA;;;AAKmC;AAIvD;;;;AAEuD;AAG3C,KAnBA,YAAA,GAmBM;EAAA,IAAA,EAlBX,YAAA,CAAa,YAkBF,GAlBiB,YAAA,CAAa,eAkB9B;EAAA,GAEX,EAAA,MAAA;CAA0B;AAAgC,KAhBrD,QAAA,GAgBqD;EAGrD,QAAA,EAAA,MAAQ;EAKR,IAAA,EAAG,MAAA;EAKH,QAAA,EAAM,MAAA;EAAA,IAAA,EAAA,MAAA;EAAA,IACX,EAzBA,YAAA,CAAa,QAyBA,GAzBW,YAAA,CAAa,WAyBxB;EAAM,QAAG,EAAA,MAAa;AAAS,CAAA;AAIvC,KAzBA,QAAA,GAyBQ;EAAA,IAAA,EAAA,MAAA;EAAA,IACjB,EAxBI,YAAA,CAAa,QAwBjB,GAxB4B,YAAA,CAAa,WAwBzC;CAAY;AAEZ,KAvBS,MAAA,GAuBT;EAAQ,IACR,EAAA,MAAA;EAAM,IACN,EAvBI,YAAA,CAAa,aAuBjB,GAvBiC,YAAA,CAAa,gBAuB9C;CAAQ;AAER,KAtBS,QAAA,GAsBT;EAAM,GAAA,EAAA,MAAA;EAEG,IAAA,EAtBL,YAAA,CAAa,QAsBS;CAAA;AAAW,KAnB5B,GAAA,GAmB4B;EAAQ,OAExC,EAAA,MAAA;EAAC,IACJ,EApBE,YAAA,CAAa,GAoBf;AAAM,CAAA;KAjBC,MAAA;QACL,YAAA,CAAa,SAAS,YAAA,CAAa;;;KAI9B,QAAA,GACT,eACA,WACA,WACA,SACA,WACA,MACA;KAES,4BAA4B,kCAEhC,MACH"}
|
|
@@ -5,19 +5,27 @@ declare enum ResourceType {
|
|
|
5
5
|
ApiGatewayV2 = "sst.aws.ApiGatewayV2",
|
|
6
6
|
Postgres = "sst.aws.Postgres",
|
|
7
7
|
Function = "sst.aws.Function",
|
|
8
|
-
|
|
8
|
+
ObjectStorage = "sst.aws.Bucket",
|
|
9
9
|
Vpc = "sst.aws.Vpc",
|
|
10
10
|
Secret = "sst.sst.Secret",
|
|
11
11
|
SSTSecret = "sst:sst:Secret",
|
|
12
12
|
SSTFunction = "sst:sst:Function",
|
|
13
13
|
SSTApiGatewayV2 = "sst:aws:ApiGatewayV2",
|
|
14
14
|
SSTPostgres = "sst:aws:Postgres",
|
|
15
|
-
|
|
15
|
+
SSTObjectStorage = "sst:aws:Bucket",
|
|
16
16
|
SnsTopic = "sst:aws:SnsTopic",
|
|
17
17
|
}
|
|
18
18
|
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
|
+
*/
|
|
19
27
|
type ApiGatewayV2 = {
|
|
20
|
-
type: ResourceType.ApiGatewayV2;
|
|
28
|
+
type: ResourceType.ApiGatewayV2 | ResourceType.SSTApiGatewayV2;
|
|
21
29
|
url: string;
|
|
22
30
|
};
|
|
23
31
|
type Postgres = {
|
|
@@ -25,16 +33,16 @@ type Postgres = {
|
|
|
25
33
|
host: string;
|
|
26
34
|
password: string;
|
|
27
35
|
port: number;
|
|
28
|
-
type: ResourceType.Postgres;
|
|
36
|
+
type: ResourceType.Postgres | ResourceType.SSTPostgres;
|
|
29
37
|
username: string;
|
|
30
38
|
};
|
|
31
39
|
type Function = {
|
|
32
40
|
name: string;
|
|
33
|
-
type: ResourceType.Function;
|
|
41
|
+
type: ResourceType.Function | ResourceType.SSTFunction;
|
|
34
42
|
};
|
|
35
43
|
type Bucket = {
|
|
36
44
|
name: string;
|
|
37
|
-
type: ResourceType.
|
|
45
|
+
type: ResourceType.ObjectStorage | ResourceType.SSTObjectStorage;
|
|
38
46
|
};
|
|
39
47
|
type SnsTopic = {
|
|
40
48
|
arn: string;
|
|
@@ -45,12 +53,12 @@ type Vpc = {
|
|
|
45
53
|
type: ResourceType.Vpc;
|
|
46
54
|
};
|
|
47
55
|
type Secret = {
|
|
48
|
-
type: ResourceType.Secret;
|
|
56
|
+
type: ResourceType.Secret | ResourceType.SSTSecret;
|
|
49
57
|
value: string;
|
|
50
58
|
};
|
|
51
|
-
type Resource = ApiGatewayV2 | Postgres | Function | Bucket | Vpc | Secret;
|
|
59
|
+
type Resource = ApiGatewayV2 | Postgres | Function | Bucket | SnsTopic | Vpc | Secret;
|
|
52
60
|
type ResourceProcessor<K extends Resource> = (name: string, value: K) => Record<string, string | number>;
|
|
53
61
|
//# sourceMappingURL=index.d.ts.map
|
|
54
62
|
//#endregion
|
|
55
63
|
export { ApiGatewayV2, Bucket, Function, Postgres, Resource, ResourceProcessor, ResourceType, Secret, SnsTopic, Vpc, buildResourceEnv, environmentCase, getLocalIpAddress };
|
|
56
|
-
//# sourceMappingURL=index-
|
|
64
|
+
//# sourceMappingURL=index-DhHRjduZ.d.mts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index-DhHRjduZ.d.mts","names":[],"sources":["../src/utils/index.ts"],"sourcesContent":[],"mappings":";iBAGgB,iBAAA,CAAA;AAAA,iBAcA,eAAA,CAdiB,IAAA,EAAA,MAAA,CAAA,EAAA,MAAA;AAcjB,aAOJ,YAAA;EAAA,YAAA,GAAY,sBAAA;EA+DR,QAAA,GAAA,kBAAgB;EAAA,QAAA,GAAA,kBAAA;EAAA,aACR,GAAA,gBAAA;EAAQ,GAAvB,GAAA,aAAA;EAAM,MACZ,GAAA,gBAAA;EAAM,SAAA,GAAA,gBAAA;EA0BG,WAAA,GAAA,kBAAY;EAAA,eAAA,GAAA,sBAAA;EAAA,WACjB,GAAA,kBAAa;EAAY,gBAAgB,GAAA,gBAAA;EAAe,QAAA,GAAA,kBAAA;AAI/D;AAAoB,iBAjCJ,gBAAA,CAiCI,MAAA,EAhCX,MAgCW,CAAA,MAAA,EAhCI,QAgCJ,GAAA,MAAA,CAAA,CAAA,EA/BjB,MA+BiB,CAAA,MAAA,EAAA,MAAA,CAAA;;;AAKmC;AAIvD;;;;AAEuD;AAG3C,KAnBA,YAAA,GAmBM;EAAA,IAAA,EAlBX,YAAA,CAAa,YAkBF,GAlBiB,YAAA,CAAa,eAkB9B;EAAA,GAEX,EAAA,MAAA;CAA0B;AAAgC,KAhBrD,QAAA,GAgBqD;EAGrD,QAAA,EAAA,MAAQ;EAKR,IAAA,EAAG,MAAA;EAKH,QAAA,EAAM,MAAA;EAAA,IAAA,EAAA,MAAA;EAAA,IACX,EAzBA,YAAA,CAAa,QAyBA,GAzBW,YAAA,CAAa,WAyBxB;EAAM,QAAG,EAAA,MAAa;AAAS,CAAA;AAIvC,KAzBA,QAAA,GAyBQ;EAAA,IAAA,EAAA,MAAA;EAAA,IACjB,EAxBI,YAAA,CAAa,QAwBjB,GAxB4B,YAAA,CAAa,WAwBzC;CAAY;AAEZ,KAvBS,MAAA,GAuBT;EAAQ,IACR,EAAA,MAAA;EAAM,IACN,EAvBI,YAAA,CAAa,aAuBjB,GAvBiC,YAAA,CAAa,gBAuB9C;CAAQ;AAER,KAtBS,QAAA,GAsBT;EAAM,GAAA,EAAA,MAAA;EAEG,IAAA,EAtBL,YAAA,CAAa,QAsBS;CAAA;AAAW,KAnB5B,GAAA,GAmB4B;EAAQ,OAExC,EAAA,MAAA;EAAC,IACJ,EApBE,YAAA,CAAa,GAoBf;AAAM,CAAA;KAjBC,MAAA;QACL,YAAA,CAAa,SAAS,YAAA,CAAa;;;KAI9B,QAAA,GACT,eACA,WACA,WACA,SACA,WACA,MACA;KAES,4BAA4B,kCAEhC,MACH"}
|
package/dist/index.cjs
CHANGED
package/dist/index.d.cts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { buildResourceEnv } from "./index-
|
|
1
|
+
import { buildResourceEnv } from "./index-B5CZ1xVf.cjs";
|
|
2
2
|
export { buildResourceEnv };
|
package/dist/index.d.mts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { buildResourceEnv } from "./index-
|
|
1
|
+
import { buildResourceEnv } from "./index-DhHRjduZ.mjs";
|
|
2
2
|
export { buildResourceEnv };
|
package/dist/index.mjs
CHANGED
package/dist/utils/index.cjs
CHANGED
package/dist/utils/index.d.cts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { ApiGatewayV2, Bucket, Function, Postgres, Resource, ResourceProcessor, ResourceType, Secret, SnsTopic, Vpc, buildResourceEnv, environmentCase, getLocalIpAddress } from "../index-
|
|
1
|
+
import { ApiGatewayV2, Bucket, Function, Postgres, Resource, ResourceProcessor, ResourceType, Secret, SnsTopic, Vpc, buildResourceEnv, environmentCase, getLocalIpAddress } from "../index-B5CZ1xVf.cjs";
|
|
2
2
|
export { ApiGatewayV2, Bucket, Function, Postgres, Resource, ResourceProcessor, ResourceType, Secret, SnsTopic, Vpc, buildResourceEnv, environmentCase, getLocalIpAddress };
|
package/dist/utils/index.d.mts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { ApiGatewayV2, Bucket, Function, Postgres, Resource, ResourceProcessor, ResourceType, Secret, SnsTopic, Vpc, buildResourceEnv, environmentCase, getLocalIpAddress } from "../index-
|
|
1
|
+
import { ApiGatewayV2, Bucket, Function, Postgres, Resource, ResourceProcessor, ResourceType, Secret, SnsTopic, Vpc, buildResourceEnv, environmentCase, getLocalIpAddress } from "../index-DhHRjduZ.mjs";
|
|
2
2
|
export { ApiGatewayV2, Bucket, Function, Postgres, Resource, ResourceProcessor, ResourceType, Secret, SnsTopic, Vpc, buildResourceEnv, environmentCase, getLocalIpAddress };
|
package/dist/utils/index.mjs
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
import { ResourceType, buildResourceEnv, environmentCase, getLocalIpAddress } from "../utils-
|
|
1
|
+
import { ResourceType, buildResourceEnv, environmentCase, getLocalIpAddress } from "../utils-DMOXJ27j.mjs";
|
|
2
2
|
|
|
3
3
|
export { ResourceType, buildResourceEnv, environmentCase, getLocalIpAddress };
|
|
@@ -42,14 +42,14 @@ let ResourceType = /* @__PURE__ */ function(ResourceType$1) {
|
|
|
42
42
|
ResourceType$1["ApiGatewayV2"] = "sst.aws.ApiGatewayV2";
|
|
43
43
|
ResourceType$1["Postgres"] = "sst.aws.Postgres";
|
|
44
44
|
ResourceType$1["Function"] = "sst.aws.Function";
|
|
45
|
-
ResourceType$1["
|
|
45
|
+
ResourceType$1["ObjectStorage"] = "sst.aws.Bucket";
|
|
46
46
|
ResourceType$1["Vpc"] = "sst.aws.Vpc";
|
|
47
47
|
ResourceType$1["Secret"] = "sst.sst.Secret";
|
|
48
48
|
ResourceType$1["SSTSecret"] = "sst:sst:Secret";
|
|
49
49
|
ResourceType$1["SSTFunction"] = "sst:sst:Function";
|
|
50
50
|
ResourceType$1["SSTApiGatewayV2"] = "sst:aws:ApiGatewayV2";
|
|
51
51
|
ResourceType$1["SSTPostgres"] = "sst:aws:Postgres";
|
|
52
|
-
ResourceType$1["
|
|
52
|
+
ResourceType$1["SSTObjectStorage"] = "sst:aws:Bucket";
|
|
53
53
|
ResourceType$1["SnsTopic"] = "sst:aws:SnsTopic";
|
|
54
54
|
return ResourceType$1;
|
|
55
55
|
}({});
|
|
@@ -80,9 +80,9 @@ const processors = {
|
|
|
80
80
|
[ResourceType.Vpc]: noop,
|
|
81
81
|
[ResourceType.Secret]: secret,
|
|
82
82
|
[ResourceType.Postgres]: postgres,
|
|
83
|
-
[ResourceType.
|
|
83
|
+
[ResourceType.ObjectStorage]: bucket,
|
|
84
84
|
[ResourceType.SSTSecret]: secret,
|
|
85
|
-
[ResourceType.
|
|
85
|
+
[ResourceType.SSTObjectStorage]: bucket,
|
|
86
86
|
[ResourceType.SSTFunction]: noop,
|
|
87
87
|
[ResourceType.SSTPostgres]: postgres,
|
|
88
88
|
[ResourceType.SSTApiGatewayV2]: noop,
|
|
@@ -126,4 +126,4 @@ Object.defineProperty(exports, 'getLocalIpAddress', {
|
|
|
126
126
|
return getLocalIpAddress;
|
|
127
127
|
}
|
|
128
128
|
});
|
|
129
|
-
//# sourceMappingURL=utils-
|
|
129
|
+
//# sourceMappingURL=utils-B1a2UuEO.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"utils-B1a2UuEO.cjs","names":["name: string","value: Secret","key: string","value: Postgres","value: Bucket","value: SnsTopic","_name: string","_value: any","processors: Record<ResourceType, ResourceProcessor<any>>","record: Record<string, Resource | string>","env: Record<string, string>"],"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,gBAAG,mBAAmB;AAChD,MAAK,MAAM,iBAAiB,mBAAmB;EAC9C,MAAM,YAAY,kBAAkB,kBAAkB,CAAE;AACxD,OAAK,MAAM,eAAe,UAEzB,KAAI,YAAY,WAAW,WAAW,YAAY,SACjD,QAAO,YAAY;CAGrB;AACD,QAAO;AACP;AAED,SAAgB,gBAAgBA,MAAc;AAC7C,QAAO,8BAAU,KAAK,CACpB,aAAa,CACb,QAAQ,SAAS,CAAC,MAAM;AACxB,SAAO,EAAE,QAAQ,KAAK,GAAG;CACzB,EAAC;AACH;AACD,IAAY,wDAAL;AACN;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AACA;AAED,MAAM,SAAS,CAACA,MAAcC,WAAmB,GAC/C,gBAAgB,KAAK,GAAG,MAAM,MAC/B;AACD,MAAM,WAAW,CAACC,KAAaC,UAAoB;CAClD,MAAM,UAAU,EAAE,gBAAgB,IAAI,CAAC;AACvC,QAAO;IACJ,EAAE,OAAO,SAAS,MAAM;IACxB,EAAE,OAAO,SAAS,MAAM;IACxB,EAAE,OAAO,aAAa,MAAM;IAC5B,EAAE,OAAO,SAAS,MAAM;IACxB,EAAE,OAAO,aAAa,MAAM;CAC9B;AACD;AAED,MAAM,SAAS,CAACH,MAAcI,UAAkB;CAC/C,MAAM,UAAU,EAAE,gBAAgB,KAAK,CAAC;AACxC,QAAO,IACJ,EAAE,OAAO,SAAS,MAAM,KAC1B;AACD;AAED,MAAM,QAAQ,CAACJ,MAAcK,UAAoB;CAChD,MAAM,UAAU,EAAE,gBAAgB,KAAK,CAAC;CACxC,MAAM,OAAO,EAAE,OAAO;AAEtB,QAAO,GACL,MAAM,MAAM,IACb;AACD;AAED,MAAM,OAAO,CAACC,OAAeC,YAAiB,CAAE;AAEhD,MAAMC,aAA2D;EAC/D,aAAa,eAAe;EAC5B,aAAa,WAAW;EACxB,aAAa,MAAM;EACnB,aAAa,SAAS;EACtB,aAAa,WAAW;EACxB,aAAa,gBAAgB;EAE7B,aAAa,YAAY;EACzB,aAAa,mBAAmB;EAChC,aAAa,cAAc;EAC3B,aAAa,cAAc;EAC3B,aAAa,kBAAkB;EAC/B,aAAa,WAAW;AACzB;AAED,SAAgB,iBACfC,QACyB;CACzB,MAAMC,MAA8B,CAAE;AACtC,MAAK,MAAM,CAAC,GAAG,MAAM,IAAI,OAAO,QAAQ,OAAO,EAAE;AAChD,aAAW,UAAU,UAAU;AAC9B,OAAI,gBAAgB,EAAE,IAAI;AAC1B;EACA;EAED,MAAM,YAAY,WAAW,MAAM;AACnC,MAAI,UACH,QAAO,OAAO,KAAK,UAAU,GAAG,MAAM,CAAC;CAGxC;AAED,QAAO;AACP"}
|
|
@@ -19,14 +19,14 @@ let ResourceType = /* @__PURE__ */ function(ResourceType$1) {
|
|
|
19
19
|
ResourceType$1["ApiGatewayV2"] = "sst.aws.ApiGatewayV2";
|
|
20
20
|
ResourceType$1["Postgres"] = "sst.aws.Postgres";
|
|
21
21
|
ResourceType$1["Function"] = "sst.aws.Function";
|
|
22
|
-
ResourceType$1["
|
|
22
|
+
ResourceType$1["ObjectStorage"] = "sst.aws.Bucket";
|
|
23
23
|
ResourceType$1["Vpc"] = "sst.aws.Vpc";
|
|
24
24
|
ResourceType$1["Secret"] = "sst.sst.Secret";
|
|
25
25
|
ResourceType$1["SSTSecret"] = "sst:sst:Secret";
|
|
26
26
|
ResourceType$1["SSTFunction"] = "sst:sst:Function";
|
|
27
27
|
ResourceType$1["SSTApiGatewayV2"] = "sst:aws:ApiGatewayV2";
|
|
28
28
|
ResourceType$1["SSTPostgres"] = "sst:aws:Postgres";
|
|
29
|
-
ResourceType$1["
|
|
29
|
+
ResourceType$1["SSTObjectStorage"] = "sst:aws:Bucket";
|
|
30
30
|
ResourceType$1["SnsTopic"] = "sst:aws:SnsTopic";
|
|
31
31
|
return ResourceType$1;
|
|
32
32
|
}({});
|
|
@@ -57,9 +57,9 @@ const processors = {
|
|
|
57
57
|
[ResourceType.Vpc]: noop,
|
|
58
58
|
[ResourceType.Secret]: secret,
|
|
59
59
|
[ResourceType.Postgres]: postgres,
|
|
60
|
-
[ResourceType.
|
|
60
|
+
[ResourceType.ObjectStorage]: bucket,
|
|
61
61
|
[ResourceType.SSTSecret]: secret,
|
|
62
|
-
[ResourceType.
|
|
62
|
+
[ResourceType.SSTObjectStorage]: bucket,
|
|
63
63
|
[ResourceType.SSTFunction]: noop,
|
|
64
64
|
[ResourceType.SSTPostgres]: postgres,
|
|
65
65
|
[ResourceType.SSTApiGatewayV2]: noop,
|
|
@@ -80,4 +80,4 @@ function buildResourceEnv(record) {
|
|
|
80
80
|
|
|
81
81
|
//#endregion
|
|
82
82
|
export { ResourceType, buildResourceEnv, environmentCase, getLocalIpAddress };
|
|
83
|
-
//# sourceMappingURL=utils-
|
|
83
|
+
//# sourceMappingURL=utils-DMOXJ27j.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"utils-DMOXJ27j.mjs","names":["name: string","value: Secret","key: string","value: Postgres","value: Bucket","value: SnsTopic","_name: string","_value: any","processors: Record<ResourceType, ResourceProcessor<any>>","record: Record<string, Resource | string>","env: Record<string, string>"],"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,mBAAmB;AAChD,MAAK,MAAM,iBAAiB,mBAAmB;EAC9C,MAAM,YAAY,kBAAkB,kBAAkB,CAAE;AACxD,OAAK,MAAM,eAAe,UAEzB,KAAI,YAAY,WAAW,WAAW,YAAY,SACjD,QAAO,YAAY;CAGrB;AACD,QAAO;AACP;AAED,SAAgB,gBAAgBA,MAAc;AAC7C,QAAO,UAAU,KAAK,CACpB,aAAa,CACb,QAAQ,SAAS,CAAC,MAAM;AACxB,SAAO,EAAE,QAAQ,KAAK,GAAG;CACzB,EAAC;AACH;AACD,IAAY,wDAAL;AACN;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AACA;AAED,MAAM,SAAS,CAACA,MAAcC,WAAmB,GAC/C,gBAAgB,KAAK,GAAG,MAAM,MAC/B;AACD,MAAM,WAAW,CAACC,KAAaC,UAAoB;CAClD,MAAM,UAAU,EAAE,gBAAgB,IAAI,CAAC;AACvC,QAAO;IACJ,EAAE,OAAO,SAAS,MAAM;IACxB,EAAE,OAAO,SAAS,MAAM;IACxB,EAAE,OAAO,aAAa,MAAM;IAC5B,EAAE,OAAO,SAAS,MAAM;IACxB,EAAE,OAAO,aAAa,MAAM;CAC9B;AACD;AAED,MAAM,SAAS,CAACH,MAAcI,UAAkB;CAC/C,MAAM,UAAU,EAAE,gBAAgB,KAAK,CAAC;AACxC,QAAO,IACJ,EAAE,OAAO,SAAS,MAAM,KAC1B;AACD;AAED,MAAM,QAAQ,CAACJ,MAAcK,UAAoB;CAChD,MAAM,UAAU,EAAE,gBAAgB,KAAK,CAAC;CACxC,MAAM,OAAO,EAAE,OAAO;AAEtB,QAAO,GACL,MAAM,MAAM,IACb;AACD;AAED,MAAM,OAAO,CAACC,OAAeC,YAAiB,CAAE;AAEhD,MAAMC,aAA2D;EAC/D,aAAa,eAAe;EAC5B,aAAa,WAAW;EACxB,aAAa,MAAM;EACnB,aAAa,SAAS;EACtB,aAAa,WAAW;EACxB,aAAa,gBAAgB;EAE7B,aAAa,YAAY;EACzB,aAAa,mBAAmB;EAChC,aAAa,cAAc;EAC3B,aAAa,cAAc;EAC3B,aAAa,kBAAkB;EAC/B,aAAa,WAAW;AACzB;AAED,SAAgB,iBACfC,QACyB;CACzB,MAAMC,MAA8B,CAAE;AACtC,MAAK,MAAM,CAAC,GAAG,MAAM,IAAI,OAAO,QAAQ,OAAO,EAAE;AAChD,aAAW,UAAU,UAAU;AAC9B,OAAI,gBAAgB,EAAE,IAAI;AAC1B;EACA;EAED,MAAM,YAAY,WAAW,MAAM;AACnC,MAAI,UACH,QAAO,OAAO,KAAK,UAAU,GAAG,MAAM,CAAC;CAGxC;AAED,QAAO;AACP"}
|
package/package.json
CHANGED
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@geekmidas/cloud",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "10.0.0-alpha.1",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"files": [
|
|
6
6
|
"dist",
|
|
7
|
-
"src/sst"
|
|
7
|
+
"src/sst",
|
|
8
|
+
"src/dokploy"
|
|
8
9
|
],
|
|
9
10
|
"exports": {
|
|
10
11
|
".": {
|
|
@@ -27,7 +28,8 @@
|
|
|
27
28
|
"default": "./dist/utils/index.cjs"
|
|
28
29
|
}
|
|
29
30
|
},
|
|
30
|
-
"./sst": "./src/sst/index.ts"
|
|
31
|
+
"./sst": "./src/sst/index.ts",
|
|
32
|
+
"./dokploy": "./src/dokploy/index.ts"
|
|
31
33
|
},
|
|
32
34
|
"repository": {
|
|
33
35
|
"type": "git",
|
|
@@ -39,21 +41,56 @@
|
|
|
39
41
|
},
|
|
40
42
|
"dependencies": {
|
|
41
43
|
"lodash.snakecase": "~4.1.1",
|
|
42
|
-
"@geekmidas/envkit": "
|
|
43
|
-
"@geekmidas/manifest": "
|
|
44
|
+
"@geekmidas/envkit": "10.0.0-alpha.1",
|
|
45
|
+
"@geekmidas/manifest": "10.0.0-alpha.1"
|
|
44
46
|
},
|
|
45
47
|
"devDependencies": {
|
|
46
48
|
"@types/lodash.get": "~4.4.9",
|
|
47
49
|
"@types/lodash.set": "~4.3.9",
|
|
48
50
|
"@types/lodash.snakecase": "~4.1.9",
|
|
49
51
|
"@types/node": "~24.9.1",
|
|
52
|
+
"@types/pg": "~8.15.5",
|
|
50
53
|
"sst": "4.15.2"
|
|
51
54
|
},
|
|
52
55
|
"peerDependencies": {
|
|
53
|
-
"sst": "^4.15.2"
|
|
56
|
+
"sst": "^4.15.2",
|
|
57
|
+
"pg": "^8.13.0",
|
|
58
|
+
"@pulumi/aws": "^7.20.0",
|
|
59
|
+
"@pulumi/random": "^4.16.6",
|
|
60
|
+
"@pulumi/pulumi": "^3.215.0",
|
|
61
|
+
"@geekmidas/manifest": "^10.0.0-alpha.1",
|
|
62
|
+
"@geekmidas/storage": "^10.0.0-alpha.1",
|
|
63
|
+
"@geekmidas/events": "^10.0.0-alpha.1",
|
|
64
|
+
"@geekmidas/db": "^10.0.0-alpha.1"
|
|
65
|
+
},
|
|
66
|
+
"peerDependenciesMeta": {
|
|
67
|
+
"@geekmidas/manifest": {
|
|
68
|
+
"optional": true
|
|
69
|
+
},
|
|
70
|
+
"@geekmidas/storage": {
|
|
71
|
+
"optional": true
|
|
72
|
+
},
|
|
73
|
+
"@geekmidas/events": {
|
|
74
|
+
"optional": true
|
|
75
|
+
},
|
|
76
|
+
"@geekmidas/db": {
|
|
77
|
+
"optional": true
|
|
78
|
+
},
|
|
79
|
+
"pg": {
|
|
80
|
+
"optional": true
|
|
81
|
+
},
|
|
82
|
+
"@pulumi/aws": {
|
|
83
|
+
"optional": true
|
|
84
|
+
},
|
|
85
|
+
"@pulumi/random": {
|
|
86
|
+
"optional": true
|
|
87
|
+
},
|
|
88
|
+
"@pulumi/pulumi": {
|
|
89
|
+
"optional": true
|
|
90
|
+
}
|
|
54
91
|
},
|
|
55
92
|
"scripts": {
|
|
56
|
-
"sst:install": "sst install",
|
|
93
|
+
"sst:install": "node -e \"process.exit(require('fs').existsSync('sst.config.ts')?0:1)\" && sst install || true",
|
|
57
94
|
"ts:check:sst": "tsc --noEmit -p src/sst/tsconfig.json 2>&1 | grep -E 'src/sst/.*error TS' && exit 1 || exit 0"
|
|
58
95
|
}
|
|
59
96
|
}
|
|
@@ -0,0 +1,259 @@
|
|
|
1
|
+
import { dynamic, type Input, type Output } from '@pulumi/pulumi';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* A Dokploy application, as a Pulumi resource.
|
|
5
|
+
*
|
|
6
|
+
* **A prototype, and the point of it is the shape rather than the coverage.**
|
|
7
|
+
* One resource, to see whether wrapping Dokploy's REST API in a dynamic provider
|
|
8
|
+
* is worth doing for the rest — because if it is, a whole subsystem goes away.
|
|
9
|
+
*
|
|
10
|
+
* ## Why this is worth trying
|
|
11
|
+
*
|
|
12
|
+
* `packages/cli/src/deploy/` is a deployment engine written by hand: it calls
|
|
13
|
+
* the API, and it remembers what it created in `deploy/state.ts` and
|
|
14
|
+
* `SSMStateProvider` so the next deploy can find the same resources. That second
|
|
15
|
+
* half is the interesting one, because *remembering what you created* is the
|
|
16
|
+
* entire job of a Pulumi state file. A provider does not need it.
|
|
17
|
+
*
|
|
18
|
+
* What else falls out: `pulumi preview` starts working for the server target,
|
|
19
|
+
* and `fromManifest` becomes one shape across both targets — a table of
|
|
20
|
+
* provisioners — rather than an SST adapter beside a bespoke engine.
|
|
21
|
+
*
|
|
22
|
+
* ## Why it is a dynamic provider and not a real one
|
|
23
|
+
*
|
|
24
|
+
* A real Pulumi provider is a plugin binary with a schema, usually generated
|
|
25
|
+
* from a Terraform provider that does not exist here. A dynamic provider is a
|
|
26
|
+
* TypeScript object with `create`/`read`/`update`/`delete`, running in-process
|
|
27
|
+
* during the deploy. SST itself uses this exact escape hatch wherever official
|
|
28
|
+
* coverage stops — `vercel/providers/dns-record.ts`,
|
|
29
|
+
* `cloudflare/providers/kv-data.ts` — which is the precedent worth leaning on.
|
|
30
|
+
*
|
|
31
|
+
* ## The three things that make it risky
|
|
32
|
+
*
|
|
33
|
+
* 1. **The provider is serialised into state.** Pulumi captures the functions
|
|
34
|
+
* below and stores them, so they must be self-contained — no reaching for an
|
|
35
|
+
* import from the surrounding module at call time. That is why the API token
|
|
36
|
+
* is an *input* rather than something closed over, and why `fetch` is used
|
|
37
|
+
* directly instead of `DokployApi`, which would have to serialise with it.
|
|
38
|
+
* 2. **`delete` runs on destroy, and orphans are silent.** Today's engine fails
|
|
39
|
+
* loudly when it cannot find something; a provider that gets destroy wrong
|
|
40
|
+
* leaves resources behind that Pulumi believes it removed. This is the half
|
|
41
|
+
* to be most careful with, and the reason a prototype exists at all.
|
|
42
|
+
* 3. **`diff` is yours.** Without it, preview cannot say what a change will do —
|
|
43
|
+
* which is one of the main reasons for doing this.
|
|
44
|
+
*
|
|
45
|
+
* ## Not verified
|
|
46
|
+
*
|
|
47
|
+
* No Dokploy instance has run this. The shape type-checks and the decisions are
|
|
48
|
+
* assertable; nothing has been created or destroyed against a real server.
|
|
49
|
+
*/
|
|
50
|
+
|
|
51
|
+
interface ApplicationInputs {
|
|
52
|
+
/** Where the Dokploy server answers, e.g. `https://dokploy.example.com`. */
|
|
53
|
+
endpoint: string;
|
|
54
|
+
/**
|
|
55
|
+
* The API token.
|
|
56
|
+
*
|
|
57
|
+
* An input rather than a captured variable, because the provider's functions
|
|
58
|
+
* are serialised into state and a closure over module scope does not survive
|
|
59
|
+
* that. SST's own dynamic providers pass credentials the same way.
|
|
60
|
+
*/
|
|
61
|
+
apiToken: string;
|
|
62
|
+
name: string;
|
|
63
|
+
projectId: string;
|
|
64
|
+
environmentId: string;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
interface ApplicationOutputs extends ApplicationInputs {
|
|
68
|
+
applicationId: string;
|
|
69
|
+
appName: string;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
/**
|
|
73
|
+
* Dokploy's app name rule, applied where the name is decided.
|
|
74
|
+
*
|
|
75
|
+
* The existing client does this inline at the create call; here it is a function
|
|
76
|
+
* because `diff` has to ask whether a *changed* name produces a changed app
|
|
77
|
+
* name, and duplicating the expression is how those two answers drift apart.
|
|
78
|
+
*/
|
|
79
|
+
export function appNameFor(name: string): string {
|
|
80
|
+
return name.toLowerCase().replace(/[^a-z0-9-]/g, '-');
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
/**
|
|
84
|
+
* What a change costs — pure, so preview's behaviour can be asserted without a
|
|
85
|
+
* Dokploy server.
|
|
86
|
+
*
|
|
87
|
+
* The name is the interesting one: Dokploy derives `appName` from it, and
|
|
88
|
+
* changing that is not an update but a different application, so the old one has
|
|
89
|
+
* to go. Saying so here is what makes `pulumi preview` warn *before* the
|
|
90
|
+
* destroy rather than reporting it after.
|
|
91
|
+
*/
|
|
92
|
+
export function diffApplication(
|
|
93
|
+
olds: { name: string; projectId: string; environmentId: string },
|
|
94
|
+
news: { name: string; projectId: string; environmentId: string },
|
|
95
|
+
): { changes: boolean; replaces: string[]; deleteBeforeReplace: boolean } {
|
|
96
|
+
const replaces: string[] = [];
|
|
97
|
+
|
|
98
|
+
if (appNameFor(olds.name) !== appNameFor(news.name)) replaces.push('name');
|
|
99
|
+
if (olds.projectId !== news.projectId) replaces.push('projectId');
|
|
100
|
+
if (olds.environmentId !== news.environmentId) replaces.push('environmentId');
|
|
101
|
+
|
|
102
|
+
return {
|
|
103
|
+
changes: replaces.length > 0 || olds.name !== news.name,
|
|
104
|
+
replaces,
|
|
105
|
+
// Create the replacement before removing the old one. A Dokploy project
|
|
106
|
+
// can hold both for a moment; it cannot hold a gap where the application
|
|
107
|
+
// used to be.
|
|
108
|
+
deleteBeforeReplace: false,
|
|
109
|
+
};
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
const provider: dynamic.ResourceProvider<
|
|
113
|
+
ApplicationInputs,
|
|
114
|
+
ApplicationOutputs
|
|
115
|
+
> = {
|
|
116
|
+
async create(inputs) {
|
|
117
|
+
const application = await call<{
|
|
118
|
+
applicationId: string;
|
|
119
|
+
appName: string;
|
|
120
|
+
}>(inputs, 'application.create', {
|
|
121
|
+
name: inputs.name,
|
|
122
|
+
projectId: inputs.projectId,
|
|
123
|
+
environmentId: inputs.environmentId,
|
|
124
|
+
appName: appNameFor(inputs.name),
|
|
125
|
+
});
|
|
126
|
+
|
|
127
|
+
return {
|
|
128
|
+
// Pulumi's own id for the resource. Using Dokploy's makes the two
|
|
129
|
+
// agree, so a state file read by a human names the same thing the
|
|
130
|
+
// Dokploy UI does.
|
|
131
|
+
id: application.applicationId,
|
|
132
|
+
outs: { ...inputs, ...application },
|
|
133
|
+
};
|
|
134
|
+
},
|
|
135
|
+
|
|
136
|
+
/**
|
|
137
|
+
* Refresh from the server.
|
|
138
|
+
*
|
|
139
|
+
* Returning no id is how a provider says "this is gone", which is what
|
|
140
|
+
* lets `pulumi refresh` notice something deleted in the Dokploy UI rather
|
|
141
|
+
* than failing on the next update against a resource that is not there.
|
|
142
|
+
*/
|
|
143
|
+
async read(id, props) {
|
|
144
|
+
const application = await call<{
|
|
145
|
+
applicationId: string;
|
|
146
|
+
appName: string;
|
|
147
|
+
} | null>(
|
|
148
|
+
props as ApplicationInputs,
|
|
149
|
+
`application.one?applicationId=${id}`,
|
|
150
|
+
undefined,
|
|
151
|
+
);
|
|
152
|
+
|
|
153
|
+
if (!application) return { id: undefined };
|
|
154
|
+
|
|
155
|
+
return { id, props: { ...(props as ApplicationOutputs), ...application } };
|
|
156
|
+
},
|
|
157
|
+
|
|
158
|
+
/**
|
|
159
|
+
* What a change costs.
|
|
160
|
+
*
|
|
161
|
+
* The name is the interesting one: Dokploy derives `appName` from it, and
|
|
162
|
+
* changing that is not an update — it is a different application, so the
|
|
163
|
+
* old one has to go. Saying so here is what makes `pulumi preview` warn
|
|
164
|
+
* before the destroy rather than after.
|
|
165
|
+
*/
|
|
166
|
+
async diff(_id, olds, news) {
|
|
167
|
+
return diffApplication(olds, news);
|
|
168
|
+
},
|
|
169
|
+
|
|
170
|
+
async update(id, _olds, news) {
|
|
171
|
+
await call(news, 'application.update', {
|
|
172
|
+
applicationId: id,
|
|
173
|
+
name: news.name,
|
|
174
|
+
});
|
|
175
|
+
|
|
176
|
+
return {
|
|
177
|
+
outs: { ...news, applicationId: id, appName: appNameFor(news.name) },
|
|
178
|
+
};
|
|
179
|
+
},
|
|
180
|
+
|
|
181
|
+
/**
|
|
182
|
+
* Remove it, and treat "already gone" as success.
|
|
183
|
+
*
|
|
184
|
+
* A destroy that fails because somebody removed the application by hand
|
|
185
|
+
* leaves the stack unable to make progress, which is worse than the thing
|
|
186
|
+
* it is protecting against — the resource is absent either way, which is
|
|
187
|
+
* what was asked for.
|
|
188
|
+
*/
|
|
189
|
+
async delete(id, props) {
|
|
190
|
+
try {
|
|
191
|
+
await call(props, 'application.remove', { applicationId: id });
|
|
192
|
+
} catch (error) {
|
|
193
|
+
if (!isNotFound(error)) throw error;
|
|
194
|
+
}
|
|
195
|
+
},
|
|
196
|
+
};
|
|
197
|
+
|
|
198
|
+
/**
|
|
199
|
+
* One call to Dokploy.
|
|
200
|
+
*
|
|
201
|
+
* Written out rather than reusing `DokployApi` because the provider's functions
|
|
202
|
+
* are serialised into state: a class imported from another module would have to
|
|
203
|
+
* serialise too, and the failure when it cannot is obscure. `fetch` is a global.
|
|
204
|
+
*/
|
|
205
|
+
async function call<T>(
|
|
206
|
+
auth: { endpoint: string; apiToken: string },
|
|
207
|
+
path: string,
|
|
208
|
+
body?: Record<string, unknown>,
|
|
209
|
+
): Promise<T> {
|
|
210
|
+
const response = await fetch(`${auth.endpoint}/api/trpc/${path}`, {
|
|
211
|
+
method: body ? 'POST' : 'GET',
|
|
212
|
+
headers: {
|
|
213
|
+
'x-api-key': auth.apiToken,
|
|
214
|
+
'content-type': 'application/json',
|
|
215
|
+
},
|
|
216
|
+
...(body ? { body: JSON.stringify(body) } : {}),
|
|
217
|
+
});
|
|
218
|
+
|
|
219
|
+
if (!response.ok) {
|
|
220
|
+
const detail = await response.text().catch(() => '');
|
|
221
|
+
throw new Error(
|
|
222
|
+
`Dokploy ${path} failed: ${response.status} ${response.statusText}${
|
|
223
|
+
detail ? ` — ${detail}` : ''
|
|
224
|
+
}`,
|
|
225
|
+
);
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
return (await response.json()) as T;
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
/** Whether an error means the thing is already absent. */
|
|
232
|
+
function isNotFound(error: unknown): boolean {
|
|
233
|
+
return error instanceof Error && /\b404\b/.test(error.message);
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
export interface ApplicationArgs {
|
|
237
|
+
endpoint: Input<string>;
|
|
238
|
+
apiToken: Input<string>;
|
|
239
|
+
name: Input<string>;
|
|
240
|
+
projectId: Input<string>;
|
|
241
|
+
environmentId: Input<string>;
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
export class Application extends dynamic.Resource {
|
|
245
|
+
declare readonly applicationId: Output<string>;
|
|
246
|
+
declare readonly appName: Output<string>;
|
|
247
|
+
|
|
248
|
+
constructor(name: string, args: ApplicationArgs, opts?: object) {
|
|
249
|
+
super(
|
|
250
|
+
provider,
|
|
251
|
+
name,
|
|
252
|
+
// The outputs have to be declared as undefined inputs or Pulumi will
|
|
253
|
+
// not populate them — a quiet rule, and the usual first thing to get
|
|
254
|
+
// wrong with a dynamic provider.
|
|
255
|
+
{ ...args, applicationId: undefined, appName: undefined },
|
|
256
|
+
opts,
|
|
257
|
+
);
|
|
258
|
+
}
|
|
259
|
+
}
|