@empire-builder-kit/nx 1.0.0-beta.4
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/LICENSE +201 -0
- package/NOTICE +5 -0
- package/README.md +25 -0
- package/executors.json +54 -0
- package/generators.json +35 -0
- package/migrations/standard-pre-v1-to-v1.md +11 -0
- package/package.json +66 -0
- package/src/blueprints/execution.d.ts +31 -0
- package/src/blueprints/execution.js +166 -0
- package/src/blueprints/execution.js.map +1 -0
- package/src/blueprints/index.d.ts +5 -0
- package/src/blueprints/index.js +9 -0
- package/src/blueprints/index.js.map +1 -0
- package/src/blueprints/inputs.d.ts +43 -0
- package/src/blueprints/inputs.js +103 -0
- package/src/blueprints/inputs.js.map +1 -0
- package/src/blueprints/manifest.d.ts +241 -0
- package/src/blueprints/manifest.js +369 -0
- package/src/blueprints/manifest.js.map +1 -0
- package/src/blueprints/resolver.d.ts +28 -0
- package/src/blueprints/resolver.js +214 -0
- package/src/blueprints/resolver.js.map +1 -0
- package/src/blueprints/transitions.d.ts +20 -0
- package/src/blueprints/transitions.js +61 -0
- package/src/blueprints/transitions.js.map +1 -0
- package/src/executors/deploy/deploy.d.ts +4 -0
- package/src/executors/deploy/deploy.js +6 -0
- package/src/executors/deploy/deploy.js.map +1 -0
- package/src/executors/dev/dev.d.ts +4 -0
- package/src/executors/dev/dev.js +6 -0
- package/src/executors/dev/dev.js.map +1 -0
- package/src/executors/dev-doctor/dev-doctor.d.ts +18 -0
- package/src/executors/dev-doctor/dev-doctor.js +145 -0
- package/src/executors/dev-doctor/dev-doctor.js.map +1 -0
- package/src/executors/dev-doctor/schema.json +17 -0
- package/src/executors/dev-setup/dev-setup.d.ts +11 -0
- package/src/executors/dev-setup/dev-setup.js +454 -0
- package/src/executors/dev-setup/dev-setup.js.map +1 -0
- package/src/executors/dev-setup/schema.json +16 -0
- package/src/executors/fleet/fleet.d.ts +51 -0
- package/src/executors/fleet/fleet.js +529 -0
- package/src/executors/fleet/fleet.js.map +1 -0
- package/src/executors/fleet/schema.json +25 -0
- package/src/executors/foundation-preflight/foundation-preflight.d.ts +15 -0
- package/src/executors/foundation-preflight/foundation-preflight.js +94 -0
- package/src/executors/foundation-preflight/foundation-preflight.js.map +1 -0
- package/src/executors/foundation-preflight/schema.json +31 -0
- package/src/executors/foundation-remove-preflight/foundation-remove-preflight.d.ts +13 -0
- package/src/executors/foundation-remove-preflight/foundation-remove-preflight.js +69 -0
- package/src/executors/foundation-remove-preflight/foundation-remove-preflight.js.map +1 -0
- package/src/executors/foundation-remove-preflight/schema.json +17 -0
- package/src/executors/refresh/refresh.d.ts +4 -0
- package/src/executors/refresh/refresh.js +6 -0
- package/src/executors/refresh/refresh.js.map +1 -0
- package/src/executors/remove/remove.d.ts +4 -0
- package/src/executors/remove/remove.js +6 -0
- package/src/executors/remove/remove.js.map +1 -0
- package/src/executors/sst-lifecycle/run-sst-command.d.ts +28 -0
- package/src/executors/sst-lifecycle/run-sst-command.js +154 -0
- package/src/executors/sst-lifecycle/run-sst-command.js.map +1 -0
- package/src/executors/sst-lifecycle/schema.json +45 -0
- package/src/executors/unlock/unlock.d.ts +4 -0
- package/src/executors/unlock/unlock.js +6 -0
- package/src/executors/unlock/unlock.js.map +1 -0
- package/src/foundation/aurora-logical-database.d.ts +76 -0
- package/src/foundation/aurora-logical-database.js +419 -0
- package/src/foundation/aurora-logical-database.js.map +1 -0
- package/src/foundation/discovery.d.ts +55 -0
- package/src/foundation/discovery.js +55 -0
- package/src/foundation/discovery.js.map +1 -0
- package/src/foundation/index.d.ts +6 -0
- package/src/foundation/index.js +10 -0
- package/src/foundation/index.js.map +1 -0
- package/src/foundation/local-database-contract.d.ts +30 -0
- package/src/foundation/local-database-contract.js +75 -0
- package/src/foundation/local-database-contract.js.map +1 -0
- package/src/foundation/preflight.d.ts +31 -0
- package/src/foundation/preflight.js +114 -0
- package/src/foundation/preflight.js.map +1 -0
- package/src/foundation/provision-database-bindings.d.ts +30 -0
- package/src/foundation/provision-database-bindings.js +113 -0
- package/src/foundation/provision-database-bindings.js.map +1 -0
- package/src/foundation/provision-logical-database.d.ts +26 -0
- package/src/foundation/provision-logical-database.js +162 -0
- package/src/foundation/provision-logical-database.js.map +1 -0
- package/src/foundation/requirements.d.ts +37 -0
- package/src/foundation/requirements.js +141 -0
- package/src/foundation/requirements.js.map +1 -0
- package/src/foundation/stages.d.ts +14 -0
- package/src/foundation/stages.js +51 -0
- package/src/foundation/stages.js.map +1 -0
- package/src/generators/function/function.d.ts +13 -0
- package/src/generators/function/function.js +71 -0
- package/src/generators/function/function.js.map +1 -0
- package/src/generators/function/schema.d.ts +5 -0
- package/src/generators/function/schema.json +20 -0
- package/src/generators/job/job.d.ts +4 -0
- package/src/generators/job/job.js +5 -0
- package/src/generators/job/job.js.map +1 -0
- package/src/generators/preset/generator.d.ts +5 -0
- package/src/generators/preset/generator.js +41 -0
- package/src/generators/preset/generator.js.map +1 -0
- package/src/generators/preset/schema.d.ts +4 -0
- package/src/generators/preset/schema.json +22 -0
- package/src/generators/preset/workspace-files.d.ts +18 -0
- package/src/generators/preset/workspace-files.js +895 -0
- package/src/generators/preset/workspace-files.js.map +1 -0
- package/src/generators/service/service.d.ts +4 -0
- package/src/generators/service/service.js +5 -0
- package/src/generators/service/service.js.map +1 -0
- package/src/generators/slice/schema.d.ts +7 -0
- package/src/generators/slice/schema.json +38 -0
- package/src/generators/slice/slice.d.ts +26 -0
- package/src/generators/slice/slice.js +1676 -0
- package/src/generators/slice/slice.js.map +1 -0
- package/src/generators/upgrade/schema.d.ts +8 -0
- package/src/generators/upgrade/schema.json +31 -0
- package/src/generators/upgrade/upgrade.d.ts +27 -0
- package/src/generators/upgrade/upgrade.js +666 -0
- package/src/generators/upgrade/upgrade.js.map +1 -0
- package/src/generators/workload/schema.d.ts +6 -0
- package/src/generators/workload/schema.json +21 -0
- package/src/generators/workload/workload.d.ts +16 -0
- package/src/generators/workload/workload.js +157 -0
- package/src/generators/workload/workload.js.map +1 -0
- package/src/index.d.ts +5 -0
- package/src/index.js +9 -0
- package/src/index.js.map +1 -0
- package/src/local-dev/contracts.d.ts +31 -0
- package/src/local-dev/contracts.js +126 -0
- package/src/local-dev/contracts.js.map +1 -0
- package/src/local-dev/gateway-daemon.d.ts +4 -0
- package/src/local-dev/gateway-daemon.js +39 -0
- package/src/local-dev/gateway-daemon.js.map +1 -0
- package/src/local-dev/gateway.d.ts +60 -0
- package/src/local-dev/gateway.js +368 -0
- package/src/local-dev/gateway.js.map +1 -0
- package/src/local-dev/identity.d.ts +16 -0
- package/src/local-dev/identity.js +101 -0
- package/src/local-dev/identity.js.map +1 -0
- package/src/local-dev/index.d.ts +7 -0
- package/src/local-dev/index.js +11 -0
- package/src/local-dev/index.js.map +1 -0
- package/src/local-dev/portless.d.ts +15 -0
- package/src/local-dev/portless.js +115 -0
- package/src/local-dev/portless.js.map +1 -0
- package/src/local-dev/ports.d.ts +10 -0
- package/src/local-dev/ports.js +39 -0
- package/src/local-dev/ports.js.map +1 -0
- package/src/local-dev/proxy.d.ts +37 -0
- package/src/local-dev/proxy.js +271 -0
- package/src/local-dev/proxy.js.map +1 -0
- package/src/local-dev/tls.d.ts +24 -0
- package/src/local-dev/tls.js +294 -0
- package/src/local-dev/tls.js.map +1 -0
- package/src/ownership/composition.d.ts +16 -0
- package/src/ownership/composition.js +125 -0
- package/src/ownership/composition.js.map +1 -0
- package/src/ownership/foundation-record.d.ts +66 -0
- package/src/ownership/foundation-record.js +108 -0
- package/src/ownership/foundation-record.js.map +1 -0
- package/src/ownership/hash.d.ts +2 -0
- package/src/ownership/hash.js +10 -0
- package/src/ownership/hash.js.map +1 -0
- package/src/ownership/index.d.ts +6 -0
- package/src/ownership/index.js +10 -0
- package/src/ownership/index.js.map +1 -0
- package/src/ownership/json-ownership.d.ts +13 -0
- package/src/ownership/json-ownership.js +147 -0
- package/src/ownership/json-ownership.js.map +1 -0
- package/src/ownership/record.d.ts +186 -0
- package/src/ownership/record.js +336 -0
- package/src/ownership/record.js.map +1 -0
- package/src/ownership/workspace-record.d.ts +66 -0
- package/src/ownership/workspace-record.js +108 -0
- package/src/ownership/workspace-record.js.map +1 -0
- package/src/schemas/blueprint-input-schema-v1.json +23 -0
- package/src/schemas/blueprint-v1.json +170 -0
- package/src/schemas/foundation-ownership-v2.json +42 -0
- package/src/schemas/foundation-requirement-v1.json +32 -0
- package/src/schemas/generated-ownership-v2.json +117 -0
- package/src/schemas/workspace-ownership-v2.json +42 -0
- package/src/validation.d.ts +14 -0
- package/src/validation.js +14 -0
- package/src/validation.js.map +1 -0
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.POSTGRES_IDENTIFIER_MAX_BYTES = void 0;
|
|
4
|
+
exports.normalizePostgresIdentifier = normalizePostgresIdentifier;
|
|
5
|
+
exports.postgresIdentifierByteLength = postgresIdentifierByteLength;
|
|
6
|
+
exports.assertPostgresIdentifierLength = assertPostgresIdentifierLength;
|
|
7
|
+
exports.resolveLogicalDatabaseIdentifiers = resolveLogicalDatabaseIdentifiers;
|
|
8
|
+
exports.resolveLocalDatabaseContract = resolveLocalDatabaseContract;
|
|
9
|
+
exports.POSTGRES_IDENTIFIER_MAX_BYTES = 63;
|
|
10
|
+
function normalizePostgresIdentifier(input) {
|
|
11
|
+
const sanitized = input.replace(/[^A-Za-z0-9_]/g, '_');
|
|
12
|
+
return /^[A-Za-z_]/.test(sanitized) ? sanitized : `s_${sanitized}`;
|
|
13
|
+
}
|
|
14
|
+
function requireIdentifierInput(value, label) {
|
|
15
|
+
if (value.trim() === '') {
|
|
16
|
+
throw new Error(`${label} must be a non-empty string.`);
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
function postgresIdentifierByteLength(identifier) {
|
|
20
|
+
return new TextEncoder().encode(identifier).byteLength;
|
|
21
|
+
}
|
|
22
|
+
function assertPostgresIdentifierLength(identifier, label) {
|
|
23
|
+
const bytes = postgresIdentifierByteLength(identifier);
|
|
24
|
+
if (bytes > exports.POSTGRES_IDENTIFIER_MAX_BYTES) {
|
|
25
|
+
throw new Error(`${label} "${identifier}" is ${bytes} UTF-8 bytes; PostgreSQL identifiers must be ${exports.POSTGRES_IDENTIFIER_MAX_BYTES} bytes or fewer. Choose a shorter stage, Slice, or database identifier. Identifiers are never truncated.`);
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
function resolveLogicalDatabaseIdentifiers(options) {
|
|
29
|
+
requireIdentifierInput(options.stage, 'Consumer stage');
|
|
30
|
+
requireIdentifierInput(options.slice, 'Product Slice name');
|
|
31
|
+
requireIdentifierInput(options.database, 'Logical database identifier');
|
|
32
|
+
const database = normalizePostgresIdentifier(`${options.stage}_${options.slice}_${options.database}`);
|
|
33
|
+
const readwriteRole = `${database}_readwrite`;
|
|
34
|
+
const readonlyRole = `${database}_readonly`;
|
|
35
|
+
const localDatabase = normalizePostgresIdentifier(`${options.slice}_${options.database}`);
|
|
36
|
+
const localReadwriteRole = `${localDatabase}_readwrite`;
|
|
37
|
+
for (const [identifier, label] of [
|
|
38
|
+
[database, 'Physical database identifier'],
|
|
39
|
+
[readwriteRole, 'Physical read-write role identifier'],
|
|
40
|
+
[readonlyRole, 'Physical read-only role identifier'],
|
|
41
|
+
[localDatabase, 'Local database identifier'],
|
|
42
|
+
[localReadwriteRole, 'Local read-write role identifier'],
|
|
43
|
+
]) {
|
|
44
|
+
assertPostgresIdentifierLength(identifier, label);
|
|
45
|
+
}
|
|
46
|
+
return {
|
|
47
|
+
database,
|
|
48
|
+
localDatabase,
|
|
49
|
+
localReadwriteRole,
|
|
50
|
+
readonlyRole,
|
|
51
|
+
readwriteRole,
|
|
52
|
+
};
|
|
53
|
+
}
|
|
54
|
+
function deterministicLocalDatabasePort(key) {
|
|
55
|
+
let hash = 5381;
|
|
56
|
+
for (let index = 0; index < key.length; index += 1) {
|
|
57
|
+
hash = (hash * 33) ^ key.charCodeAt(index);
|
|
58
|
+
}
|
|
59
|
+
return 54320 + (Math.abs(hash) % 100);
|
|
60
|
+
}
|
|
61
|
+
function resolveLocalDatabaseContract(options) {
|
|
62
|
+
const database = normalizePostgresIdentifier(`${options.slice}_${options.database}`);
|
|
63
|
+
const username = `${database}_readwrite`;
|
|
64
|
+
assertPostgresIdentifierLength(database, 'Local database identifier');
|
|
65
|
+
assertPostgresIdentifierLength(username, 'Local read-write role identifier');
|
|
66
|
+
return {
|
|
67
|
+
database,
|
|
68
|
+
host: '127.0.0.1',
|
|
69
|
+
password: options.password ?? `${options.slice}-local-dev`,
|
|
70
|
+
port: options.port ??
|
|
71
|
+
deterministicLocalDatabasePort(`${options.slice}_${options.database}`),
|
|
72
|
+
username,
|
|
73
|
+
};
|
|
74
|
+
}
|
|
75
|
+
//# sourceMappingURL=local-database-contract.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"local-database-contract.js","sourceRoot":"","sources":["../../../../../packages/nx/src/foundation/local-database-contract.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { type FoundationDiscovery } from './discovery.js';
|
|
2
|
+
import { type FoundationRequirement } from './requirements.js';
|
|
3
|
+
export interface FoundationParameterReadResult {
|
|
4
|
+
invalidNames: readonly string[];
|
|
5
|
+
values: ReadonlyMap<string, string | undefined>;
|
|
6
|
+
}
|
|
7
|
+
export type FoundationParameterReader = (names: readonly string[]) => Promise<FoundationParameterReadResult>;
|
|
8
|
+
export interface FoundationPreflightReport {
|
|
9
|
+
consumerStage: string;
|
|
10
|
+
discovery?: FoundationDiscovery;
|
|
11
|
+
foundationStage: string;
|
|
12
|
+
issues: readonly string[];
|
|
13
|
+
ok: boolean;
|
|
14
|
+
region: string;
|
|
15
|
+
state: 'absent' | 'invalid' | 'ready';
|
|
16
|
+
}
|
|
17
|
+
export declare function createFoundationParameterReader(options: {
|
|
18
|
+
profile?: string;
|
|
19
|
+
region?: string;
|
|
20
|
+
}): {
|
|
21
|
+
read: FoundationParameterReader;
|
|
22
|
+
resolveRegion: () => Promise<string>;
|
|
23
|
+
};
|
|
24
|
+
export declare function evaluateFoundationPreflight(options: {
|
|
25
|
+
consumerStage: string;
|
|
26
|
+
foundationStage?: string;
|
|
27
|
+
readParameters: FoundationParameterReader;
|
|
28
|
+
region: string;
|
|
29
|
+
requirement: FoundationRequirement;
|
|
30
|
+
}): Promise<FoundationPreflightReport>;
|
|
31
|
+
export declare function formatFoundationPreflightReport(report: FoundationPreflightReport): string;
|
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.createFoundationParameterReader = createFoundationParameterReader;
|
|
4
|
+
exports.evaluateFoundationPreflight = evaluateFoundationPreflight;
|
|
5
|
+
exports.formatFoundationPreflightReport = formatFoundationPreflightReport;
|
|
6
|
+
const client_ssm_1 = require("@aws-sdk/client-ssm");
|
|
7
|
+
const credential_providers_1 = require("@aws-sdk/credential-providers");
|
|
8
|
+
const discovery_js_1 = require("./discovery.js");
|
|
9
|
+
const requirements_js_1 = require("./requirements.js");
|
|
10
|
+
const stages_js_1 = require("./stages.js");
|
|
11
|
+
function chunks(values, size) {
|
|
12
|
+
const result = [];
|
|
13
|
+
for (let index = 0; index < values.length; index += size) {
|
|
14
|
+
result.push(values.slice(index, index + size));
|
|
15
|
+
}
|
|
16
|
+
return result;
|
|
17
|
+
}
|
|
18
|
+
function createFoundationParameterReader(options) {
|
|
19
|
+
const profile = options.profile?.trim();
|
|
20
|
+
const client = new client_ssm_1.SSMClient({
|
|
21
|
+
...(profile ? { credentials: (0, credential_providers_1.fromIni)({ profile }) } : {}),
|
|
22
|
+
...(options.region?.trim() ? { region: options.region.trim() } : {}),
|
|
23
|
+
});
|
|
24
|
+
return {
|
|
25
|
+
read: async (names) => {
|
|
26
|
+
const response = await client.send(new client_ssm_1.GetParametersCommand({ Names: [...names] }));
|
|
27
|
+
return {
|
|
28
|
+
invalidNames: response.InvalidParameters ?? [],
|
|
29
|
+
values: new Map((response.Parameters ?? []).map((parameter) => [
|
|
30
|
+
parameter.Name ?? '',
|
|
31
|
+
parameter.Value,
|
|
32
|
+
])),
|
|
33
|
+
};
|
|
34
|
+
},
|
|
35
|
+
resolveRegion: () => client.config.region(),
|
|
36
|
+
};
|
|
37
|
+
}
|
|
38
|
+
async function evaluateFoundationPreflight(options) {
|
|
39
|
+
const { consumerStage, foundationStage } = (0, stages_js_1.resolveFoundationStages)(options);
|
|
40
|
+
const names = discovery_js_1.FOUNDATION_REQUIRED_SSM_KEYS.map((key) => (0, discovery_js_1.foundationSsmPath)(foundationStage, key));
|
|
41
|
+
const values = new Map();
|
|
42
|
+
const invalidNames = new Set();
|
|
43
|
+
for (const batch of chunks(names, 10)) {
|
|
44
|
+
const result = await options.readParameters(batch);
|
|
45
|
+
result.invalidNames.forEach((name) => invalidNames.add(name));
|
|
46
|
+
result.values.forEach((value, name) => values.set(name, value));
|
|
47
|
+
}
|
|
48
|
+
const issues = names
|
|
49
|
+
.filter((name) => invalidNames.has(name) || !values.get(name))
|
|
50
|
+
.map((name) => `missing required parameter ${name}`);
|
|
51
|
+
const allRequiredParametersMissing = names.every((name) => invalidNames.has(name) || !values.has(name));
|
|
52
|
+
const value = (key) => values.get((0, discovery_js_1.foundationSsmPath)(foundationStage, key)) ?? '';
|
|
53
|
+
const schemaVersion = Number(value('schemaVersion'));
|
|
54
|
+
if (schemaVersion !== discovery_js_1.FOUNDATION_SSM_SCHEMA_VERSION) {
|
|
55
|
+
issues.push(`Foundation discovery schema ${value('schemaVersion') || 'missing'} does not match ${discovery_js_1.FOUNDATION_SSM_SCHEMA_VERSION}`);
|
|
56
|
+
}
|
|
57
|
+
const capabilities = value('capabilities')
|
|
58
|
+
.split(',')
|
|
59
|
+
.map((capability) => capability.trim())
|
|
60
|
+
.filter(Boolean);
|
|
61
|
+
const compatibility = (0, requirements_js_1.validateFoundationCompatibility)(options.requirement, {
|
|
62
|
+
capabilities,
|
|
63
|
+
contractVersion: value('contractVersion'),
|
|
64
|
+
});
|
|
65
|
+
issues.push(...compatibility.issues.map((issue) => `${issue.path}: ${issue.message}`));
|
|
66
|
+
if (issues.length > 0 || !compatibility.valid) {
|
|
67
|
+
return {
|
|
68
|
+
consumerStage,
|
|
69
|
+
foundationStage,
|
|
70
|
+
issues: [...new Set(issues)],
|
|
71
|
+
ok: false,
|
|
72
|
+
region: options.region,
|
|
73
|
+
state: allRequiredParametersMissing ? 'absent' : 'invalid',
|
|
74
|
+
};
|
|
75
|
+
}
|
|
76
|
+
return {
|
|
77
|
+
discovery: {
|
|
78
|
+
alertTopicArn: value('alertTopicArn'),
|
|
79
|
+
capabilities: compatibility.value.capabilities,
|
|
80
|
+
clusterId: value('clusterId'),
|
|
81
|
+
contractVersion: compatibility.value.contractVersion,
|
|
82
|
+
databaseClusterArn: value('databaseClusterArn'),
|
|
83
|
+
databaseClusterId: value('databaseClusterId'),
|
|
84
|
+
databaseMasterSecretArn: value('databaseMasterSecretArn'),
|
|
85
|
+
eventBusArn: value('eventBusArn'),
|
|
86
|
+
eventBusName: value('eventBusName'),
|
|
87
|
+
hasPublicDomain: value('hasPublicDomain') === 'true',
|
|
88
|
+
identityUserPoolArn: value('identityUserPoolArn'),
|
|
89
|
+
identityUserPoolId: value('identityUserPoolId'),
|
|
90
|
+
rootDomain: value('rootDomain') === 'none' ? undefined : value('rootDomain'),
|
|
91
|
+
routerDistributionId: value('routerDistributionId'),
|
|
92
|
+
routerUrl: value('routerUrl'),
|
|
93
|
+
schemaVersion: discovery_js_1.FOUNDATION_SSM_SCHEMA_VERSION,
|
|
94
|
+
vpcId: value('vpcId'),
|
|
95
|
+
},
|
|
96
|
+
consumerStage,
|
|
97
|
+
foundationStage,
|
|
98
|
+
issues: [],
|
|
99
|
+
ok: true,
|
|
100
|
+
region: options.region,
|
|
101
|
+
state: 'ready',
|
|
102
|
+
};
|
|
103
|
+
}
|
|
104
|
+
function formatFoundationPreflightReport(report) {
|
|
105
|
+
const lines = [
|
|
106
|
+
`[foundation-preflight] consumerStage=${report.consumerStage} foundationStage=${report.foundationStage} region=${report.region}: ${report.ok ? 'ready' : 'NOT ready'}`,
|
|
107
|
+
];
|
|
108
|
+
report.issues.forEach((issue) => lines.push(` - ${issue}`));
|
|
109
|
+
if (!report.ok) {
|
|
110
|
+
lines.push(` Deploy the Foundation first: pnpm nx run foundation:deploy --stage=${report.foundationStage}`);
|
|
111
|
+
}
|
|
112
|
+
return lines.join('\n');
|
|
113
|
+
}
|
|
114
|
+
//# sourceMappingURL=preflight.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"preflight.js","sourceRoot":"","sources":["../../../../../packages/nx/src/foundation/preflight.ts"],"names":[],"mappings":";;AA0CA,0EA6BC;AAED,kEAuFC;AAED,0EAaC;AA/KD,oDAAsE;AACtE,wEAAwD;AACxD,iDAMwB;AACxB,uDAG2B;AAC3B,2CAAsD;AAqBtD,SAAS,MAAM,CAAI,MAAoB,EAAE,IAAY;IACnD,MAAM,MAAM,GAAU,EAAE,CAAC;IACzB,KAAK,IAAI,KAAK,GAAG,CAAC,EAAE,KAAK,GAAG,MAAM,CAAC,MAAM,EAAE,KAAK,IAAI,IAAI,EAAE,CAAC;QACzD,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,KAAK,EAAE,KAAK,GAAG,IAAI,CAAC,CAAC,CAAC;IACjD,CAAC;IACD,OAAO,MAAM,CAAC;AAChB,CAAC;AAED,SAAgB,+BAA+B,CAAC,OAG/C;IAIC,MAAM,OAAO,GAAG,OAAO,CAAC,OAAO,EAAE,IAAI,EAAE,CAAC;IACxC,MAAM,MAAM,GAAG,IAAI,sBAAS,CAAC;QAC3B,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,WAAW,EAAE,IAAA,8BAAO,EAAC,EAAE,OAAO,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QACzD,GAAG,CAAC,OAAO,CAAC,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,OAAO,CAAC,MAAM,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;KACrE,CAAC,CAAC;IACH,OAAO;QACL,IAAI,EAAE,KAAK,EAAE,KAAK,EAAE,EAAE;YACpB,MAAM,QAAQ,GAAG,MAAM,MAAM,CAAC,IAAI,CAChC,IAAI,iCAAoB,CAAC,EAAE,KAAK,EAAE,CAAC,GAAG,KAAK,CAAC,EAAE,CAAC,CAChD,CAAC;YACF,OAAO;gBACL,YAAY,EAAE,QAAQ,CAAC,iBAAiB,IAAI,EAAE;gBAC9C,MAAM,EAAE,IAAI,GAAG,CACb,CAAC,QAAQ,CAAC,UAAU,IAAI,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,SAAS,EAAE,EAAE,CAAC;oBAC7C,SAAS,CAAC,IAAI,IAAI,EAAE;oBACpB,SAAS,CAAC,KAAK;iBAChB,CAAC,CACH;aACF,CAAC;QACJ,CAAC;QACD,aAAa,EAAE,GAAG,EAAE,CAAC,MAAM,CAAC,MAAM,CAAC,MAAM,EAAE;KAC5C,CAAC;AACJ,CAAC;AAEM,KAAK,UAAU,2BAA2B,CAAC,OAMjD;IACC,MAAM,EAAE,aAAa,EAAE,eAAe,EAAE,GAAG,IAAA,mCAAuB,EAAC,OAAO,CAAC,CAAC;IAC5E,MAAM,KAAK,GAAG,2CAA4B,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE,CACrD,IAAA,gCAAiB,EAAC,eAAe,EAAE,GAAG,CAAC,CACxC,CAAC;IACF,MAAM,MAAM,GAAG,IAAI,GAAG,EAA8B,CAAC;IACrD,MAAM,YAAY,GAAG,IAAI,GAAG,EAAU,CAAC;IAEvC,KAAK,MAAM,KAAK,IAAI,MAAM,CAAC,KAAK,EAAE,EAAE,CAAC,EAAE,CAAC;QACtC,MAAM,MAAM,GAAG,MAAM,OAAO,CAAC,cAAc,CAAC,KAAK,CAAC,CAAC;QACnD,MAAM,CAAC,YAAY,CAAC,OAAO,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,YAAY,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC;QAC9D,MAAM,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,KAAK,EAAE,IAAI,EAAE,EAAE,CAAC,MAAM,CAAC,GAAG,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC,CAAC;IAClE,CAAC;IAED,MAAM,MAAM,GAAG,KAAK;SACjB,MAAM,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,YAAY,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;SAC7D,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,8BAA8B,IAAI,EAAE,CAAC,CAAC;IACvD,MAAM,4BAA4B,GAAG,KAAK,CAAC,KAAK,CAC9C,CAAC,IAAI,EAAE,EAAE,CAAC,YAAY,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,IAAI,CAAC,CACtD,CAAC;IACF,MAAM,KAAK,GAAG,CAAC,GAAqB,EAAE,EAAE,CACtC,MAAM,CAAC,GAAG,CAAC,IAAA,gCAAiB,EAAC,eAAe,EAAE,GAAG,CAAC,CAAC,IAAI,EAAE,CAAC;IAE5D,MAAM,aAAa,GAAG,MAAM,CAAC,KAAK,CAAC,eAAe,CAAC,CAAC,CAAC;IACrD,IAAI,aAAa,KAAK,4CAA6B,EAAE,CAAC;QACpD,MAAM,CAAC,IAAI,CACT,+BAA+B,KAAK,CAAC,eAAe,CAAC,IAAI,SAAS,mBAAmB,4CAA6B,EAAE,CACrH,CAAC;IACJ,CAAC;IAED,MAAM,YAAY,GAAG,KAAK,CAAC,cAAc,CAAC;SACvC,KAAK,CAAC,GAAG,CAAC;SACV,GAAG,CAAC,CAAC,UAAU,EAAE,EAAE,CAAC,UAAU,CAAC,IAAI,EAAE,CAAC;SACtC,MAAM,CAAC,OAAO,CAAC,CAAC;IACnB,MAAM,aAAa,GAAG,IAAA,iDAA+B,EAAC,OAAO,CAAC,WAAW,EAAE;QACzE,YAAY;QACZ,eAAe,EAAE,KAAK,CAAC,iBAAiB,CAAC;KAC1C,CAAC,CAAC;IACH,MAAM,CAAC,IAAI,CACT,GAAG,aAAa,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,GAAG,KAAK,CAAC,IAAI,KAAK,KAAK,CAAC,OAAO,EAAE,CAAC,CAC1E,CAAC;IAEF,IAAI,MAAM,CAAC,MAAM,GAAG,CAAC,IAAI,CAAC,aAAa,CAAC,KAAK,EAAE,CAAC;QAC9C,OAAO;YACL,aAAa;YACb,eAAe;YACf,MAAM,EAAE,CAAC,GAAG,IAAI,GAAG,CAAC,MAAM,CAAC,CAAC;YAC5B,EAAE,EAAE,KAAK;YACT,MAAM,EAAE,OAAO,CAAC,MAAM;YACtB,KAAK,EAAE,4BAA4B,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,SAAS;SAC3D,CAAC;IACJ,CAAC;IAED,OAAO;QACL,SAAS,EAAE;YACT,aAAa,EAAE,KAAK,CAAC,eAAe,CAAC;YACrC,YAAY,EAAE,aAAa,CAAC,KAAK,CAAC,YAAY;YAC9C,SAAS,EAAE,KAAK,CAAC,WAAW,CAAC;YAC7B,eAAe,EAAE,aAAa,CAAC,KAAK,CAAC,eAAe;YACpD,kBAAkB,EAAE,KAAK,CAAC,oBAAoB,CAAC;YAC/C,iBAAiB,EAAE,KAAK,CAAC,mBAAmB,CAAC;YAC7C,uBAAuB,EAAE,KAAK,CAAC,yBAAyB,CAAC;YACzD,WAAW,EAAE,KAAK,CAAC,aAAa,CAAC;YACjC,YAAY,EAAE,KAAK,CAAC,cAAc,CAAC;YACnC,eAAe,EAAE,KAAK,CAAC,iBAAiB,CAAC,KAAK,MAAM;YACpD,mBAAmB,EAAE,KAAK,CAAC,qBAAqB,CAAC;YACjD,kBAAkB,EAAE,KAAK,CAAC,oBAAoB,CAAC;YAC/C,UAAU,EACR,KAAK,CAAC,YAAY,CAAC,KAAK,MAAM,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,KAAK,CAAC,YAAY,CAAC;YAClE,oBAAoB,EAAE,KAAK,CAAC,sBAAsB,CAAC;YACnD,SAAS,EAAE,KAAK,CAAC,WAAW,CAAC;YAC7B,aAAa,EAAE,4CAA6B;YAC5C,KAAK,EAAE,KAAK,CAAC,OAAO,CAAC;SACtB;QACD,aAAa;QACb,eAAe;QACf,MAAM,EAAE,EAAE;QACV,EAAE,EAAE,IAAI;QACR,MAAM,EAAE,OAAO,CAAC,MAAM;QACtB,KAAK,EAAE,OAAO;KACf,CAAC;AACJ,CAAC;AAED,SAAgB,+BAA+B,CAC7C,MAAiC;IAEjC,MAAM,KAAK,GAAG;QACZ,wCAAwC,MAAM,CAAC,aAAa,oBAAoB,MAAM,CAAC,eAAe,WAAW,MAAM,CAAC,MAAM,KAAK,MAAM,CAAC,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,WAAW,EAAE;KACvK,CAAC;IACF,MAAM,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,IAAI,CAAC,OAAO,KAAK,EAAE,CAAC,CAAC,CAAC;IAC7D,IAAI,CAAC,MAAM,CAAC,EAAE,EAAE,CAAC;QACf,KAAK,CAAC,IAAI,CACR,wEAAwE,MAAM,CAAC,eAAe,EAAE,CACjG,CAAC;IACJ,CAAC;IACD,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AAC1B,CAAC"}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { type LogicalDatabaseIdentifiers } from './local-database-contract.js';
|
|
2
|
+
import { type FoundationInfrastructure, type ProvisionLogicalDatabaseOptions, type ProvisionLogicalDatabaseResult } from './provision-logical-database.js';
|
|
3
|
+
export interface DatabaseBinding {
|
|
4
|
+
active: string;
|
|
5
|
+
provisioned: readonly string[];
|
|
6
|
+
}
|
|
7
|
+
export type DatabaseBindingDeclaration = Readonly<Record<string, DatabaseBinding>>;
|
|
8
|
+
export interface DatabaseBindingPlan {
|
|
9
|
+
active: Readonly<Record<string, string>>;
|
|
10
|
+
identifiers: Readonly<Record<string, LogicalDatabaseIdentifiers>>;
|
|
11
|
+
provisioned: readonly string[];
|
|
12
|
+
}
|
|
13
|
+
export interface ProvisionDatabaseBindingsOptions {
|
|
14
|
+
bindings: DatabaseBindingDeclaration;
|
|
15
|
+
localDev?: boolean;
|
|
16
|
+
localDevPassword?: string;
|
|
17
|
+
removalPolicy?: ProvisionLogicalDatabaseOptions['removalPolicy'];
|
|
18
|
+
rotationTokens?: Readonly<Record<string, string>>;
|
|
19
|
+
slice: string;
|
|
20
|
+
}
|
|
21
|
+
export type ProvisionedDatabaseBindings<TBindings extends DatabaseBindingDeclaration> = {
|
|
22
|
+
[TBinding in keyof TBindings]: ProvisionLogicalDatabaseResult;
|
|
23
|
+
};
|
|
24
|
+
export declare function createDatabaseBindingPlan(bindings: DatabaseBindingDeclaration, context: {
|
|
25
|
+
slice: string;
|
|
26
|
+
stage: string;
|
|
27
|
+
}): DatabaseBindingPlan;
|
|
28
|
+
export declare function provisionDatabaseBindings<TBindings extends DatabaseBindingDeclaration>(foundation: FoundationInfrastructure, options: ProvisionDatabaseBindingsOptions & {
|
|
29
|
+
bindings: TBindings;
|
|
30
|
+
}): ProvisionedDatabaseBindings<TBindings>;
|
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.createDatabaseBindingPlan = createDatabaseBindingPlan;
|
|
4
|
+
exports.provisionDatabaseBindings = provisionDatabaseBindings;
|
|
5
|
+
const local_database_contract_js_1 = require("./local-database-contract.js");
|
|
6
|
+
const provision_logical_database_js_1 = require("./provision-logical-database.js");
|
|
7
|
+
const databaseIdentifierPattern = /^[a-z][a-z0-9]*(?:[-_][a-z0-9]+)*$/;
|
|
8
|
+
function collisionKey(value) {
|
|
9
|
+
return (0, local_database_contract_js_1.normalizePostgresIdentifier)(value).normalize('NFKC').toLowerCase();
|
|
10
|
+
}
|
|
11
|
+
function createDatabaseBindingPlan(bindings, context) {
|
|
12
|
+
if (typeof bindings !== 'object' ||
|
|
13
|
+
bindings === null ||
|
|
14
|
+
Array.isArray(bindings)) {
|
|
15
|
+
throw new Error('Database bindings must be an object.');
|
|
16
|
+
}
|
|
17
|
+
const entries = Object.entries(bindings);
|
|
18
|
+
if (entries.length === 0) {
|
|
19
|
+
throw new Error('Database bindings must declare at least one stable role.');
|
|
20
|
+
}
|
|
21
|
+
const active = {};
|
|
22
|
+
const identifiers = {};
|
|
23
|
+
const declared = new Set();
|
|
24
|
+
const normalized = new Map();
|
|
25
|
+
const componentNames = new Map();
|
|
26
|
+
for (const [role, binding] of entries) {
|
|
27
|
+
if (!/^[a-z][a-z0-9-]*$/.test(role)) {
|
|
28
|
+
throw new Error(`Database binding role "${role}" must start with a lowercase letter and contain only lowercase letters, numbers, and hyphens.`);
|
|
29
|
+
}
|
|
30
|
+
if (typeof binding !== 'object' ||
|
|
31
|
+
binding === null ||
|
|
32
|
+
Array.isArray(binding)) {
|
|
33
|
+
throw new Error(`Database binding "${role}" must be an object.`);
|
|
34
|
+
}
|
|
35
|
+
const unexpectedMembers = Object.keys(binding).filter((key) => key !== 'active' && key !== 'provisioned');
|
|
36
|
+
if (unexpectedMembers.length > 0) {
|
|
37
|
+
throw new Error(`Database binding "${role}" contains unsupported member${unexpectedMembers.length === 1 ? '' : 's'}: ${unexpectedMembers.join(', ')}. Only active and provisioned are allowed.`);
|
|
38
|
+
}
|
|
39
|
+
if (typeof binding.active !== 'string' || binding.active.trim() === '') {
|
|
40
|
+
throw new Error(`Database binding "${role}" must select a non-empty active identifier.`);
|
|
41
|
+
}
|
|
42
|
+
if (!Array.isArray(binding.provisioned) ||
|
|
43
|
+
binding.provisioned.length === 0) {
|
|
44
|
+
throw new Error(`Database binding "${role}" must provision at least one identifier.`);
|
|
45
|
+
}
|
|
46
|
+
if (!binding.provisioned.includes(binding.active)) {
|
|
47
|
+
throw new Error(`Database binding "${role}" selects "${binding.active}", but that identifier is not provisioned.`);
|
|
48
|
+
}
|
|
49
|
+
active[role] = binding.active;
|
|
50
|
+
for (const identifier of binding.provisioned) {
|
|
51
|
+
if (typeof identifier !== 'string' || identifier.trim() === '') {
|
|
52
|
+
throw new Error(`Database binding "${role}" contains an invalid empty identifier.`);
|
|
53
|
+
}
|
|
54
|
+
if (!databaseIdentifierPattern.test(identifier)) {
|
|
55
|
+
throw new Error(`Database identifier "${identifier}" must start with a lowercase letter and contain only lowercase letters, numbers, single hyphens, or single underscores.`);
|
|
56
|
+
}
|
|
57
|
+
if (declared.has(identifier)) {
|
|
58
|
+
throw new Error(`Database identifier "${identifier}" is declared more than once. Each provisioned identifier must be unique across the binding set.`);
|
|
59
|
+
}
|
|
60
|
+
const resolved = (0, local_database_contract_js_1.resolveLogicalDatabaseIdentifiers)({
|
|
61
|
+
database: identifier,
|
|
62
|
+
slice: context.slice,
|
|
63
|
+
stage: context.stage,
|
|
64
|
+
});
|
|
65
|
+
const key = collisionKey(resolved.database);
|
|
66
|
+
const previous = normalized.get(key);
|
|
67
|
+
if (previous !== undefined) {
|
|
68
|
+
throw new Error(`Database identifiers "${previous}" and "${identifier}" collide after PostgreSQL normalization. Rename one identifier; EBK never truncates or aliases database bindings.`);
|
|
69
|
+
}
|
|
70
|
+
const componentName = (0, provision_logical_database_js_1.defaultDatabaseLinkableName)(context.slice, identifier);
|
|
71
|
+
const previousComponent = componentNames.get(componentName);
|
|
72
|
+
if (previousComponent !== undefined) {
|
|
73
|
+
throw new Error(`Database identifiers "${previousComponent}" and "${identifier}" collide after SST logical-name normalization as "${componentName}". Rename one identifier so every resource name is unique before deployment.`);
|
|
74
|
+
}
|
|
75
|
+
declared.add(identifier);
|
|
76
|
+
normalized.set(key, identifier);
|
|
77
|
+
componentNames.set(componentName, identifier);
|
|
78
|
+
identifiers[identifier] = resolved;
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
return {
|
|
82
|
+
active,
|
|
83
|
+
identifiers,
|
|
84
|
+
provisioned: [...declared],
|
|
85
|
+
};
|
|
86
|
+
}
|
|
87
|
+
function provisionDatabaseBindings(foundation, options) {
|
|
88
|
+
// Validate the complete set before the first provisioner call. This is what
|
|
89
|
+
// makes a collision or overlong identifier fail before any local Linkable,
|
|
90
|
+
// Pulumi dynamic resource, Secrets Manager secret, or SQL mutation exists.
|
|
91
|
+
const plan = createDatabaseBindingPlan(options.bindings, {
|
|
92
|
+
slice: options.slice,
|
|
93
|
+
stage: $app.stage,
|
|
94
|
+
});
|
|
95
|
+
const provisioned = new Map();
|
|
96
|
+
for (const database of plan.provisioned) {
|
|
97
|
+
provisioned.set(database, (0, provision_logical_database_js_1.provisionLogicalDatabase)(foundation, {
|
|
98
|
+
database,
|
|
99
|
+
localDev: options.localDev,
|
|
100
|
+
localDevPassword: options.localDevPassword,
|
|
101
|
+
removalPolicy: options.removalPolicy,
|
|
102
|
+
...(options.rotationTokens?.[database] !== undefined
|
|
103
|
+
? { rotationToken: options.rotationTokens[database] }
|
|
104
|
+
: {}),
|
|
105
|
+
slice: options.slice,
|
|
106
|
+
}));
|
|
107
|
+
}
|
|
108
|
+
return Object.fromEntries(Object.entries(plan.active).map(([role, database]) => [
|
|
109
|
+
role,
|
|
110
|
+
provisioned.get(database),
|
|
111
|
+
]));
|
|
112
|
+
}
|
|
113
|
+
//# sourceMappingURL=provision-database-bindings.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"provision-database-bindings.js","sourceRoot":"","sources":["../../../../../packages/nx/src/foundation/provision-database-bindings.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
export interface FoundationDatabaseCapacity {
|
|
2
|
+
cluster: any;
|
|
3
|
+
clusterArn: string;
|
|
4
|
+
masterSecretArn: string;
|
|
5
|
+
}
|
|
6
|
+
export interface FoundationInfrastructure {
|
|
7
|
+
database: FoundationDatabaseCapacity;
|
|
8
|
+
}
|
|
9
|
+
export interface ProvisionLogicalDatabaseOptions {
|
|
10
|
+
slice: string;
|
|
11
|
+
database: string;
|
|
12
|
+
localDev?: boolean;
|
|
13
|
+
localDevPassword?: string;
|
|
14
|
+
localDevPort?: number;
|
|
15
|
+
linkableName?: string;
|
|
16
|
+
removalPolicy?: 'retain' | 'destroy';
|
|
17
|
+
rotationToken?: string;
|
|
18
|
+
}
|
|
19
|
+
export interface ProvisionLogicalDatabaseResult {
|
|
20
|
+
db: any;
|
|
21
|
+
logicalDb?: any;
|
|
22
|
+
readwriteSecretArn?: any;
|
|
23
|
+
readonlySecretArn?: any;
|
|
24
|
+
}
|
|
25
|
+
export declare function defaultDatabaseLinkableName(slice: string, database: string): string;
|
|
26
|
+
export declare function provisionLogicalDatabase(foundation: FoundationInfrastructure, options: ProvisionLogicalDatabaseOptions): ProvisionLogicalDatabaseResult;
|
|
@@ -0,0 +1,162 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.defaultDatabaseLinkableName = defaultDatabaseLinkableName;
|
|
4
|
+
exports.provisionLogicalDatabase = provisionLogicalDatabase;
|
|
5
|
+
const aurora_logical_database_js_1 = require("./aurora-logical-database.js");
|
|
6
|
+
const local_database_contract_js_1 = require("./local-database-contract.js");
|
|
7
|
+
function classNameForDatabaseComponent(value) {
|
|
8
|
+
// 'example-primary' -> 'ExamplePrimary'. Simple normalizer; the db
|
|
9
|
+
// generator always passes already-kebab-cased segments.
|
|
10
|
+
return value
|
|
11
|
+
.split(/[-_]/)
|
|
12
|
+
.filter(Boolean)
|
|
13
|
+
.map((p) => p.charAt(0).toUpperCase() + p.slice(1))
|
|
14
|
+
.join('');
|
|
15
|
+
}
|
|
16
|
+
function defaultDatabaseLinkableName(slice, database) {
|
|
17
|
+
return `${classNameForDatabaseComponent(slice)}${classNameForDatabaseComponent(database)}Database`;
|
|
18
|
+
}
|
|
19
|
+
// Carves out an app-scoped logical database on the shared `CoreDb` Aurora
|
|
20
|
+
// cluster. Creates:
|
|
21
|
+
// * `<app>_<database>` logical Postgres database on the shared cluster
|
|
22
|
+
// * `<app>_readwrite` role (full DML + DDL) + `<app>_readonly` role (SELECT only)
|
|
23
|
+
// * AWS Secrets Manager secrets for each role at
|
|
24
|
+
// `ebk/<stage>/<app>/db/<role>` with JSON `{ host, port, database, username, password }`
|
|
25
|
+
// * An `sst.Linkable` exposing the readwrite credentials — consumers link
|
|
26
|
+
// this into their Nextjs / Service / Function stacks so runtime code sees
|
|
27
|
+
// `Resource.<Linkable>.host/port/database/username/password` unchanged
|
|
28
|
+
//
|
|
29
|
+
// Passwords are generated inside the `AuroraLogicalDb` dynamic resource via
|
|
30
|
+
// Node `crypto.randomBytes` and persisted in Pulumi state, so no
|
|
31
|
+
// `@pulumi/random` dep is needed. They are never rotated automatically —
|
|
32
|
+
// change `rotationToken` to rotate on the next deploy (see the rotation
|
|
33
|
+
// runbook in this package's README).
|
|
34
|
+
//
|
|
35
|
+
// DO NOT pass `core.db.cluster` (the raw Aurora handle) into
|
|
36
|
+
// `new sst.aws.Nextjs({ link })` — that leaks the master password. This
|
|
37
|
+
// helper is the sanctioned consumer path.
|
|
38
|
+
function provisionLogicalDatabase(foundation, options) {
|
|
39
|
+
// Resolve and validate every deployed and local PostgreSQL identifier before
|
|
40
|
+
// constructing an SST Linkable, Pulumi dynamic resource, or AWS secret.
|
|
41
|
+
// PostgreSQL truncates overlong identifiers by default; EBK fails instead so
|
|
42
|
+
// two declarations can never alias silently.
|
|
43
|
+
const identifiers = (0, local_database_contract_js_1.resolveLogicalDatabaseIdentifiers)({
|
|
44
|
+
database: options.database,
|
|
45
|
+
slice: options.slice,
|
|
46
|
+
stage: $app.stage,
|
|
47
|
+
});
|
|
48
|
+
const linkableName = options.linkableName ??
|
|
49
|
+
defaultDatabaseLinkableName(options.slice, options.database);
|
|
50
|
+
// Local live mode needs only the workload-facing Linkable. Return before
|
|
51
|
+
// constructing the Pulumi dynamic resource or either Secrets Manager secret
|
|
52
|
+
// so `sst dev` does not provision unused AWS database resources merely to
|
|
53
|
+
// point the application at Docker Postgres.
|
|
54
|
+
if ($dev && (options.localDev ?? true)) {
|
|
55
|
+
const localDatabase = (0, local_database_contract_js_1.resolveLocalDatabaseContract)({
|
|
56
|
+
database: options.database,
|
|
57
|
+
password: options.localDevPassword,
|
|
58
|
+
port: options.localDevPort,
|
|
59
|
+
slice: options.slice,
|
|
60
|
+
});
|
|
61
|
+
return {
|
|
62
|
+
db: new sst.Linkable(linkableName, {
|
|
63
|
+
properties: localDatabase,
|
|
64
|
+
}),
|
|
65
|
+
};
|
|
66
|
+
}
|
|
67
|
+
// `<consumer_stage>_<app>_<database>` — scoped by the CONSUMER stage, not
|
|
68
|
+
// core's. Personal/preview stages (`pr-123`, `lukas`) share the shared
|
|
69
|
+
// development cluster via `EBK_CORE_STAGE=development` for cost, but their
|
|
70
|
+
// data MUST be isolated from every other stage's. Without stage-scoping, two stages
|
|
71
|
+
// pointing at the same core would stomp on each other's database rows and
|
|
72
|
+
// rotate each other's passwords via the retained-role `ALTER ROLE` path.
|
|
73
|
+
// Hyphens become underscores because Postgres identifiers reject `-`.
|
|
74
|
+
const databaseIdentifier = identifiers.database;
|
|
75
|
+
const readwriteRole = identifiers.readwriteRole;
|
|
76
|
+
const readonlyRole = identifiers.readonlyRole;
|
|
77
|
+
// Default removal policy depends on stage. Canonical persistent stages
|
|
78
|
+
// (development/staging/production) retain data — destroying a consumer stack
|
|
79
|
+
// shouldn't nuke anything anyone cares about. Ephemeral stages (preview
|
|
80
|
+
// `pr-123`, personal `lukas`, etc.) destroy — every such stage creates
|
|
81
|
+
// its own stage-scoped logical DB, and leaving it behind after the
|
|
82
|
+
// preview is torn down would leak Aurora state + roles forever.
|
|
83
|
+
// Callers can override explicitly via `options.removalPolicy`.
|
|
84
|
+
const canonicalStages = new Set(['development', 'staging', 'production']);
|
|
85
|
+
const defaultRemovalPolicy = canonicalStages.has($app.stage)
|
|
86
|
+
? 'retain'
|
|
87
|
+
: 'destroy';
|
|
88
|
+
const logicalDb = (0, aurora_logical_database_js_1.createAuroraLogicalDbResource)({
|
|
89
|
+
name: linkableName,
|
|
90
|
+
args: {
|
|
91
|
+
clusterArn: foundation.database.clusterArn,
|
|
92
|
+
masterSecretArn: foundation.database.masterSecretArn,
|
|
93
|
+
database: databaseIdentifier,
|
|
94
|
+
readwriteRole,
|
|
95
|
+
readonlyRole,
|
|
96
|
+
removalPolicy: options.removalPolicy ?? defaultRemovalPolicy,
|
|
97
|
+
// Only include the rotation trigger when the caller set one — keeping
|
|
98
|
+
// the key out of the inputs entirely when unset avoids a spurious
|
|
99
|
+
// `undefined` diff against resources created before this option existed.
|
|
100
|
+
...(options.rotationToken !== undefined
|
|
101
|
+
? { rotationToken: options.rotationToken }
|
|
102
|
+
: {}),
|
|
103
|
+
},
|
|
104
|
+
});
|
|
105
|
+
// `core.db.cluster.host` auto-resolves to the proxy endpoint when proxy is
|
|
106
|
+
// enabled (production) or the cluster writer endpoint otherwise.
|
|
107
|
+
// `core.db.cluster.port` similarly resolves to either the proxy port or the
|
|
108
|
+
// cluster port.
|
|
109
|
+
const host = foundation.database.cluster.host;
|
|
110
|
+
const port = foundation.database.cluster.port;
|
|
111
|
+
// Outputs from the dynamic resource — Pulumi unwraps them on link.
|
|
112
|
+
const readwritePassword = logicalDb.readwritePassword;
|
|
113
|
+
const readonlyPassword = logicalDb.readonlyPassword;
|
|
114
|
+
const secretJsonFor = (role, password) => $interpolate `{"host":"${host}","port":${port},"database":"${databaseIdentifier}","username":"${role}","password":"${password}"}`;
|
|
115
|
+
// Secret paths are keyed by the CONSUMER's stage, not core's. Two stages
|
|
116
|
+
// pointing at the same core via `EBK_CORE_STAGE` (e.g. `pr-123` → `development`)
|
|
117
|
+
// would otherwise collide on `ebk/development/<app>/db/<db>/...`. Keying by
|
|
118
|
+
// `$app.stage` isolates each consumer's secret namespace while the actual
|
|
119
|
+
// cluster remains shared.
|
|
120
|
+
const secretBasePath = `ebk/${$app.stage}/${options.slice}/database/${options.database}`;
|
|
121
|
+
// `recoveryWindowInDays: 0` skips the default 7-day soft-delete window.
|
|
122
|
+
// Destroy frees the secret name immediately so a subsequent create (or a
|
|
123
|
+
// redeploy after `sst remove`) doesn't hit `InvalidRequestException:
|
|
124
|
+
// ...already scheduled for deletion`. App-scoped DB role credentials are
|
|
125
|
+
// regenerated on every create() anyway — a recovery window serves no
|
|
126
|
+
// purpose here.
|
|
127
|
+
const readwriteSecret = new aws.secretsmanager.Secret(`${linkableName}ReadwriteSecret`, {
|
|
128
|
+
name: `${secretBasePath}/readwrite`,
|
|
129
|
+
recoveryWindowInDays: 0,
|
|
130
|
+
}, { dependsOn: logicalDb });
|
|
131
|
+
const readwriteSecretVersion = new aws.secretsmanager.SecretVersion(`${linkableName}ReadwriteSecretVersion`, {
|
|
132
|
+
secretId: readwriteSecret.id,
|
|
133
|
+
secretString: secretJsonFor(readwriteRole, readwritePassword),
|
|
134
|
+
});
|
|
135
|
+
const readonlySecret = new aws.secretsmanager.Secret(`${linkableName}ReadonlySecret`, {
|
|
136
|
+
name: `${secretBasePath}/readonly`,
|
|
137
|
+
recoveryWindowInDays: 0,
|
|
138
|
+
}, { dependsOn: logicalDb });
|
|
139
|
+
const readonlySecretVersion = new aws.secretsmanager.SecretVersion(`${linkableName}ReadonlySecretVersion`, {
|
|
140
|
+
secretId: readonlySecret.id,
|
|
141
|
+
secretString: secretJsonFor(readonlyRole, readonlyPassword),
|
|
142
|
+
});
|
|
143
|
+
const linkable = new sst.Linkable(linkableName, {
|
|
144
|
+
properties: {
|
|
145
|
+
host,
|
|
146
|
+
port,
|
|
147
|
+
database: databaseIdentifier,
|
|
148
|
+
username: readwriteRole,
|
|
149
|
+
password: $util.secret(readwritePassword),
|
|
150
|
+
},
|
|
151
|
+
});
|
|
152
|
+
// Touch the version refs so Pulumi tracks them + keep them alive in GC.
|
|
153
|
+
void readwriteSecretVersion;
|
|
154
|
+
void readonlySecretVersion;
|
|
155
|
+
return {
|
|
156
|
+
db: linkable,
|
|
157
|
+
logicalDb,
|
|
158
|
+
readwriteSecretArn: readwriteSecret.arn,
|
|
159
|
+
readonlySecretArn: readonlySecret.arn,
|
|
160
|
+
};
|
|
161
|
+
}
|
|
162
|
+
//# sourceMappingURL=provision-logical-database.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"provision-logical-database.js","sourceRoot":"","sources":["../../../../../packages/nx/src/foundation/provision-logical-database.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import { type ValidationResult } from '../validation.js';
|
|
2
|
+
export declare const STANDARD_FOUNDATION_CONTRACT_VERSION: 1;
|
|
3
|
+
export declare const STANDARD_FOUNDATION_CAPABILITIES: readonly ["network", "routing", "container-compute", "postgres", "identity", "events", "observability", "configuration", "deployment"];
|
|
4
|
+
export type StandardFoundationCapability = (typeof STANDARD_FOUNDATION_CAPABILITIES)[number];
|
|
5
|
+
export interface FoundationRequirement {
|
|
6
|
+
capabilities: StandardFoundationCapability[];
|
|
7
|
+
contract: string;
|
|
8
|
+
}
|
|
9
|
+
export interface FoundationDescriptor {
|
|
10
|
+
capabilities: StandardFoundationCapability[];
|
|
11
|
+
contractVersion: string;
|
|
12
|
+
}
|
|
13
|
+
export declare function isStandardFoundationCapability(value: unknown): value is StandardFoundationCapability;
|
|
14
|
+
export declare function validateFoundationRequirement(value: unknown, path?: string): ValidationResult<FoundationRequirement>;
|
|
15
|
+
export declare function validateFoundationCompatibility(requirement: unknown, foundation: unknown): ValidationResult<FoundationDescriptor>;
|
|
16
|
+
export declare const foundationRequirementSchema: {
|
|
17
|
+
readonly $id: "https://empirebuilderkit.dev/schemas/foundation-requirement-v1.json";
|
|
18
|
+
readonly $schema: "https://json-schema.org/draft/2020-12/schema";
|
|
19
|
+
readonly additionalProperties: false;
|
|
20
|
+
readonly properties: {
|
|
21
|
+
readonly capabilities: {
|
|
22
|
+
readonly items: {
|
|
23
|
+
readonly enum: readonly ["network", "routing", "container-compute", "postgres", "identity", "events", "observability", "configuration", "deployment"];
|
|
24
|
+
readonly type: "string";
|
|
25
|
+
};
|
|
26
|
+
readonly type: "array";
|
|
27
|
+
readonly uniqueItems: true;
|
|
28
|
+
};
|
|
29
|
+
readonly contract: {
|
|
30
|
+
readonly minLength: 1;
|
|
31
|
+
readonly type: "string";
|
|
32
|
+
};
|
|
33
|
+
};
|
|
34
|
+
readonly required: readonly ["contract", "capabilities"];
|
|
35
|
+
readonly title: "Empire Builder Kit Standard Foundation Requirement v1";
|
|
36
|
+
readonly type: "object";
|
|
37
|
+
};
|