@geekmidas/cloud 10.0.0-alpha.2 → 10.0.0-alpha.21
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 +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 +14 -14
- package/src/dokploy/Application.ts +52 -5
- package/src/dokploy/__tests__/Application.provider.spec.ts +206 -0
- package/src/sst/__tests__/api.spec.ts +231 -0
- package/src/sst/__tests__/fromManifest.integration.spec.ts +368 -0
- package/src/sst/__tests__/function.spec.ts +192 -0
- package/src/sst/__tests__/links.spec.ts +209 -0
- package/src/sst/aws/Api.ts +16 -1
- package/src/sst/aws/Cache.ts +4 -4
- package/src/sst/aws/Database.ts +15 -1
- package/src/sst/fromManifest.ts +16 -5
- 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
|
@@ -0,0 +1,209 @@
|
|
|
1
|
+
import { describe, expect, it } from 'vitest';
|
|
2
|
+
import { Cache, CacheNeedsProvider, CacheNeedsVpc } from '../aws/Cache';
|
|
3
|
+
import { Database } from '../aws/Database';
|
|
4
|
+
import { DatabaseReader, DatabaseSchema } from '../aws/DerivedDatabase';
|
|
5
|
+
import { Email } from '../aws/Email';
|
|
6
|
+
import { FileServer } from '../aws/FileServer';
|
|
7
|
+
import { Queue } from '../aws/Queue';
|
|
8
|
+
import { RestApiSurface } from '../aws/RestApiSurface';
|
|
9
|
+
import { Secret } from '../aws/Secret';
|
|
10
|
+
import { StaticSite } from '../aws/StaticSite';
|
|
11
|
+
import { Storage } from '../aws/Storage';
|
|
12
|
+
import { Topic } from '../aws/Topic';
|
|
13
|
+
import { ResourceType } from '../Linkable';
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* What a linked function receives from each component, and the type that
|
|
17
|
+
* decides which variables a link provides. `getSSTLink()` is the payload SST
|
|
18
|
+
* injects into every handler linked to the resource; `_type` is what
|
|
19
|
+
* `LinkedEnvironment` keys the variable names off.
|
|
20
|
+
*/
|
|
21
|
+
|
|
22
|
+
const stack = {} as never;
|
|
23
|
+
const vpc = { subnets: ['subnet-1'], securityGroups: ['sg-1'] } as never;
|
|
24
|
+
|
|
25
|
+
/** Resolves `$util.output(promise)`, which the stub leaves as the promise. */
|
|
26
|
+
const settle = async (value: unknown) =>
|
|
27
|
+
(value as { apply: (fn: (v: unknown) => unknown) => unknown }).apply(
|
|
28
|
+
(v) => v,
|
|
29
|
+
);
|
|
30
|
+
|
|
31
|
+
describe('link payloads', () => {
|
|
32
|
+
it('a queue adds its ARN and connection string to SST’s own link', () => {
|
|
33
|
+
const queue = new Queue(stack, 'Emails');
|
|
34
|
+
|
|
35
|
+
expect(queue._type).toBe(ResourceType.Queue);
|
|
36
|
+
// The connection string itself is parsed back in provides.spec; here, the
|
|
37
|
+
// link carries exactly what `provides()` resolved.
|
|
38
|
+
expect(queue.getSSTLink().properties).toEqual({
|
|
39
|
+
name: 'Emails',
|
|
40
|
+
arn: queue.arn,
|
|
41
|
+
...queue.provides(),
|
|
42
|
+
});
|
|
43
|
+
});
|
|
44
|
+
|
|
45
|
+
it('a topic carries its publisher connection string', () => {
|
|
46
|
+
const topic = new Topic(stack, 'Users');
|
|
47
|
+
|
|
48
|
+
expect(topic._type).toBe(ResourceType.SnsTopic);
|
|
49
|
+
expect(topic.getSSTLink().properties).toEqual({
|
|
50
|
+
name: 'Users',
|
|
51
|
+
...topic.provides(),
|
|
52
|
+
});
|
|
53
|
+
});
|
|
54
|
+
|
|
55
|
+
it('a secret carries its value', () => {
|
|
56
|
+
const secret = new Secret(stack, 'AuthSecret');
|
|
57
|
+
|
|
58
|
+
expect(secret._type).toBe(ResourceType.SSTSecret);
|
|
59
|
+
expect(secret.getSSTLink().properties).toMatchObject(secret.provides());
|
|
60
|
+
});
|
|
61
|
+
|
|
62
|
+
it('a mailer carries its URL and sending identity, and nothing else', () => {
|
|
63
|
+
const email = new Email(stack, 'Mail', {
|
|
64
|
+
backend: 'smtp',
|
|
65
|
+
url: 'smtp://relay.test:587',
|
|
66
|
+
from: 'hello@shop.test',
|
|
67
|
+
} as never);
|
|
68
|
+
|
|
69
|
+
expect(email._type).toBe(ResourceType.Email);
|
|
70
|
+
expect(email.getSSTLink()).toEqual({
|
|
71
|
+
properties: { url: 'smtp://relay.test:587', from: 'hello@shop.test' },
|
|
72
|
+
});
|
|
73
|
+
});
|
|
74
|
+
|
|
75
|
+
it('a file server routes everything to its bucket, and links its URL', () => {
|
|
76
|
+
const origin = new Storage(stack, 'Uploads');
|
|
77
|
+
const server = new FileServer(stack, 'Files', { origin } as never);
|
|
78
|
+
|
|
79
|
+
expect(origin._type).toBe(ResourceType.ObjectStorage);
|
|
80
|
+
expect(origin._id).toBe('Uploads');
|
|
81
|
+
expect(server._type).toBe(ResourceType.FileServer);
|
|
82
|
+
expect((server as unknown as { routed: unknown[] }).routed).toEqual([
|
|
83
|
+
{ pattern: '/*', bucket: origin },
|
|
84
|
+
]);
|
|
85
|
+
expect(server.getSSTLink().properties).toMatchObject({
|
|
86
|
+
url: server.url,
|
|
87
|
+
});
|
|
88
|
+
});
|
|
89
|
+
|
|
90
|
+
it('a site is built the way its variant builds, and links its URL', () => {
|
|
91
|
+
const vite = new StaticSite(stack, 'Web');
|
|
92
|
+
const next = new StaticSite(stack, 'Admin', {
|
|
93
|
+
variant: 'next',
|
|
94
|
+
build: { command: 'pnpm build:custom', output: 'out' },
|
|
95
|
+
} as never);
|
|
96
|
+
const args = (site: unknown) => (site as { args: { build: unknown } }).args;
|
|
97
|
+
|
|
98
|
+
expect(vite._type).toBe(ResourceType.StaticSite);
|
|
99
|
+
expect(args(vite).build).toEqual(expect.objectContaining({}));
|
|
100
|
+
// A build the caller supplied wins over the variant's.
|
|
101
|
+
expect(args(next).build).toEqual({
|
|
102
|
+
command: 'pnpm build:custom',
|
|
103
|
+
output: 'out',
|
|
104
|
+
});
|
|
105
|
+
expect(vite.getSSTLink().properties).toMatchObject({ url: vite.url });
|
|
106
|
+
});
|
|
107
|
+
|
|
108
|
+
it('a surface links its address and, once resolved, who may call it', async () => {
|
|
109
|
+
const bare = new RestApiSurface(stack, 'Api');
|
|
110
|
+
const called = new RestApiSurface(stack, 'Api', {
|
|
111
|
+
callers: Promise.resolve({
|
|
112
|
+
trustedOrigins: 'https://web.shop.test',
|
|
113
|
+
cookieDomain: 'shop.test',
|
|
114
|
+
}),
|
|
115
|
+
});
|
|
116
|
+
|
|
117
|
+
expect(bare._type).toBe(ResourceType.ApiGatewayV2);
|
|
118
|
+
expect(await settle(bare.provides().trustedOrigins)).toBe('');
|
|
119
|
+
expect(await settle(bare.provides().cookieDomain)).toBe('');
|
|
120
|
+
|
|
121
|
+
const link = called.getSSTLink().properties as Record<string, unknown>;
|
|
122
|
+
expect(link.url).toBe(called.url);
|
|
123
|
+
expect(await settle(link.trustedOrigins)).toBe('https://web.shop.test');
|
|
124
|
+
expect(await settle(link.cookieDomain)).toBe('shop.test');
|
|
125
|
+
});
|
|
126
|
+
|
|
127
|
+
it('a database and the nodes derived from it each link only their own URL', () => {
|
|
128
|
+
const cluster = new Database(stack, 'Orders', { vpc, schema: 'app' });
|
|
129
|
+
const reader = new DatabaseReader('OrdersReader', cluster);
|
|
130
|
+
const tenant = new DatabaseSchema('AuthDb', cluster, 'authdb');
|
|
131
|
+
|
|
132
|
+
expect(cluster._type).toBe(ResourceType.SSTPostgres);
|
|
133
|
+
expect(reader._type).toBe(ResourceType.SSTPostgres);
|
|
134
|
+
expect(tenant._type).toBe(ResourceType.SSTPostgres);
|
|
135
|
+
expect(cluster.getSSTLink().properties).toMatchObject({
|
|
136
|
+
url: cluster.provides().url,
|
|
137
|
+
});
|
|
138
|
+
// Least privilege: the reader's link is its URL and not the writer's.
|
|
139
|
+
expect(reader.getSSTLink()).toEqual({
|
|
140
|
+
properties: { url: reader.provides().url },
|
|
141
|
+
});
|
|
142
|
+
expect(tenant.getSSTLink()).toEqual({
|
|
143
|
+
properties: { url: tenant.provides().url },
|
|
144
|
+
});
|
|
145
|
+
});
|
|
146
|
+
|
|
147
|
+
it('a cache given its URL links it as-is', () => {
|
|
148
|
+
const cache = new Cache(stack, 'Sessions', {
|
|
149
|
+
backend: 'db',
|
|
150
|
+
url: 'postgres://db.test/app',
|
|
151
|
+
});
|
|
152
|
+
|
|
153
|
+
expect(cache._type).toBe(ResourceType.Cache);
|
|
154
|
+
expect(cache.getSSTLink()).toEqual({
|
|
155
|
+
properties: { url: 'postgres://db.test/app' },
|
|
156
|
+
});
|
|
157
|
+
});
|
|
158
|
+
});
|
|
159
|
+
|
|
160
|
+
describe('Cache on Upstash', () => {
|
|
161
|
+
/** `sst add upstash` installs this global; here, a recording stand-in. */
|
|
162
|
+
const created: { name: string; args: Record<string, unknown> }[] = [];
|
|
163
|
+
class RedisDatabase {
|
|
164
|
+
readonly endpoint = 'eu1-cache.upstash.io';
|
|
165
|
+
readonly restToken = 'tok/en+1';
|
|
166
|
+
constructor(name: string, args: Record<string, unknown>) {
|
|
167
|
+
created.push({ name, args });
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
it('creates a TLS database and puts its token in the URL', () => {
|
|
172
|
+
(globalThis as Record<string, unknown>).upstash = { RedisDatabase };
|
|
173
|
+
try {
|
|
174
|
+
const defaulted = new Cache(stack, 'Sessions', { backend: 'upstash' });
|
|
175
|
+
new Cache(stack, 'Rates', { backend: 'upstash', region: 'us-east-1' });
|
|
176
|
+
|
|
177
|
+
expect(created).toEqual([
|
|
178
|
+
{
|
|
179
|
+
name: 'SessionsCache',
|
|
180
|
+
args: { databaseName: 'Sessions', region: 'eu-west-1', tls: true },
|
|
181
|
+
},
|
|
182
|
+
{
|
|
183
|
+
name: 'RatesCache',
|
|
184
|
+
args: { databaseName: 'Rates', region: 'us-east-1', tls: true },
|
|
185
|
+
},
|
|
186
|
+
]);
|
|
187
|
+
// The address and the credential that opens it are one fact.
|
|
188
|
+
expect(defaulted.provides().url).toBe(
|
|
189
|
+
`https://:${encodeURIComponent('tok/en+1')}@eu1-cache.upstash.io`,
|
|
190
|
+
);
|
|
191
|
+
} finally {
|
|
192
|
+
delete (globalThis as Record<string, unknown>).upstash;
|
|
193
|
+
}
|
|
194
|
+
});
|
|
195
|
+
});
|
|
196
|
+
|
|
197
|
+
describe('Cache provisioning refusals', () => {
|
|
198
|
+
it('asks for the Upstash provider when it is not installed', () => {
|
|
199
|
+
expect(() => new Cache(stack, 'Sessions', { backend: 'upstash' })).toThrow(
|
|
200
|
+
CacheNeedsProvider,
|
|
201
|
+
);
|
|
202
|
+
});
|
|
203
|
+
|
|
204
|
+
it('asks for a VPC before creating an ElastiCache', () => {
|
|
205
|
+
expect(
|
|
206
|
+
() => new Cache(stack, 'Sessions', { backend: 'elasticache' }),
|
|
207
|
+
).toThrow(CacheNeedsVpc);
|
|
208
|
+
});
|
|
209
|
+
});
|
package/src/sst/aws/Api.ts
CHANGED
|
@@ -153,7 +153,7 @@ export class Api<
|
|
|
153
153
|
// Fail the whole synth if any route is misconfigured, with one actionable
|
|
154
154
|
// message per offending route.
|
|
155
155
|
if (failures.length) {
|
|
156
|
-
throw new
|
|
156
|
+
throw new RoutesMissingEnvironment(id, failures);
|
|
157
157
|
}
|
|
158
158
|
}
|
|
159
159
|
|
|
@@ -307,3 +307,18 @@ export interface ApiProps<TAuthorizers extends Record<string, unknown> = {}>
|
|
|
307
307
|
* may override it. */
|
|
308
308
|
runtime?: sst.aws.FunctionArgs['runtime'];
|
|
309
309
|
}
|
|
310
|
+
|
|
311
|
+
/**
|
|
312
|
+
* Routes that read variables nothing links or whitelists. Collected across
|
|
313
|
+
* every route so one synth reports all of them, each with its own suggestions,
|
|
314
|
+
* rather than stopping at the first.
|
|
315
|
+
*/
|
|
316
|
+
export class RoutesMissingEnvironment extends Error {
|
|
317
|
+
constructor(
|
|
318
|
+
readonly api: string,
|
|
319
|
+
readonly failures: readonly EnvValidationError[],
|
|
320
|
+
) {
|
|
321
|
+
super(failures.map((f) => f.message).join('\n\n'));
|
|
322
|
+
this.name = 'RoutesMissingEnvironment';
|
|
323
|
+
}
|
|
324
|
+
}
|
package/src/sst/aws/Cache.ts
CHANGED
|
@@ -206,7 +206,7 @@ export function withCacheTable(url: string, table: string): string {
|
|
|
206
206
|
}
|
|
207
207
|
|
|
208
208
|
/**
|
|
209
|
-
* `
|
|
209
|
+
* A `'db'` cache in an app that declares more than one database.
|
|
210
210
|
*
|
|
211
211
|
* Picking one would put the cache somewhere nobody chose, and the symptom —
|
|
212
212
|
* entries that are never found — appears long after the deploy reported
|
|
@@ -222,7 +222,7 @@ export class CacheIsAmbiguous extends Error {
|
|
|
222
222
|
`'${id}' is a cache backed by the database, and this app declares ` +
|
|
223
223
|
`${databases.length}: ${databases.join(', ')}. Declare the cache from ` +
|
|
224
224
|
`its database — e.g. ${databases[0]}.cache('${id}') — rather than ` +
|
|
225
|
-
`
|
|
225
|
+
`as a bare new Cache().`,
|
|
226
226
|
);
|
|
227
227
|
this.name = 'CacheIsAmbiguous';
|
|
228
228
|
}
|
|
@@ -232,8 +232,8 @@ export class CacheNeedsDatabase extends Error {
|
|
|
232
232
|
constructor(readonly id: string) {
|
|
233
233
|
super(
|
|
234
234
|
`'${id}' is a cache backed by the database, and this app declares no ` +
|
|
235
|
-
`database for it to live in. Declare one, or
|
|
236
|
-
`
|
|
235
|
+
`database for it to live in. Declare one, or declare the cache from ` +
|
|
236
|
+
`the database it belongs to.`,
|
|
237
237
|
);
|
|
238
238
|
this.name = 'CacheNeedsDatabase';
|
|
239
239
|
}
|
package/src/sst/aws/Database.ts
CHANGED
|
@@ -84,7 +84,21 @@ export class Database<
|
|
|
84
84
|
* produces a database that looks empty.
|
|
85
85
|
*/
|
|
86
86
|
provides(): Record<string, $util.Input<string>> {
|
|
87
|
-
return { url: this.urlFor({}) };
|
|
87
|
+
return { url: this.urlFor(this.role ? { as: this.role } : {}) };
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
/**
|
|
91
|
+
* The runtime role this database's own handlers connect as.
|
|
92
|
+
*
|
|
93
|
+
* Set by the adapter once the bootstrap has registered the role — the
|
|
94
|
+
* cluster exists before any role does, so it cannot be a constructor
|
|
95
|
+
* argument. Until it is set (and under `roles: false`, where it never is),
|
|
96
|
+
* the URL is the master's.
|
|
97
|
+
*/
|
|
98
|
+
private role: { user: string; password: $util.Input<string> } | undefined;
|
|
99
|
+
|
|
100
|
+
connectAs(role: { user: string; password: $util.Input<string> }): void {
|
|
101
|
+
this.role = role;
|
|
88
102
|
}
|
|
89
103
|
|
|
90
104
|
/**
|
package/src/sst/fromManifest.ts
CHANGED
|
@@ -39,7 +39,7 @@ import {
|
|
|
39
39
|
withCacheTable,
|
|
40
40
|
} from './aws/Cache';
|
|
41
41
|
import { Credential } from './aws/Credential';
|
|
42
|
-
import { Database, DatabaseNeedsVpc } from './aws/Database';
|
|
42
|
+
import { Database, DatabaseNeedsVpc, type DatabaseProps } from './aws/Database';
|
|
43
43
|
import { DatabaseBootstrap } from './aws/DatabaseBootstrap';
|
|
44
44
|
import { DatabaseReader, DatabaseSchema } from './aws/DerivedDatabase';
|
|
45
45
|
import { Email, EmailNeedsSender } from './aws/Email';
|
|
@@ -98,8 +98,8 @@ export interface ProvisionContext {
|
|
|
98
98
|
/**
|
|
99
99
|
* Where a declared cache lives, and who delivers mail.
|
|
100
100
|
*
|
|
101
|
-
* Deployment choices rather than declarations, for the same reason
|
|
102
|
-
*
|
|
101
|
+
* Deployment choices rather than declarations, for the same reason the
|
|
102
|
+
* event broker is: the same application code caches into any of them and
|
|
103
103
|
* sends through any of them. They reach the provisioner here because it is
|
|
104
104
|
* the only place that knows both the choice and the manifest.
|
|
105
105
|
*/
|
|
@@ -220,7 +220,11 @@ const PROVISIONERS: Partial<Record<DeclarationKind, Provisioner>> = {
|
|
|
220
220
|
// rather than whatever Aurora defaults to that month. Local ran 18
|
|
221
221
|
// while this ran 17.7, and neither was written down anywhere.
|
|
222
222
|
version: String(d.version ?? DEFAULT_POSTGRES_VERSION),
|
|
223
|
-
|
|
223
|
+
// `DatabaseProps`, not `sst.aws.PostgresArgs`: the database needs the
|
|
224
|
+
// `Vpc` component itself (its bootstrap function runs in the same VPC
|
|
225
|
+
// and needs the security groups too), where RDS would accept bare
|
|
226
|
+
// subnet ids. TS 7 checks the spread; 6 let the wider type through.
|
|
227
|
+
...(props as unknown as Omit<DatabaseProps, 'schema'>),
|
|
224
228
|
});
|
|
225
229
|
|
|
226
230
|
// A database needs its own roles, not just its tenants'. Registering only
|
|
@@ -232,13 +236,20 @@ const PROVISIONERS: Partial<Record<DeclarationKind, Provisioner>> = {
|
|
|
232
236
|
const bootstrap = bootstrapFor(cluster, d.id, context);
|
|
233
237
|
const runtime = roleNameFor(d, context);
|
|
234
238
|
|
|
235
|
-
bootstrap?.add({
|
|
239
|
+
const credentials = bootstrap?.add({
|
|
236
240
|
id: d.id,
|
|
237
241
|
schema: d.schema,
|
|
238
242
|
runtime,
|
|
239
243
|
owner: ownerRole(runtime),
|
|
240
244
|
...(hasReader(d.id, context) ? { reader: readerRole(runtime) } : {}),
|
|
241
245
|
});
|
|
246
|
+
|
|
247
|
+
// Registering the role was half of it: its handlers have to connect as
|
|
248
|
+
// it too, or the DDL creates a role nothing uses and every handler
|
|
249
|
+
// linked to the database still holds the master.
|
|
250
|
+
if (credentials) {
|
|
251
|
+
cluster.connectAs({ user: runtime, password: credentials.runtime });
|
|
252
|
+
}
|
|
242
253
|
}
|
|
243
254
|
|
|
244
255
|
return cluster;
|
|
@@ -1,64 +0,0 @@
|
|
|
1
|
-
//#region src/utils/index.d.ts
|
|
2
|
-
declare function getLocalIpAddress(): string | null;
|
|
3
|
-
declare function environmentCase(name: string): string;
|
|
4
|
-
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
|
-
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
|
-
type ApiGatewayV2 = {
|
|
28
|
-
type: ResourceType.ApiGatewayV2 | ResourceType.SSTApiGatewayV2;
|
|
29
|
-
url: string;
|
|
30
|
-
};
|
|
31
|
-
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
|
-
type Function = {
|
|
40
|
-
name: string;
|
|
41
|
-
type: ResourceType.Function | ResourceType.SSTFunction;
|
|
42
|
-
};
|
|
43
|
-
type Bucket = {
|
|
44
|
-
name: string;
|
|
45
|
-
type: ResourceType.ObjectStorage | ResourceType.SSTObjectStorage;
|
|
46
|
-
};
|
|
47
|
-
type SnsTopic = {
|
|
48
|
-
arn: string;
|
|
49
|
-
type: ResourceType.SnsTopic;
|
|
50
|
-
};
|
|
51
|
-
type Vpc = {
|
|
52
|
-
bastion: string;
|
|
53
|
-
type: ResourceType.Vpc;
|
|
54
|
-
};
|
|
55
|
-
type Secret = {
|
|
56
|
-
type: ResourceType.Secret | ResourceType.SSTSecret;
|
|
57
|
-
value: string;
|
|
58
|
-
};
|
|
59
|
-
type Resource = ApiGatewayV2 | Postgres | Function | Bucket | SnsTopic | Vpc | Secret;
|
|
60
|
-
type ResourceProcessor<K extends Resource> = (name: string, value: K) => Record<string, string | number>;
|
|
61
|
-
//# sourceMappingURL=index.d.ts.map
|
|
62
|
-
//#endregion
|
|
63
|
-
export { ApiGatewayV2, Bucket, Function, Postgres, Resource, ResourceProcessor, ResourceType, Secret, SnsTopic, Vpc, buildResourceEnv, environmentCase, getLocalIpAddress };
|
|
64
|
-
//# sourceMappingURL=index-B5CZ1xVf.d.cts.map
|
|
@@ -1 +0,0 @@
|
|
|
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"}
|
|
@@ -1,64 +0,0 @@
|
|
|
1
|
-
//#region src/utils/index.d.ts
|
|
2
|
-
declare function getLocalIpAddress(): string | null;
|
|
3
|
-
declare function environmentCase(name: string): string;
|
|
4
|
-
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
|
-
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
|
-
type ApiGatewayV2 = {
|
|
28
|
-
type: ResourceType.ApiGatewayV2 | ResourceType.SSTApiGatewayV2;
|
|
29
|
-
url: string;
|
|
30
|
-
};
|
|
31
|
-
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
|
-
type Function = {
|
|
40
|
-
name: string;
|
|
41
|
-
type: ResourceType.Function | ResourceType.SSTFunction;
|
|
42
|
-
};
|
|
43
|
-
type Bucket = {
|
|
44
|
-
name: string;
|
|
45
|
-
type: ResourceType.ObjectStorage | ResourceType.SSTObjectStorage;
|
|
46
|
-
};
|
|
47
|
-
type SnsTopic = {
|
|
48
|
-
arn: string;
|
|
49
|
-
type: ResourceType.SnsTopic;
|
|
50
|
-
};
|
|
51
|
-
type Vpc = {
|
|
52
|
-
bastion: string;
|
|
53
|
-
type: ResourceType.Vpc;
|
|
54
|
-
};
|
|
55
|
-
type Secret = {
|
|
56
|
-
type: ResourceType.Secret | ResourceType.SSTSecret;
|
|
57
|
-
value: string;
|
|
58
|
-
};
|
|
59
|
-
type Resource = ApiGatewayV2 | Postgres | Function | Bucket | SnsTopic | Vpc | Secret;
|
|
60
|
-
type ResourceProcessor<K extends Resource> = (name: string, value: K) => Record<string, string | number>;
|
|
61
|
-
//# sourceMappingURL=index.d.ts.map
|
|
62
|
-
//#endregion
|
|
63
|
-
export { ApiGatewayV2, Bucket, Function, Postgres, Resource, ResourceProcessor, ResourceType, Secret, SnsTopic, Vpc, buildResourceEnv, environmentCase, getLocalIpAddress };
|
|
64
|
-
//# sourceMappingURL=index-DhHRjduZ.d.mts.map
|
|
@@ -1 +0,0 @@
|
|
|
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/utils-B1a2UuEO.cjs
DELETED
|
@@ -1,129 +0,0 @@
|
|
|
1
|
-
//#region rolldown:runtime
|
|
2
|
-
var __create = Object.create;
|
|
3
|
-
var __defProp = Object.defineProperty;
|
|
4
|
-
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
5
|
-
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
6
|
-
var __getProtoOf = Object.getPrototypeOf;
|
|
7
|
-
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
8
|
-
var __copyProps = (to, from, except, desc) => {
|
|
9
|
-
if (from && typeof from === "object" || typeof from === "function") for (var keys = __getOwnPropNames(from), i = 0, n = keys.length, key; i < n; i++) {
|
|
10
|
-
key = keys[i];
|
|
11
|
-
if (!__hasOwnProp.call(to, key) && key !== except) __defProp(to, key, {
|
|
12
|
-
get: ((k) => from[k]).bind(null, key),
|
|
13
|
-
enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable
|
|
14
|
-
});
|
|
15
|
-
}
|
|
16
|
-
return to;
|
|
17
|
-
};
|
|
18
|
-
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", {
|
|
19
|
-
value: mod,
|
|
20
|
-
enumerable: true
|
|
21
|
-
}) : target, mod));
|
|
22
|
-
|
|
23
|
-
//#endregion
|
|
24
|
-
const node_os = __toESM(require("node:os"));
|
|
25
|
-
const lodash_snakecase = __toESM(require("lodash.snakecase"));
|
|
26
|
-
|
|
27
|
-
//#region src/utils/index.ts
|
|
28
|
-
function getLocalIpAddress() {
|
|
29
|
-
const networkInterfaces = node_os.default.networkInterfaces();
|
|
30
|
-
for (const interfaceName in networkInterfaces) {
|
|
31
|
-
const addresses = networkInterfaces[interfaceName] || [];
|
|
32
|
-
for (const addressInfo of addresses) if (addressInfo.family === "IPv4" && !addressInfo.internal) return addressInfo.address;
|
|
33
|
-
}
|
|
34
|
-
return null;
|
|
35
|
-
}
|
|
36
|
-
function environmentCase(name) {
|
|
37
|
-
return (0, lodash_snakecase.default)(name).toUpperCase().replace(/_\d+/g, (r) => {
|
|
38
|
-
return r.replace("_", "");
|
|
39
|
-
});
|
|
40
|
-
}
|
|
41
|
-
let ResourceType = /* @__PURE__ */ function(ResourceType$1) {
|
|
42
|
-
ResourceType$1["ApiGatewayV2"] = "sst.aws.ApiGatewayV2";
|
|
43
|
-
ResourceType$1["Postgres"] = "sst.aws.Postgres";
|
|
44
|
-
ResourceType$1["Function"] = "sst.aws.Function";
|
|
45
|
-
ResourceType$1["ObjectStorage"] = "sst.aws.Bucket";
|
|
46
|
-
ResourceType$1["Vpc"] = "sst.aws.Vpc";
|
|
47
|
-
ResourceType$1["Secret"] = "sst.sst.Secret";
|
|
48
|
-
ResourceType$1["SSTSecret"] = "sst:sst:Secret";
|
|
49
|
-
ResourceType$1["SSTFunction"] = "sst:sst:Function";
|
|
50
|
-
ResourceType$1["SSTApiGatewayV2"] = "sst:aws:ApiGatewayV2";
|
|
51
|
-
ResourceType$1["SSTPostgres"] = "sst:aws:Postgres";
|
|
52
|
-
ResourceType$1["SSTObjectStorage"] = "sst:aws:Bucket";
|
|
53
|
-
ResourceType$1["SnsTopic"] = "sst:aws:SnsTopic";
|
|
54
|
-
return ResourceType$1;
|
|
55
|
-
}({});
|
|
56
|
-
const secret = (name, value) => ({ [environmentCase(name)]: value.value });
|
|
57
|
-
const postgres = (key, value) => {
|
|
58
|
-
const prefix = `${environmentCase(key)}`;
|
|
59
|
-
return {
|
|
60
|
-
[`${prefix}_NAME`]: value.database,
|
|
61
|
-
[`${prefix}_HOST`]: value.host,
|
|
62
|
-
[`${prefix}_PASSWORD`]: value.password,
|
|
63
|
-
[`${prefix}_PORT`]: value.port,
|
|
64
|
-
[`${prefix}_USERNAME`]: value.username
|
|
65
|
-
};
|
|
66
|
-
};
|
|
67
|
-
const bucket = (name, value) => {
|
|
68
|
-
const prefix = `${environmentCase(name)}`;
|
|
69
|
-
return { [`${prefix}_NAME`]: value.name };
|
|
70
|
-
};
|
|
71
|
-
const topic = (name, value) => {
|
|
72
|
-
const prefix = `${environmentCase(name)}`;
|
|
73
|
-
const key = `${prefix}_ARN`;
|
|
74
|
-
return { [key]: value.arn };
|
|
75
|
-
};
|
|
76
|
-
const noop = (_name, _value) => ({});
|
|
77
|
-
const processors = {
|
|
78
|
-
[ResourceType.ApiGatewayV2]: noop,
|
|
79
|
-
[ResourceType.Function]: noop,
|
|
80
|
-
[ResourceType.Vpc]: noop,
|
|
81
|
-
[ResourceType.Secret]: secret,
|
|
82
|
-
[ResourceType.Postgres]: postgres,
|
|
83
|
-
[ResourceType.ObjectStorage]: bucket,
|
|
84
|
-
[ResourceType.SSTSecret]: secret,
|
|
85
|
-
[ResourceType.SSTObjectStorage]: bucket,
|
|
86
|
-
[ResourceType.SSTFunction]: noop,
|
|
87
|
-
[ResourceType.SSTPostgres]: postgres,
|
|
88
|
-
[ResourceType.SSTApiGatewayV2]: noop,
|
|
89
|
-
[ResourceType.SnsTopic]: topic
|
|
90
|
-
};
|
|
91
|
-
function buildResourceEnv(record) {
|
|
92
|
-
const env = {};
|
|
93
|
-
for (const [k, value] of Object.entries(record)) {
|
|
94
|
-
if (typeof value === "string") {
|
|
95
|
-
env[environmentCase(k)] = value;
|
|
96
|
-
continue;
|
|
97
|
-
}
|
|
98
|
-
const processor = processors[value.type];
|
|
99
|
-
if (processor) Object.assign(env, processor(k, value));
|
|
100
|
-
}
|
|
101
|
-
return env;
|
|
102
|
-
}
|
|
103
|
-
|
|
104
|
-
//#endregion
|
|
105
|
-
Object.defineProperty(exports, 'ResourceType', {
|
|
106
|
-
enumerable: true,
|
|
107
|
-
get: function () {
|
|
108
|
-
return ResourceType;
|
|
109
|
-
}
|
|
110
|
-
});
|
|
111
|
-
Object.defineProperty(exports, 'buildResourceEnv', {
|
|
112
|
-
enumerable: true,
|
|
113
|
-
get: function () {
|
|
114
|
-
return buildResourceEnv;
|
|
115
|
-
}
|
|
116
|
-
});
|
|
117
|
-
Object.defineProperty(exports, 'environmentCase', {
|
|
118
|
-
enumerable: true,
|
|
119
|
-
get: function () {
|
|
120
|
-
return environmentCase;
|
|
121
|
-
}
|
|
122
|
-
});
|
|
123
|
-
Object.defineProperty(exports, 'getLocalIpAddress', {
|
|
124
|
-
enumerable: true,
|
|
125
|
-
get: function () {
|
|
126
|
-
return getLocalIpAddress;
|
|
127
|
-
}
|
|
128
|
-
});
|
|
129
|
-
//# sourceMappingURL=utils-B1a2UuEO.cjs.map
|
|
@@ -1 +0,0 @@
|
|
|
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"}
|