@geekmidas/cloud 10.0.0-alpha.11 → 10.0.0-alpha.111
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/README.md +14 -6
- package/dist/index.cjs +3 -3
- package/dist/index.d.cts +1 -1
- package/dist/index.d.mts +1 -1
- package/dist/index.mjs +2 -3
- package/dist/utils/index.cjs +106 -5
- package/dist/utils/index.cjs.map +1 -0
- package/dist/utils/index.d.cts +62 -2
- package/dist/utils/index.d.cts.map +1 -0
- package/dist/utils/index.d.mts +62 -2
- package/dist/utils/index.d.mts.map +1 -0
- package/dist/utils/index.mjs +78 -2
- package/dist/utils/index.mjs.map +1 -0
- package/package.json +9 -8
- package/src/dokploy/Application.ts +52 -5
- package/src/dokploy/__tests__/Application.provider.spec.ts +206 -0
- package/src/sst/__tests__/api.spec.ts +185 -0
- package/src/sst/__tests__/encryption.spec.ts +90 -0
- package/src/sst/__tests__/fromManifest.integration.spec.ts +452 -0
- package/src/sst/__tests__/fromManifest.secret.spec.ts +79 -0
- package/src/sst/__tests__/fromManifest.spec.ts +306 -5
- package/src/sst/__tests__/function.spec.ts +121 -0
- package/src/sst/__tests__/links.spec.ts +209 -0
- package/src/sst/__tests__/surfaces.spec.ts +17 -0
- package/src/sst/__type-tests__/overrides.type-test.ts +152 -0
- package/src/sst/aws/Api.ts +16 -44
- package/src/sst/aws/Cache.ts +4 -4
- package/src/sst/aws/Credential.ts +42 -9
- package/src/sst/aws/Cron.ts +5 -45
- package/src/sst/aws/Database.ts +15 -1
- package/src/sst/aws/DatabaseBootstrap.ts +3 -0
- package/src/sst/aws/Encryption.ts +91 -0
- package/src/sst/aws/ExternalApi.ts +58 -0
- package/src/sst/aws/Function.ts +9 -38
- package/src/sst/aws/Queue.ts +34 -1
- package/src/sst/aws/RestApiSurface.ts +36 -14
- package/src/sst/aws/Secret.ts +5 -3
- package/src/sst/aws/bootstrap/handler.ts +10 -1
- package/src/sst/fromManifest.ts +299 -46
- package/src/sst/index.ts +6 -1
- package/src/sst/overrides.ts +133 -0
- package/dist/index-B5CZ1xVf.d.cts +0 -64
- package/dist/index-B5CZ1xVf.d.cts.map +0 -1
- package/dist/index-DhHRjduZ.d.mts +0 -64
- package/dist/index-DhHRjduZ.d.mts.map +0 -1
- package/dist/utils-B1a2UuEO.cjs +0 -129
- package/dist/utils-B1a2UuEO.cjs.map +0 -1
- package/dist/utils-DMOXJ27j.mjs +0 -83
- package/dist/utils-DMOXJ27j.mjs.map +0 -1
- package/src/sst/__type-tests__/manifest.type-test.ts +0 -77
package/src/sst/aws/Function.ts
CHANGED
|
@@ -1,9 +1,4 @@
|
|
|
1
1
|
import type { EnvValidator, ValidationResult } from '@geekmidas/envkit/sst';
|
|
2
|
-
import {
|
|
3
|
-
type FunctionInfo,
|
|
4
|
-
flattenManifestField,
|
|
5
|
-
type ManifestField,
|
|
6
|
-
} from '@geekmidas/manifest';
|
|
7
2
|
import { type GkmLinkable, ResourceType } from '../Linkable';
|
|
8
3
|
import { LinkedEnvironment } from '../LinkedEnvironment';
|
|
9
4
|
import type { StackType } from '../Stack';
|
|
@@ -66,9 +61,10 @@ export class Function<
|
|
|
66
61
|
super(id, {
|
|
67
62
|
...fnArgs,
|
|
68
63
|
environment: mergedEnvironment,
|
|
69
|
-
//
|
|
70
|
-
//
|
|
71
|
-
link:
|
|
64
|
+
// Resolved from `links` when `envVars` names what it needs; otherwise
|
|
65
|
+
// the `link` it was given — the edges a manifest declared.
|
|
66
|
+
link:
|
|
67
|
+
envVars.length > 0 ? linked.resolveLink(envVars) : (fnArgs.link ?? []),
|
|
72
68
|
runtime: runtime ?? 'nodejs24.x',
|
|
73
69
|
logging: logging ?? { format: 'json' },
|
|
74
70
|
});
|
|
@@ -78,40 +74,15 @@ export class Function<
|
|
|
78
74
|
this.envVars = envVars;
|
|
79
75
|
}
|
|
80
76
|
|
|
77
|
+
/** Its address, for whatever declared an edge to it. */
|
|
78
|
+
provides(): Record<string, $util.Input<string>> {
|
|
79
|
+
return { url: this.url };
|
|
80
|
+
}
|
|
81
|
+
|
|
81
82
|
/** Re-runs validation and returns the result (does not throw). */
|
|
82
83
|
validate(): ValidationResult {
|
|
83
84
|
return this.validator.validate(this.envVars);
|
|
84
85
|
}
|
|
85
|
-
|
|
86
|
-
/**
|
|
87
|
-
* Build one `Function` per entry in a `gkm build` manifest's `functions`
|
|
88
|
-
* field (flat or partitioned). Shared `props` (e.g. `links`) apply to every
|
|
89
|
-
* function.
|
|
90
|
-
*
|
|
91
|
-
* ```ts
|
|
92
|
-
* Function.fromManifest(stack, manifest.functions, { links: [db] });
|
|
93
|
-
* ```
|
|
94
|
-
*/
|
|
95
|
-
static fromManifest<
|
|
96
|
-
TStage extends string = string,
|
|
97
|
-
TDomain extends string = string,
|
|
98
|
-
>(
|
|
99
|
-
stack: StackType<TStage, TDomain>,
|
|
100
|
-
functions: ManifestField<FunctionInfo>,
|
|
101
|
-
props: Omit<FunctionProps, 'handler'> = {},
|
|
102
|
-
): Function<TStage, TDomain>[] {
|
|
103
|
-
return flattenManifestField(functions).map(
|
|
104
|
-
(fn) =>
|
|
105
|
-
new Function(stack, fn.name, {
|
|
106
|
-
...props,
|
|
107
|
-
name: stack.logicalPrefixedName(fn.name),
|
|
108
|
-
handler: fn.handler,
|
|
109
|
-
envVars: fn.environment,
|
|
110
|
-
timeout: fn.timeout ? `${fn.timeout} seconds` : undefined,
|
|
111
|
-
memory: fn.memorySize ? `${fn.memorySize} MB` : undefined,
|
|
112
|
-
}),
|
|
113
|
-
);
|
|
114
|
-
}
|
|
115
86
|
}
|
|
116
87
|
|
|
117
88
|
export interface FunctionProps extends sst.aws.FunctionArgs {
|
package/src/sst/aws/Queue.ts
CHANGED
|
@@ -11,7 +11,8 @@ import type { StackType } from '../Stack';
|
|
|
11
11
|
* work queue. Link it to a producer and the runtime resolves `<NAME>_URL`,
|
|
12
12
|
* `<NAME>_ARN`, and a `<NAME>_PUBLISHER_CONNECTION_STRING` (`sqs://?queueUrl=…`)
|
|
13
13
|
* that `@geekmidas/events`'s `Publisher.fromConnectionString` consumes. Its
|
|
14
|
-
*
|
|
14
|
+
* one consumer — the handler the queue was declared with — is subscribed by
|
|
15
|
+
* {@link Queue.consume}.
|
|
15
16
|
*
|
|
16
17
|
* SST's native `Queue` link exposes only `url`, so `getSSTLink` is overridden to
|
|
17
18
|
* also expose `arn` (what the resolver needs). `QueueProps` extends
|
|
@@ -73,6 +74,26 @@ export class Queue<
|
|
|
73
74
|
};
|
|
74
75
|
}
|
|
75
76
|
|
|
77
|
+
/**
|
|
78
|
+
* Subscribe the queue's one consumer: a Lambda running `handler`, linked to
|
|
79
|
+
* what the consumer depends on and to this queue itself.
|
|
80
|
+
*
|
|
81
|
+
* A queue has exactly one consumer, so this is called once per queue — by
|
|
82
|
+
* `fromManifest`, from the handler the build wrote for it.
|
|
83
|
+
*/
|
|
84
|
+
consume(consumer: QueueConsumer) {
|
|
85
|
+
return this.subscribe(
|
|
86
|
+
{
|
|
87
|
+
handler: consumer.handler,
|
|
88
|
+
link: [this, ...(consumer.link ?? [])],
|
|
89
|
+
runtime: 'nodejs24.x',
|
|
90
|
+
...(consumer.vpc ? { vpc: consumer.vpc } : {}),
|
|
91
|
+
...(consumer.timeout ? { timeout: consumer.timeout } : {}),
|
|
92
|
+
},
|
|
93
|
+
consumer.batchSize ? { batch: { size: consumer.batchSize } } : {},
|
|
94
|
+
);
|
|
95
|
+
}
|
|
96
|
+
|
|
76
97
|
override getSSTLink() {
|
|
77
98
|
const link = super.getSSTLink();
|
|
78
99
|
return {
|
|
@@ -82,6 +103,18 @@ export class Queue<
|
|
|
82
103
|
}
|
|
83
104
|
}
|
|
84
105
|
|
|
106
|
+
/** The queue's one consumer, as {@link Queue.consume} subscribes it. */
|
|
107
|
+
export interface QueueConsumer {
|
|
108
|
+
/** The built handler — `apps/api/.gkm/aws/queues/emails.handler`. */
|
|
109
|
+
handler: string;
|
|
110
|
+
/** What the consumer depends on; the queue itself is always linked. */
|
|
111
|
+
link?: unknown[];
|
|
112
|
+
/** The database's network, when the consumer reaches one. */
|
|
113
|
+
vpc?: sst.aws.Vpc;
|
|
114
|
+
timeout?: `${number} seconds` | `${number} minutes`;
|
|
115
|
+
batchSize?: number;
|
|
116
|
+
}
|
|
117
|
+
|
|
85
118
|
export interface QueueProps extends sst.aws.QueueArgs {
|
|
86
119
|
/**
|
|
87
120
|
* The physical queue name, where the auto-generated one will not do.
|
|
@@ -4,20 +4,10 @@ import type { StackType } from '../Stack';
|
|
|
4
4
|
/**
|
|
5
5
|
* `RestApiSurface` — an HTTP API, and the infra half of the `rest-api` kind.
|
|
6
6
|
*
|
|
7
|
-
*
|
|
8
|
-
*
|
|
9
|
-
*
|
|
10
|
-
*
|
|
11
|
-
*
|
|
12
|
-
* So what this provisions is the surface and nothing on it. An API Gateway with
|
|
13
|
-
* no routes 404s everything, which is the honest state of things — and it is
|
|
14
|
-
* still worth provisioning, because the *address* is what everything downstream
|
|
15
|
-
* needs: a site inlines it as `VITE_API_URL`, an auth server puts it on its
|
|
16
|
-
* trusted-origin list, and the cookie domain derives from it. Those are blocked
|
|
17
|
-
* on the API existing, not on it answering.
|
|
18
|
-
*
|
|
19
|
-
* The two collapse into one component when the endpoint merge lands and the
|
|
20
|
-
* surface node carries its routes.
|
|
7
|
+
* Provisioned before its routes, because its *address* is what everything
|
|
8
|
+
* downstream needs: a site inlines it as `VITE_API_URL`, an auth server puts it
|
|
9
|
+
* on its trusted-origin list, and the cookie domain derives from it. The routes
|
|
10
|
+
* are mounted once everything they link to exists — see {@link mount}.
|
|
21
11
|
*/
|
|
22
12
|
|
|
23
13
|
export interface RestApiSurfaceProps extends sst.aws.ApiGatewayV2Args {
|
|
@@ -82,6 +72,25 @@ export class RestApiSurface<
|
|
|
82
72
|
};
|
|
83
73
|
}
|
|
84
74
|
|
|
75
|
+
/**
|
|
76
|
+
* Mount one endpoint: a Lambda running the handler the build wrote for it,
|
|
77
|
+
* linked to exactly what that endpoint depends on.
|
|
78
|
+
*/
|
|
79
|
+
mount(endpoint: SurfaceRoute) {
|
|
80
|
+
return this.route(
|
|
81
|
+
`${endpoint.method} ${endpoint.path}`,
|
|
82
|
+
{
|
|
83
|
+
handler: endpoint.handler,
|
|
84
|
+
link: endpoint.link ?? [],
|
|
85
|
+
runtime: 'nodejs24.x',
|
|
86
|
+
...(endpoint.vpc ? { vpc: endpoint.vpc } : {}),
|
|
87
|
+
},
|
|
88
|
+
// `iam` is the one authorizer the gateway enforces itself; every other
|
|
89
|
+
// is the endpoint's own, checked in the handler.
|
|
90
|
+
endpoint.authorizer === 'iam' ? { auth: { iam: true } } : {},
|
|
91
|
+
);
|
|
92
|
+
}
|
|
93
|
+
|
|
85
94
|
override getSSTLink() {
|
|
86
95
|
const link = super.getSSTLink();
|
|
87
96
|
return {
|
|
@@ -90,3 +99,16 @@ export class RestApiSurface<
|
|
|
90
99
|
};
|
|
91
100
|
}
|
|
92
101
|
}
|
|
102
|
+
|
|
103
|
+
/** One endpoint, as {@link RestApiSurface.mount} mounts it. */
|
|
104
|
+
export interface SurfaceRoute {
|
|
105
|
+
method: string;
|
|
106
|
+
path: string;
|
|
107
|
+
/** The built handler — `apps/api/.gkm/aws/routes/getUser.handler`. */
|
|
108
|
+
handler: string;
|
|
109
|
+
/** What the endpoint depends on, and nothing else. */
|
|
110
|
+
link?: unknown[];
|
|
111
|
+
/** The database's network, when the endpoint reaches one. */
|
|
112
|
+
vpc?: sst.aws.Vpc;
|
|
113
|
+
authorizer?: string;
|
|
114
|
+
}
|
package/src/sst/aws/Secret.ts
CHANGED
|
@@ -15,8 +15,10 @@ import type { StackType } from '../Stack';
|
|
|
15
15
|
* signing key, the thing that stores it, and the thing that reads it are three
|
|
16
16
|
* different systems deployed, and one derived string locally.
|
|
17
17
|
*
|
|
18
|
-
* Usable on its own. `Stack.fromManifest` translates a manifest into these,
|
|
19
|
-
*
|
|
18
|
+
* Usable on its own. `Stack.fromManifest` translates a manifest into these, and
|
|
19
|
+
* hands each a generated placeholder, so a manifest's secret is generated on
|
|
20
|
+
* its first deploy rather than set by hand; the component on its own takes
|
|
21
|
+
* whatever placeholder it is given, so it works in a hand-written
|
|
20
22
|
* `sst.config.ts` with no manifest anywhere.
|
|
21
23
|
*/
|
|
22
24
|
export class Secret<
|
|
@@ -72,5 +74,5 @@ export interface SecretProps {
|
|
|
72
74
|
* letting the deploy fail — is the correct handling for a real secret. It
|
|
73
75
|
* exists for the values that are secrets by habit rather than by need.
|
|
74
76
|
*/
|
|
75
|
-
placeholder?: string
|
|
77
|
+
placeholder?: $util.Input<string>;
|
|
76
78
|
}
|
|
@@ -28,6 +28,11 @@ export interface BootstrapTenant {
|
|
|
28
28
|
runtime: string;
|
|
29
29
|
owner: string;
|
|
30
30
|
reader?: string;
|
|
31
|
+
/**
|
|
32
|
+
* The database's own roles rather than a tenant's: its owner may create in
|
|
33
|
+
* the database, for trusted extensions.
|
|
34
|
+
*/
|
|
35
|
+
ownsDatabase?: boolean;
|
|
31
36
|
passwords: { runtime: string; owner: string; reader?: string };
|
|
32
37
|
}
|
|
33
38
|
|
|
@@ -75,7 +80,11 @@ export async function handler(event: BootstrapEvent): Promise<BootstrapResult> {
|
|
|
75
80
|
|
|
76
81
|
try {
|
|
77
82
|
for (const tenant of event.tenants) {
|
|
78
|
-
|
|
83
|
+
const spec = {
|
|
84
|
+
...tenant,
|
|
85
|
+
...(tenant.ownsDatabase ? { database: event.master.database } : {}),
|
|
86
|
+
};
|
|
87
|
+
for (const statement of roleStatements(spec)) {
|
|
79
88
|
if (statement.exists) {
|
|
80
89
|
const { rows } = await client.query(
|
|
81
90
|
statement.exists.sql,
|