@chaim-tools/cdk-lib 0.1.0
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 +238 -0
- package/lib/binders/base-chaim-binder.d.ts +144 -0
- package/lib/binders/base-chaim-binder.js +532 -0
- package/lib/binders/chaim-dynamodb-binder.d.ts +95 -0
- package/lib/binders/chaim-dynamodb-binder.js +292 -0
- package/lib/config/chaim-endpoints.d.ts +47 -0
- package/lib/config/chaim-endpoints.js +51 -0
- package/lib/index.d.ts +15 -0
- package/lib/index.js +43 -0
- package/lib/lambda-handler/.test-temp/snapshot.json +1 -0
- package/lib/lambda-handler/handler.js +513 -0
- package/lib/lambda-handler/handler.test.ts +365 -0
- package/lib/lambda-handler/package-lock.json +1223 -0
- package/lib/lambda-handler/package.json +14 -0
- package/lib/services/ingestion-service.d.ts +50 -0
- package/lib/services/ingestion-service.js +81 -0
- package/lib/services/os-cache-paths.d.ts +52 -0
- package/lib/services/os-cache-paths.js +123 -0
- package/lib/services/schema-service.d.ts +11 -0
- package/lib/services/schema-service.js +67 -0
- package/lib/services/snapshot-cleanup.d.ts +78 -0
- package/lib/services/snapshot-cleanup.js +220 -0
- package/lib/types/base-binder-props.d.ts +32 -0
- package/lib/types/base-binder-props.js +17 -0
- package/lib/types/credentials.d.ts +57 -0
- package/lib/types/credentials.js +83 -0
- package/lib/types/data-store-metadata.d.ts +67 -0
- package/lib/types/data-store-metadata.js +4 -0
- package/lib/types/failure-mode.d.ts +16 -0
- package/lib/types/failure-mode.js +21 -0
- package/lib/types/ingest-contract.d.ts +110 -0
- package/lib/types/ingest-contract.js +12 -0
- package/lib/types/snapshot-cache-policy.d.ts +52 -0
- package/lib/types/snapshot-cache-policy.js +57 -0
- package/lib/types/snapshot-payload.d.ts +245 -0
- package/lib/types/snapshot-payload.js +3 -0
- package/lib/types/table-binding-config.d.ts +43 -0
- package/lib/types/table-binding-config.js +57 -0
- package/package.json +67 -0
|
@@ -0,0 +1,220 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || function (mod) {
|
|
19
|
+
if (mod && mod.__esModule) return mod;
|
|
20
|
+
var result = {};
|
|
21
|
+
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
|
|
22
|
+
__setModuleDefault(result, mod);
|
|
23
|
+
return result;
|
|
24
|
+
};
|
|
25
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
26
|
+
exports.pruneOldSnapshots = exports.pruneStackSnapshots = void 0;
|
|
27
|
+
const fs = __importStar(require("fs"));
|
|
28
|
+
const path = __importStar(require("path"));
|
|
29
|
+
const os_cache_paths_1 = require("./os-cache-paths");
|
|
30
|
+
/**
|
|
31
|
+
* Delete all snapshots for a specific stack.
|
|
32
|
+
*
|
|
33
|
+
* This is the PRUNE_STACK behavior - scoped to a single stack only.
|
|
34
|
+
* Deletes: ~/.chaim/cache/snapshots/aws/{account}/{region}/{stackName}/
|
|
35
|
+
*
|
|
36
|
+
* @param options - Cleanup options
|
|
37
|
+
* @returns Cleanup result summary
|
|
38
|
+
*/
|
|
39
|
+
function pruneStackSnapshots(options) {
|
|
40
|
+
const { stackName, verbose = false } = options;
|
|
41
|
+
const result = {
|
|
42
|
+
deletedCount: 0,
|
|
43
|
+
skippedCount: 0,
|
|
44
|
+
deletedPaths: [],
|
|
45
|
+
errors: [],
|
|
46
|
+
};
|
|
47
|
+
if (!stackName) {
|
|
48
|
+
result.errors.push('stackName is required for pruneStackSnapshots');
|
|
49
|
+
return result;
|
|
50
|
+
}
|
|
51
|
+
const accountId = (0, os_cache_paths_1.normalizeAccountId)(options.accountId);
|
|
52
|
+
const region = (0, os_cache_paths_1.normalizeRegion)(options.region);
|
|
53
|
+
const stackDir = path.join((0, os_cache_paths_1.getSnapshotBaseDir)(), 'aws', accountId, region, stackName);
|
|
54
|
+
if (!fs.existsSync(stackDir)) {
|
|
55
|
+
if (verbose) {
|
|
56
|
+
console.log(`[Chaim] No snapshots found for stack: ${stackName}`);
|
|
57
|
+
}
|
|
58
|
+
return result;
|
|
59
|
+
}
|
|
60
|
+
if (verbose) {
|
|
61
|
+
console.log(`[Chaim] Pruning snapshots for stack: ${stackName}`);
|
|
62
|
+
console.log(`[Chaim] Path: ${stackDir}`);
|
|
63
|
+
}
|
|
64
|
+
try {
|
|
65
|
+
// Recursively delete stack directory
|
|
66
|
+
const snapshotFiles = collectSnapshotFiles(stackDir);
|
|
67
|
+
for (const filePath of snapshotFiles) {
|
|
68
|
+
try {
|
|
69
|
+
fs.unlinkSync(filePath);
|
|
70
|
+
result.deletedCount++;
|
|
71
|
+
result.deletedPaths.push(filePath);
|
|
72
|
+
if (verbose) {
|
|
73
|
+
console.log(`[Chaim] Deleted: ${path.relative(stackDir, filePath)}`);
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
catch (error) {
|
|
77
|
+
result.errors.push(`Failed to delete ${filePath}: ${error}`);
|
|
78
|
+
result.skippedCount++;
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
// Clean up empty directories
|
|
82
|
+
cleanEmptyDirectories(stackDir);
|
|
83
|
+
if (verbose) {
|
|
84
|
+
console.log(`[Chaim] Deleted ${result.deletedCount} snapshot(s)`);
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
catch (error) {
|
|
88
|
+
result.errors.push(`Failed to prune stack snapshots: ${error}`);
|
|
89
|
+
}
|
|
90
|
+
return result;
|
|
91
|
+
}
|
|
92
|
+
exports.pruneStackSnapshots = pruneStackSnapshots;
|
|
93
|
+
/**
|
|
94
|
+
* Delete snapshots older than a specified age (TTL cleanup).
|
|
95
|
+
*
|
|
96
|
+
* This is a maintenance operation that can be run periodically
|
|
97
|
+
* to clean up very old snapshots across all stacks.
|
|
98
|
+
*
|
|
99
|
+
* @param options - TTL cleanup options
|
|
100
|
+
* @returns Cleanup result summary
|
|
101
|
+
*/
|
|
102
|
+
function pruneOldSnapshots(options = {}) {
|
|
103
|
+
const { olderThanDays = 30, dryRun = false, verbose = false, } = options;
|
|
104
|
+
const result = {
|
|
105
|
+
deletedCount: 0,
|
|
106
|
+
skippedCount: 0,
|
|
107
|
+
deletedPaths: [],
|
|
108
|
+
errors: [],
|
|
109
|
+
};
|
|
110
|
+
const baseDir = (0, os_cache_paths_1.getSnapshotBaseDir)();
|
|
111
|
+
const now = Date.now();
|
|
112
|
+
const cutoffMs = olderThanDays * 24 * 60 * 60 * 1000;
|
|
113
|
+
if (verbose) {
|
|
114
|
+
console.log(`[Chaim] Scanning for snapshots older than ${olderThanDays} days...`);
|
|
115
|
+
console.log(`[Chaim] Base directory: ${baseDir}`);
|
|
116
|
+
if (dryRun) {
|
|
117
|
+
console.log(`[Chaim] DRY RUN - no files will be deleted`);
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
if (!fs.existsSync(baseDir)) {
|
|
121
|
+
if (verbose) {
|
|
122
|
+
console.log(`[Chaim] Snapshot directory does not exist: ${baseDir}`);
|
|
123
|
+
}
|
|
124
|
+
return result;
|
|
125
|
+
}
|
|
126
|
+
try {
|
|
127
|
+
const allSnapshots = collectSnapshotFiles(baseDir);
|
|
128
|
+
for (const filePath of allSnapshots) {
|
|
129
|
+
try {
|
|
130
|
+
const stats = fs.statSync(filePath);
|
|
131
|
+
const ageMs = now - stats.mtimeMs;
|
|
132
|
+
if (ageMs > cutoffMs) {
|
|
133
|
+
const ageDays = Math.floor(ageMs / (24 * 60 * 60 * 1000));
|
|
134
|
+
if (dryRun) {
|
|
135
|
+
result.skippedCount++;
|
|
136
|
+
if (verbose) {
|
|
137
|
+
console.log(`[Chaim] Would delete (${ageDays} days old): ${filePath}`);
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
else {
|
|
141
|
+
fs.unlinkSync(filePath);
|
|
142
|
+
result.deletedCount++;
|
|
143
|
+
result.deletedPaths.push(filePath);
|
|
144
|
+
if (verbose) {
|
|
145
|
+
console.log(`[Chaim] Deleted (${ageDays} days old): ${filePath}`);
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
catch (error) {
|
|
151
|
+
result.errors.push(`Failed to process ${filePath}: ${error}`);
|
|
152
|
+
result.skippedCount++;
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
// Clean up empty directories (only if not dry run)
|
|
156
|
+
if (!dryRun) {
|
|
157
|
+
cleanEmptyDirectories(baseDir);
|
|
158
|
+
}
|
|
159
|
+
if (verbose) {
|
|
160
|
+
if (dryRun) {
|
|
161
|
+
console.log(`[Chaim] Would delete ${result.skippedCount} snapshot(s)`);
|
|
162
|
+
}
|
|
163
|
+
else {
|
|
164
|
+
console.log(`[Chaim] Deleted ${result.deletedCount} snapshot(s)`);
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
catch (error) {
|
|
169
|
+
result.errors.push(`Failed to prune old snapshots: ${error}`);
|
|
170
|
+
}
|
|
171
|
+
return result;
|
|
172
|
+
}
|
|
173
|
+
exports.pruneOldSnapshots = pruneOldSnapshots;
|
|
174
|
+
/**
|
|
175
|
+
* Recursively collect all .json snapshot files in a directory.
|
|
176
|
+
*/
|
|
177
|
+
function collectSnapshotFiles(dir) {
|
|
178
|
+
const files = [];
|
|
179
|
+
if (!fs.existsSync(dir)) {
|
|
180
|
+
return files;
|
|
181
|
+
}
|
|
182
|
+
const entries = fs.readdirSync(dir, { withFileTypes: true });
|
|
183
|
+
for (const entry of entries) {
|
|
184
|
+
const fullPath = path.join(dir, entry.name);
|
|
185
|
+
if (entry.isDirectory()) {
|
|
186
|
+
files.push(...collectSnapshotFiles(fullPath));
|
|
187
|
+
}
|
|
188
|
+
else if (entry.isFile() && entry.name.endsWith('.json')) {
|
|
189
|
+
files.push(fullPath);
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
return files;
|
|
193
|
+
}
|
|
194
|
+
/**
|
|
195
|
+
* Recursively remove empty directories.
|
|
196
|
+
*/
|
|
197
|
+
function cleanEmptyDirectories(dir) {
|
|
198
|
+
if (!fs.existsSync(dir)) {
|
|
199
|
+
return;
|
|
200
|
+
}
|
|
201
|
+
const entries = fs.readdirSync(dir, { withFileTypes: true });
|
|
202
|
+
// First, recursively clean subdirectories
|
|
203
|
+
for (const entry of entries) {
|
|
204
|
+
if (entry.isDirectory()) {
|
|
205
|
+
const fullPath = path.join(dir, entry.name);
|
|
206
|
+
cleanEmptyDirectories(fullPath);
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
// Now check if directory is empty and remove it
|
|
210
|
+
const remainingEntries = fs.readdirSync(dir);
|
|
211
|
+
if (remainingEntries.length === 0) {
|
|
212
|
+
try {
|
|
213
|
+
fs.rmdirSync(dir);
|
|
214
|
+
}
|
|
215
|
+
catch {
|
|
216
|
+
// Ignore errors (directory might not be empty or might be in use)
|
|
217
|
+
}
|
|
218
|
+
}
|
|
219
|
+
}
|
|
220
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic25hcHNob3QtY2xlYW51cC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9zZXJ2aWNlcy9zbmFwc2hvdC1jbGVhbnVwLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7O0FBQUEsdUNBQXlCO0FBQ3pCLDJDQUE2QjtBQUM3QixxREFBMkY7QUF1RTNGOzs7Ozs7OztHQVFHO0FBQ0gsU0FBZ0IsbUJBQW1CLENBQUMsT0FBdUI7SUFDekQsTUFBTSxFQUFFLFNBQVMsRUFBRSxPQUFPLEdBQUcsS0FBSyxFQUFFLEdBQUcsT0FBTyxDQUFDO0lBQy9DLE1BQU0sTUFBTSxHQUFrQjtRQUM1QixZQUFZLEVBQUUsQ0FBQztRQUNmLFlBQVksRUFBRSxDQUFDO1FBQ2YsWUFBWSxFQUFFLEVBQUU7UUFDaEIsTUFBTSxFQUFFLEVBQUU7S0FDWCxDQUFDO0lBRUYsSUFBSSxDQUFDLFNBQVMsRUFBRTtRQUNkLE1BQU0sQ0FBQyxNQUFNLENBQUMsSUFBSSxDQUFDLCtDQUErQyxDQUFDLENBQUM7UUFDcEUsT0FBTyxNQUFNLENBQUM7S0FDZjtJQUVELE1BQU0sU0FBUyxHQUFHLElBQUEsbUNBQWtCLEVBQUMsT0FBTyxDQUFDLFNBQVMsQ0FBQyxDQUFDO0lBQ3hELE1BQU0sTUFBTSxHQUFHLElBQUEsZ0NBQWUsRUFBQyxPQUFPLENBQUMsTUFBTSxDQUFDLENBQUM7SUFFL0MsTUFBTSxRQUFRLEdBQUcsSUFBSSxDQUFDLElBQUksQ0FDeEIsSUFBQSxtQ0FBa0IsR0FBRSxFQUNwQixLQUFLLEVBQ0wsU0FBUyxFQUNULE1BQU0sRUFDTixTQUFTLENBQ1YsQ0FBQztJQUVGLElBQUksQ0FBQyxFQUFFLENBQUMsVUFBVSxDQUFDLFFBQVEsQ0FBQyxFQUFFO1FBQzVCLElBQUksT0FBTyxFQUFFO1lBQ1gsT0FBTyxDQUFDLEdBQUcsQ0FBQyx5Q0FBeUMsU0FBUyxFQUFFLENBQUMsQ0FBQztTQUNuRTtRQUNELE9BQU8sTUFB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QixDQUFDLEdBQVc7SUFDeEMsSUFBSSxDQUFDLEVBQUUsQ0FBQyxVQUFVLENBQUMsR0FBRyxDQUFDLEVBQUU7UUFDdkIsT0FBTztLQUNSO0lBRUQsTUFBTSxPQUFPLEdBQUcsRUFBRSxDQUFDLFdBQVcsQ0FBQyxHQUFHLEVBQUUsRUFBRSxhQUFhLEVBQUUsSUFBSSxFQUFFLENBQUMsQ0FBQztJQUU3RCwwQ0FBMEM7SUFDMUMsS0FBSyxNQUFNLEtBQUssSUFBSSxPQUFPLEVBQUU7UUFDM0IsSUFBSSxLQUFLLENBQUMsV0FBVyxFQUFFLEVBQUU7WUFDdkIsTUFBTSxRQUFRLEdBQUcsSUFBSSxDQUFDLElBQUksQ0FBQyxHQUFHLEVBQUUsS0FBSyxDQUFDLElBQUksQ0FBQyxDQUFDO1lBQzVDLHFCQUFxQixDQUFDLFFBQVEsQ0FBQyxDQUFDO1NBQ2pDO0tBQ0Y7SUFFRCxnREFBZ0Q7SUFDaEQsTUFBTSxnQkFBZ0IsR0FBRyxFQUFFLENBQUMsV0FBVyxDQUFDLEdBQUcsQ0FBQyxDQUFDO0lBQzdDLElBQUksZ0JBQWdCLENBQUMsTUFBTSxLQUFLLENBQUMsRUFBRTtRQUNqQyxJQUFJO1lBQ0YsRUFBRSxDQUFDLFNBQVMsQ0FBQyxHQUFHLENBQUMsQ0FBQztTQUNuQjtRQUFDLE1BQU07WUFDTixrRUFBa0U7U0FDbkU7S0FDRjtBQUNILENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgKiBhcyBmcyBmcm9tICdmcyc7XG5pbXBvcnQgKiBhcyBwYXRoIGZyb20gJ3BhdGgnO1xuaW1wb3J0IHsgZ2V0U25hcHNob3RCYXNlRGlyLCBub3JtYWxpemVBY2NvdW50SWQsIG5vcm1hbGl6ZVJlZ2lvbiB9IGZyb20gJy4vb3MtY2FjaGUtcGF0aHMnO1xuXG4vKipcbiAqIE9wdGlvbnMgZm9yIHNuYXBzaG90IGNsZWFudXAgb3BlcmF0aW9ucy5cbiAqL1xuZXhwb3J0IGludGVyZmFjZSBDbGVhbnVwT3B0aW9ucyB7XG4gIC8qKlxuICAgKiBBV1MgYWNjb3VudCBJRCB0byBzY29wZSBjbGVhbnVwLlxuICAgKiBJZiB1bmRlZmluZWQsIG9wZXJhdGVzIG9uICd1bmtub3duJyBhY2NvdW50IChmb3IgbG9jYWwgZGV2KS5cbiAgICovXG4gIGFjY291bnRJZD86IHN0cmluZztcblxuICAvKipcbiAgICogQVdTIHJlZ2lvbiB0byBzY29wZSBjbGVhbnVwLlxuICAgKiBJZiB1bmRlZmluZWQsIG9wZXJhdGVzIG9uICd1bmtub3duJyByZWdpb24gKGZvciBsb2NhbCBkZXYpLlxuICAgKi9cbiAgcmVnaW9uPzogc3RyaW5nO1xuXG4gIC8qKlxuICAgKiBDREsgc3RhY2sgbmFtZSB0byBzY29wZSBjbGVhbnVwLlxuICAgKiBSRVFVSVJFRCBmb3IgUFJVTkVfU1RBQ0sgb3BlcmF0aW9ucy5cbiAgICovXG4gIHN0YWNrTmFtZTogc3RyaW5nO1xuXG4gIC8qKlxuICAgKiBJZiB0cnVlLCBsb2cgY2xlYW51cCBvcGVyYXRpb25zIHRvIGNvbnNvbGUuXG4gICAqIERlZmF1bHQ6IGZhbHNlXG4gICAqL1xuICB2ZXJib3NlPzogYm9vbGVhbjtcbn1cblxuLyoqXG4gKiBPcHRpb25zIGZvciBUVEwtYmFzZWQgY2xlYW51cC5cbiAqL1xuZXhwb3J0IGludGVyZmFjZSBUVExDbGVhbnVwT3B0aW9ucyB7XG4gIC8qKlxuICAgKiBEZWxldGUgc25hcHNob3RzIG9sZGVyIHRoYW4gdGhpcyBtYW55IGRheXMuXG4gICAqIERlZmF1bHQ6IDMwIGRheXNcbiAgICovXG4gIG9sZGVyVGhhbkRheXM/OiBudW1iZXI7XG5cbiAgLyoqXG4gICAqIElmIHRydWUsIHBlcmZvcm0gYSBkcnkgcnVuIHdpdGhvdXQgZGVsZXRpbmcgZmlsZXMuXG4gICAqIERlZmF1bHQ6IGZhbHNlXG4gICAqL1xuICBkcnlSdW4/OiBib29sZWFuO1xuXG4gIC8qKlxuICAgKiBJZiB0cnVlLCBsb2cgY2xlYW51cCBvcGVyYXRpb25zIHRvIGNvbnNvbGUuXG4gICAqIERlZmF1bHQ6IGZhbHNlXG4gICAqL1xuICB2ZXJib3NlPzogYm9vbGVhbjtcbn1cblxuLyoqXG4gKiBSZXN1bHQgb2YgYSBjbGVhbnVwIG9wZXJhdGlvbi5cbiAqL1xuZXhwb3J0IGludGVyZmFjZSBDbGVhbnVwUmVzdWx0IHtcbiAgLyoqIE51bWJlciBvZiBzbmFwc2hvdHMgZGVsZXRlZCAqL1xuICBkZWxldGVkQ291bnQ6IG51bWJlcjtcblxuICAvKiogTnVtYmVyIG9mIHNuYXBzaG90cyBmb3VuZCBidXQgbm90IGRlbGV0ZWQgKGRyeSBydW4gb3IgZXJyb3JzKSAqL1xuICBza2lwcGVkQ291bnQ6IG51bWJlcjtcblxuICAvKiogUGF0aHMgb2YgZGVsZXRlZCBzbmFwc2hvdCBmaWxlcyAqL1xuICBkZWxldGVkUGF0aHM6IHN0cmluZ1tdO1xuXG4gIC8qKiBFcnJvcnMgZW5jb3VudGVyZWQgZHVyaW5nIGNsZWFudXAgKi9cbiAgZXJyb3JzOiBzdHJpbmdbXTtcbn1cblxuLyoqXG4gKiBEZWxldGUgYWxsIHNuYXBzaG90cyBmb3IgYSBzcGVjaWZpYyBzdGFjay5cbiAqIFxuICogVGhpcyBpcyB0aGUgUFJVTkVfU1RBQ0sgYmVoYXZpb3IgLSBzY29wZWQgdG8gYSBzaW5nbGUgc3RhY2sgb25seS5cbiAqIERlbGV0ZXM6IH4vLmNoYWltL2NhY2hlL3NuYXBzaG90cy9hd3Mve2FjY291bnR9L3tyZWdpb259L3tzdGFja05hbWV9L1xuICogXG4gKiBAcGFyYW0gb3B0aW9ucyAtIENsZWFudXAgb3B0aW9uc1xuICogQHJldHVybnMgQ2xlYW51cCByZXN1bHQgc3VtbWFyeVxuICovXG5leHBvcnQgZnVuY3Rpb24gcHJ1bmVTdGFja1NuYXBzaG90cyhvcHRpb25zOiBDbGVhbnVwT3B0aW9ucyk6IENsZWFudXBSZXN1bHQge1xuICBjb25zdCB7IHN0YWNrTmFtZSwgdmVyYm9zZSA9IGZhbHNlIH0gPSBvcHRpb25zO1xuICBjb25zdCByZXN1bHQ6IENsZWFudXBSZXN1bHQgPSB7XG4gICAgZGVsZXRlZENvdW50OiAwLFxuICAgIHNraXBwZWRDb3VudDogMCxcbiAgICBkZWxldGVkUGF0aHM6IFtdLFxuICAgIGVycm9yczogW10sXG4gIH07XG5cbiAgaWYgKCFzdGFja05hbWUpIHtcbiAgICByZXN1bHQuZXJyb3JzLnB1c2goJ3N0YWNrTmFtZSBpcyByZXF1aXJlZCBmb3IgcHJ1bmVTdGFja1NuYXBzaG90cycpO1xuICAgIHJldHVybiByZXN1bHQ7XG4gIH1cblxuICBjb25zdCBhY2NvdW50SWQgPSBub3JtYWxpemVBY2NvdW50SWQob3B0aW9ucy5hY2NvdW50SWQpO1xuICBjb25zdCByZWdpb24gPSBub3JtYWxpemVSZWdpb24ob3B0aW9ucy5yZWdpb24pO1xuXG4gIGNvbnN0IHN0YWNrRGlyID0gcGF0aC5qb2luKFxuICAgIGdldFNuYXBzaG90QmFzZURpcigpLFxuICAgICdhd3MnLFxuICAgIGFjY291bnRJZCxcbiAgICByZWdpb24sXG4gICAgc3RhY2tOYW1lXG4gICk7XG5cbiAgaWYgKCFmcy5leGlzdHNTeW5jKHN0YWNrRGlyKSkge1xuICAgIGlmICh2ZXJib3NlKSB7XG4gICAgICBjb25zb2xlLmxvZyhgW0NoYWltXSBObyBzbmFwc2hvdHMgZm91bmQgZm9yIHN0YWNrOiAke3N0YWNrTmFtZX1gKTtcbiAgICB9XG4gICAgcmV0dXJuIHJlc3VsdDtcbiAgfVxuXG4gIGlmICh2ZXJib3NlKSB7XG4gICAgY29uc29sZS5sb2coYFtDaGFpbV0gUHJ1bmluZyBzbmFwc2hvdHMgZm9yIHN0YWNrOiAke3N0YWNrTmFtZX1gKTtcbiAgICBjb25zb2xlLmxvZyhgW0NoYWltXSBQYXRoOiAke3N0YWNrRGlyfWApO1xuICB9XG5cbiAgdHJ5IHtcbiAgICAvLyBSZWN1cnNpdmVseSBkZWxldGUgc3RhY2sgZGlyZWN0b3J5XG4gICAgY29uc3Qgc25hcHNob3RGaWxlcyA9IGNvbGxlY3RTbmFwc2hvdEZpbGVzKHN0YWNrRGlyKTtcbiAgICBcbiAgICBmb3IgKGNvbnN0IGZpbGVQYXRoIG9mIHNuYXBzaG90RmlsZXMpIHtcbiAgICAgIHRyeSB7XG4gICAgICAgIGZzLnVubGlua1N5bmMoZmlsZVBhdGgpO1xuICAgICAgICByZXN1bHQuZGVsZXRlZENvdW50Kys7XG4gICAgICAgIHJlc3VsdC5kZWxldGVkUGF0aHMucHVzaChmaWxlUGF0aCk7XG4gICAgICAgIFxuICAgICAgICBpZiAodmVyYm9zZSkge1xuICAgICAgICAgIGNvbnNvbGUubG9nKGBbQ2hhaW1dICAgRGVsZXRlZDogJHtwYXRoLnJlbGF0aXZlKHN0YWNrRGlyLCBmaWxlUGF0aCl9YCk7XG4gICAgICAgIH1cbiAgICAgIH0gY2F0Y2ggKGVycm9yKSB7XG4gICAgICAgIHJlc3VsdC5lcnJvcnMucHVzaChgRmFpbGVkIHRvIGRlbGV0ZSAke2ZpbGVQYXRofTogJHtlcnJvcn1gKTtcbiAgICAgICAgcmVzdWx0LnNraXBwZWRDb3VudCsrO1xuICAgICAgfVxuICAgIH1cblxuICAgIC8vIENsZWFuIHVwIGVtcHR5IGRpcmVjdG9yaWVzXG4gICAgY2xlYW5FbXB0eURpcmVjdG9yaWVzKHN0YWNrRGlyKTtcblxuICAgIGlmICh2ZXJib3NlKSB7XG4gICAgICBjb25zb2xlLmxvZyhgW0NoYWltXSBEZWxldGVkICR7cmVzdWx0LmRlbGV0ZWRDb3VudH0gc25hcHNob3QocylgKTtcbiAgICB9XG4gIH0gY2F0Y2ggKGVycm9yKSB7XG4gICAgcmVzdWx0LmVycm9ycy5wdXNoKGBGYWlsZWQgdG8gcHJ1bmUgc3RhY2sgc25hcHNob3RzOiAke2Vycm9yfWApO1xuICB9XG5cbiAgcmV0dXJuIHJlc3VsdDtcbn1cblxuLyoqXG4gKiBEZWxldGUgc25hcHNob3RzIG9sZGVyIHRoYW4gYSBzcGVjaWZpZWQgYWdlIChUVEwgY2xlYW51cCkuXG4gKiBcbiAqIFRoaXMgaXMgYSBtYWludGVuYW5jZSBvcGVyYXRpb24gdGhhdCBjYW4gYmUgcnVuIHBlcmlvZGljYWxseVxuICogdG8gY2xlYW4gdXAgdmVyeSBvbGQgc25hcHNob3RzIGFjcm9zcyBhbGwgc3RhY2tzLlxuICogXG4gKiBAcGFyYW0gb3B0aW9ucyAtIFRUTCBjbGVhbnVwIG9wdGlvbnNcbiAqIEByZXR1cm5zIENsZWFudXAgcmVzdWx0IHN1bW1hcnlcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHBydW5lT2xkU25hcHNob3RzKG9wdGlvbnM6IFRUTENsZWFudXBPcHRpb25zID0ge30pOiBDbGVhbnVwUmVzdWx0IHtcbiAgY29uc3Qge1xuICAgIG9sZGVyVGhhbkRheXMgPSAzMCxcbiAgICBkcnlSdW4gPSBmYWxzZSxcbiAgICB2ZXJib3NlID0gZmFsc2UsXG4gIH0gPSBvcHRpb25zO1xuXG4gIGNvbnN0IHJlc3VsdDogQ2xlYW51cFJlc3VsdCA9IHtcbiAgICBkZWxldGVkQ291bnQ6IDAsXG4gICAgc2tpcHBlZENvdW50OiAwLFxuICAgIGRlbGV0ZWRQYXRoczogW10sXG4gICAgZXJyb3JzOiBbXSxcbiAgfTtcblxuICBjb25zdCBiYXNlRGlyID0gZ2V0U25hcHNob3RCYXNlRGlyKCk7XG4gIGNvbnN0IG5vdyA9IERhdGUubm93KCk7XG4gIGNvbnN0IGN1dG9mZk1zID0gb2xkZXJUaGFuRGF5cyAqIDI0ICogNjAgKiA2MCAqIDEwMDA7XG5cbiAgaWYgKHZlcmJvc2UpIHtcbiAgICBjb25zb2xlLmxvZyhgW0NoYWltXSBTY2FubmluZyBmb3Igc25hcHNob3RzIG9sZGVyIHRoYW4gJHtvbGRlclRoYW5EYXlzfSBkYXlzLi4uYCk7XG4gICAgY29uc29sZS5sb2coYFtDaGFpbV0gQmFzZSBkaXJlY3Rvcnk6ICR7YmFzZURpcn1gKTtcbiAgICBpZiAoZHJ5UnVuKSB7XG4gICAgICBjb25zb2xlLmxvZyhgW0NoYWltXSBEUlkgUlVOIC0gbm8gZmlsZXMgd2lsbCBiZSBkZWxldGVkYCk7XG4gICAgfVxuICB9XG5cbiAgaWYgKCFmcy5leGlzdHNTeW5jKGJhc2VEaXIpKSB7XG4gICAgaWYgKHZlcmJvc2UpIHtcbiAgICAgIGNvbnNvbGUubG9nKGBbQ2hhaW1dIFNuYXBzaG90IGRpcmVjdG9yeSBkb2VzIG5vdCBleGlzdDogJHtiYXNlRGlyfWApO1xuICAgIH1cbiAgICByZXR1cm4gcmVzdWx0O1xuICB9XG5cbiAgdHJ5IHtcbiAgICBjb25zdCBhbGxTbmFwc2hvdHMgPSBjb2xsZWN0U25hcHNob3RGaWxlcyhiYXNlRGlyKTtcblxuICAgIGZvciAoY29uc3QgZmlsZVBhdGggb2YgYWxsU25hcHNob3RzKSB7XG4gICAgICB0cnkge1xuICAgICAgICBjb25zdCBzdGF0cyA9IGZzLnN0YXRTeW5jKGZpbGVQYXRoKTtcbiAgICAgICAgY29uc3QgYWdlTXMgPSBub3cgLSBzdGF0cy5tdGltZU1zO1xuXG4gICAgICAgIGlmIChhZ2VNcyA+IGN1dG9mZk1zKSB7XG4gICAgICAgICAgY29uc3QgYWdlRGF5cyA9IE1hdGguZmxvb3IoYWdlTXMgLyAoMjQgKiA2MCAqIDYwICogMTAwMCkpO1xuICAgICAgICAgIFxuICAgICAgICAgIGlmIChkcnlSdW4pIHtcbiAgICAgICAgICAgIHJlc3VsdC5za2lwcGVkQ291bnQrKztcbiAgICAgICAgICAgIGlmICh2ZXJib3NlKSB7XG4gICAgICAgICAgICAgIGNvbnNvbGUubG9nKGBbQ2hhaW1dIFdvdWxkIGRlbGV0ZSAoJHthZ2VEYXlzfSBkYXlzIG9sZCk6ICR7ZmlsZVBhdGh9YCk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIGZzLnVubGlua1N5bmMoZmlsZVBhdGgpO1xuICAgICAgICAgICAgcmVzdWx0LmRlbGV0ZWRDb3VudCsrO1xuICAgICAgICAgICAgcmVzdWx0LmRlbGV0ZWRQYXRocy5wdXNoKGZpbGVQYXRoKTtcbiAgICAgICAgICAgIFxuICAgICAgICAgICAgaWYgKHZlcmJvc2UpIHtcbiAgICAgICAgICAgICAgY29uc29sZS5sb2coYFtDaGFpbV0gRGVsZXRlZCAoJHthZ2VEYXlzfSBkYXlzIG9sZCk6ICR7ZmlsZVBhdGh9YCk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICB9IGNhdGNoIChlcnJvcikge1xuICAgICAgICByZXN1bHQuZXJyb3JzLnB1c2goYEZhaWxlZCB0byBwcm9jZXNzICR7ZmlsZVBhdGh9OiAke2Vycm9yfWApO1xuICAgICAgICByZXN1bHQuc2tpcHBlZENvdW50Kys7XG4gICAgICB9XG4gICAgfVxuXG4gICAgLy8gQ2xlYW4gdXAgZW1wdHkgZGlyZWN0b3JpZXMgKG9ubHkgaWYgbm90IGRyeSBydW4pXG4gICAgaWYgKCFkcnlSdW4pIHtcbiAgICAgIGNsZWFuRW1wdHlEaXJlY3RvcmllcyhiYXNlRGlyKTtcbiAgICB9XG5cbiAgICBpZiAodmVyYm9zZSkge1xuICAgICAgaWYgKGRyeVJ1bikge1xuICAgICAgICBjb25zb2xlLmxvZyhgW0NoYWltXSBXb3VsZCBkZWxldGUgJHtyZXN1bHQuc2tpcHBlZENvdW50fSBzbmFwc2hvdChzKWApO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgY29uc29sZS5sb2coYFtDaGFpbV0gRGVsZXRlZCAke3Jlc3VsdC5kZWxldGVkQ291bnR9IHNuYXBzaG90KHMpYCk7XG4gICAgICB9XG4gICAgfVxuICB9IGNhdGNoIChlcnJvcikge1xuICAgIHJlc3VsdC5lcnJvcnMucHVzaChgRmFpbGVkIHRvIHBydW5lIG9sZCBzbmFwc2hvdHM6ICR7ZXJyb3J9YCk7XG4gIH1cblxuICByZXR1cm4gcmVzdWx0O1xufVxuXG4vKipcbiAqIFJlY3Vyc2l2ZWx5IGNvbGxlY3QgYWxsIC5qc29uIHNuYXBzaG90IGZpbGVzIGluIGEgZGlyZWN0b3J5LlxuICovXG5mdW5jdGlvbiBjb2xsZWN0U25hcHNob3RGaWxlcyhkaXI6IHN0cmluZyk6IHN0cmluZ1tdIHtcbiAgY29uc3QgZmlsZXM6IHN0cmluZ1tdID0gW107XG5cbiAgaWYgKCFmcy5leGlzdHNTeW5jKGRpcikpIHtcbiAgICByZXR1cm4gZmlsZXM7XG4gIH1cblxuICBjb25zdCBlbnRyaWVzID0gZnMucmVhZGRpclN5bmMoZGlyLCB7IHdpdGhGaWxlVHlwZXM6IHRydWUgfSk7XG5cbiAgZm9yIChjb25zdCBlbnRyeSBvZiBlbnRyaWVzKSB7XG4gICAgY29uc3QgZnVsbFBhdGggPSBwYXRoLmpvaW4oZGlyLCBlbnRyeS5uYW1lKTtcblxuICAgIGlmIChlbnRyeS5pc0RpcmVjdG9yeSgpKSB7XG4gICAgICBmaWxlcy5wdXNoKC4uLmNvbGxlY3RTbmFwc2hvdEZpbGVzKGZ1bGxQYXRoKSk7XG4gICAgfSBlbHNlIGlmIChlbnRyeS5pc0ZpbGUoKSAmJiBlbnRyeS5uYW1lLmVuZHNXaXRoKCcuanNvbicpKSB7XG4gICAgICBmaWxlcy5wdXNoKGZ1bGxQYXRoKTtcbiAgICB9XG4gIH1cblxuICByZXR1cm4gZmlsZXM7XG59XG5cbi8qKlxuICogUmVjdXJzaXZlbHkgcmVtb3ZlIGVtcHR5IGRpcmVjdG9yaWVzLlxuICovXG5mdW5jdGlvbiBjbGVhbkVtcHR5RGlyZWN0b3JpZXMoZGlyOiBzdHJpbmcpOiB2b2lkIHtcbiAgaWYgKCFmcy5leGlzdHNTeW5jKGRpcikpIHtcbiAgICByZXR1cm47XG4gIH1cblxuICBjb25zdCBlbnRyaWVzID0gZnMucmVhZGRpclN5bmMoZGlyLCB7IHdpdGhGaWxlVHlwZXM6IHRydWUgfSk7XG5cbiAgLy8gRmlyc3QsIHJlY3Vyc2l2ZWx5IGNsZWFuIHN1YmRpcmVjdG9yaWVzXG4gIGZvciAoY29uc3QgZW50cnkgb2YgZW50cmllcykge1xuICAgIGlmIChlbnRyeS5pc0RpcmVjdG9yeSgpKSB7XG4gICAgICBjb25zdCBmdWxsUGF0aCA9IHBhdGguam9pbihkaXIsIGVudHJ5Lm5hbWUpO1xuICAgICAgY2xlYW5FbXB0eURpcmVjdG9yaWVzKGZ1bGxQYXRoKTtcbiAgICB9XG4gIH1cblxuICAvLyBOb3cgY2hlY2sgaWYgZGlyZWN0b3J5IGlzIGVtcHR5IGFuZCByZW1vdmUgaXRcbiAgY29uc3QgcmVtYWluaW5nRW50cmllcyA9IGZzLnJlYWRkaXJTeW5jKGRpcik7XG4gIGlmIChyZW1haW5pbmdFbnRyaWVzLmxlbmd0aCA9PT0gMCkge1xuICAgIHRyeSB7XG4gICAgICBmcy5ybWRpclN5bmMoZGlyKTtcbiAgICB9IGNhdGNoIHtcbiAgICAgIC8vIElnbm9yZSBlcnJvcnMgKGRpcmVjdG9yeSBtaWdodCBub3QgYmUgZW1wdHkgb3IgbWlnaHQgYmUgaW4gdXNlKVxuICAgIH1cbiAgfVxufVxuIl19
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { TableBindingConfig } from './table-binding-config';
|
|
2
|
+
/**
|
|
3
|
+
* Base properties shared by all Chaim data store binders.
|
|
4
|
+
*/
|
|
5
|
+
export interface BaseBinderProps {
|
|
6
|
+
/** Path to the .bprint schema file (JSON format) */
|
|
7
|
+
readonly schemaPath: string;
|
|
8
|
+
/**
|
|
9
|
+
* Binding configuration (appId, credentials, failureMode).
|
|
10
|
+
*
|
|
11
|
+
* For single-table design, create one config and share across all entity bindings.
|
|
12
|
+
*
|
|
13
|
+
* @example
|
|
14
|
+
* ```typescript
|
|
15
|
+
* const config = new TableBindingConfig(
|
|
16
|
+
* 'my-app',
|
|
17
|
+
* ChaimCredentials.fromSecretsManager('chaim/api-credentials')
|
|
18
|
+
* );
|
|
19
|
+
*
|
|
20
|
+
* new ChaimDynamoDBBinder(this, 'UserBinding', {
|
|
21
|
+
* schemaPath: './schemas/user.bprint',
|
|
22
|
+
* table: usersTable,
|
|
23
|
+
* config,
|
|
24
|
+
* });
|
|
25
|
+
* ```
|
|
26
|
+
*/
|
|
27
|
+
readonly config: TableBindingConfig;
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* Validate binder props.
|
|
31
|
+
*/
|
|
32
|
+
export declare function validateBinderProps(props: BaseBinderProps): void;
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.validateBinderProps = void 0;
|
|
4
|
+
/**
|
|
5
|
+
* Validate binder props.
|
|
6
|
+
*/
|
|
7
|
+
function validateBinderProps(props) {
|
|
8
|
+
if (!props.schemaPath || props.schemaPath.trim() === '') {
|
|
9
|
+
throw new Error('schemaPath is required and cannot be empty');
|
|
10
|
+
}
|
|
11
|
+
if (!props.config) {
|
|
12
|
+
throw new Error('config is required. Create a TableBindingConfig with your appId and credentials.');
|
|
13
|
+
}
|
|
14
|
+
// TableBindingConfig validates itself in its constructor
|
|
15
|
+
}
|
|
16
|
+
exports.validateBinderProps = validateBinderProps;
|
|
17
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYmFzZS1iaW5kZXItcHJvcHMuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvdHlwZXMvYmFzZS1iaW5kZXItcHJvcHMudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7O0FBK0JBOztHQUVHO0FBQ0gsU0FBZ0IsbUJBQW1CLENBQUMsS0FBc0I7SUFDeEQsSUFBSSxDQUFDLEtBQUssQ0FBQyxVQUFVLElBQUksS0FBSyxDQUFDLFVBQVUsQ0FBQyxJQUFJLEVBQUUsS0FBSyxFQUFFLEVBQUU7UUFDdkQsTUFBTSxJQUFJLEtBQUssQ0FBQyw0Q0FBNEMsQ0FBQyxDQUFDO0tBQy9EO0lBRUQsSUFBSSxDQUFDLEtBQUssQ0FBQyxNQUFNLEVBQUU7UUFDakIsTUFBTSxJQUFJLEtBQUssQ0FBQyxrRkFBa0YsQ0FBQyxDQUFDO0tBQ3JHO0lBRUQseURBQXlEO0FBQzNELENBQUM7QUFWRCxrREFVQyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IFRhYmxlQmluZGluZ0NvbmZpZyB9IGZyb20gJy4vdGFibGUtYmluZGluZy1jb25maWcnO1xuXG4vKipcbiAqIEJhc2UgcHJvcGVydGllcyBzaGFyZWQgYnkgYWxsIENoYWltIGRhdGEgc3RvcmUgYmluZGVycy5cbiAqL1xuZXhwb3J0IGludGVyZmFjZSBCYXNlQmluZGVyUHJvcHMge1xuICAvKiogUGF0aCB0byB0aGUgLmJwcmludCBzY2hlbWEgZmlsZSAoSlNPTiBmb3JtYXQpICovXG4gIHJlYWRvbmx5IHNjaGVtYVBhdGg6IHN0cmluZztcblxuICAvKiogXG4gICAqIEJpbmRpbmcgY29uZmlndXJhdGlvbiAoYXBwSWQsIGNyZWRlbnRpYWxzLCBmYWlsdXJlTW9kZSkuXG4gICAqIFxuICAgKiBGb3Igc2luZ2xlLXRhYmxlIGRlc2lnbiwgY3JlYXRlIG9uZSBjb25maWcgYW5kIHNoYXJlIGFjcm9zcyBhbGwgZW50aXR5IGJpbmRpbmdzLlxuICAgKiBcbiAgICogQGV4YW1wbGVcbiAgICogYGBgdHlwZXNjcmlwdFxuICAgKiBjb25zdCBjb25maWcgPSBuZXcgVGFibGVCaW5kaW5nQ29uZmlnKFxuICAgKiAgICdteS1hcHAnLFxuICAgKiAgIENoYWltQ3JlZGVudGlhbHMuZnJvbVNlY3JldHNNYW5hZ2VyKCdjaGFpbS9hcGktY3JlZGVudGlhbHMnKVxuICAgKiApO1xuICAgKiBcbiAgICogbmV3IENoYWltRHluYW1vREJCaW5kZXIodGhpcywgJ1VzZXJCaW5kaW5nJywge1xuICAgKiAgIHNjaGVtYVBhdGg6ICcuL3NjaGVtYXMvdXNlci5icHJpbnQnLFxuICAgKiAgIHRhYmxlOiB1c2Vyc1RhYmxlLFxuICAgKiAgIGNvbmZpZyxcbiAgICogfSk7XG4gICAqIGBgYFxuICAgKi9cbiAgcmVhZG9ubHkgY29uZmlnOiBUYWJsZUJpbmRpbmdDb25maWc7XG59XG5cbi8qKlxuICogVmFsaWRhdGUgYmluZGVyIHByb3BzLlxuICovXG5leHBvcnQgZnVuY3Rpb24gdmFsaWRhdGVCaW5kZXJQcm9wcyhwcm9wczogQmFzZUJpbmRlclByb3BzKTogdm9pZCB7XG4gIGlmICghcHJvcHMuc2NoZW1hUGF0aCB8fCBwcm9wcy5zY2hlbWFQYXRoLnRyaW0oKSA9PT0gJycpIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoJ3NjaGVtYVBhdGggaXMgcmVxdWlyZWQgYW5kIGNhbm5vdCBiZSBlbXB0eScpO1xuICB9XG5cbiAgaWYgKCFwcm9wcy5jb25maWcpIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoJ2NvbmZpZyBpcyByZXF1aXJlZC4gQ3JlYXRlIGEgVGFibGVCaW5kaW5nQ29uZmlnIHdpdGggeW91ciBhcHBJZCBhbmQgY3JlZGVudGlhbHMuJyk7XG4gIH1cblxuICAvLyBUYWJsZUJpbmRpbmdDb25maWcgdmFsaWRhdGVzIGl0c2VsZiBpbiBpdHMgY29uc3RydWN0b3Jcbn1cbiJdfQ==
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Interface for Chaim API credentials.
|
|
3
|
+
* Use ChaimCredentials factory methods to create instances.
|
|
4
|
+
*/
|
|
5
|
+
export interface IChaimCredentials {
|
|
6
|
+
/** The type of credential configuration */
|
|
7
|
+
readonly credentialType: 'secretsManager' | 'direct';
|
|
8
|
+
/** Secret name in AWS Secrets Manager (only for secretsManager type) */
|
|
9
|
+
readonly secretName?: string;
|
|
10
|
+
/** API key for direct authentication (only for direct type) */
|
|
11
|
+
readonly apiKey?: string;
|
|
12
|
+
/** API secret for direct authentication (only for direct type) */
|
|
13
|
+
readonly apiSecret?: string;
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* Factory class for creating Chaim API credentials.
|
|
17
|
+
*
|
|
18
|
+
* @example
|
|
19
|
+
* ```typescript
|
|
20
|
+
* // Using AWS Secrets Manager (recommended for production)
|
|
21
|
+
* const credentials = ChaimCredentials.fromSecretsManager('chaim/api-credentials');
|
|
22
|
+
*
|
|
23
|
+
* // Using direct API keys (for development/testing)
|
|
24
|
+
* const credentials = ChaimCredentials.fromApiKeys(
|
|
25
|
+
* process.env.CHAIM_API_KEY!,
|
|
26
|
+
* process.env.CHAIM_API_SECRET!
|
|
27
|
+
* );
|
|
28
|
+
* ```
|
|
29
|
+
*/
|
|
30
|
+
export declare class ChaimCredentials {
|
|
31
|
+
/**
|
|
32
|
+
* Create credentials from AWS Secrets Manager.
|
|
33
|
+
*
|
|
34
|
+
* The secret must contain JSON with `apiKey` and `apiSecret` fields:
|
|
35
|
+
* ```json
|
|
36
|
+
* {
|
|
37
|
+
* "apiKey": "your-chaim-api-key",
|
|
38
|
+
* "apiSecret": "your-chaim-api-secret"
|
|
39
|
+
* }
|
|
40
|
+
* ```
|
|
41
|
+
*
|
|
42
|
+
* @param secretName - The name or ARN of the secret in AWS Secrets Manager
|
|
43
|
+
* @returns Credentials configured to use Secrets Manager
|
|
44
|
+
*/
|
|
45
|
+
static fromSecretsManager(secretName: string): IChaimCredentials;
|
|
46
|
+
/**
|
|
47
|
+
* Create credentials from direct API key and secret.
|
|
48
|
+
*
|
|
49
|
+
* Note: For production deployments, prefer `fromSecretsManager()` to avoid
|
|
50
|
+
* exposing credentials in CDK code or environment variables.
|
|
51
|
+
*
|
|
52
|
+
* @param apiKey - The Chaim API key
|
|
53
|
+
* @param apiSecret - The Chaim API secret
|
|
54
|
+
* @returns Credentials configured with direct API keys
|
|
55
|
+
*/
|
|
56
|
+
static fromApiKeys(apiKey: string, apiSecret: string): IChaimCredentials;
|
|
57
|
+
}
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.ChaimCredentials = void 0;
|
|
4
|
+
/**
|
|
5
|
+
* Internal implementation for Secrets Manager credentials.
|
|
6
|
+
*/
|
|
7
|
+
class SecretsManagerCredentials {
|
|
8
|
+
credentialType = 'secretsManager';
|
|
9
|
+
secretName;
|
|
10
|
+
constructor(secretName) {
|
|
11
|
+
if (!secretName || secretName.trim() === '') {
|
|
12
|
+
throw new Error('secretName is required and cannot be empty');
|
|
13
|
+
}
|
|
14
|
+
this.secretName = secretName;
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* Internal implementation for direct API credentials.
|
|
19
|
+
*/
|
|
20
|
+
class DirectCredentials {
|
|
21
|
+
credentialType = 'direct';
|
|
22
|
+
apiKey;
|
|
23
|
+
apiSecret;
|
|
24
|
+
constructor(apiKey, apiSecret) {
|
|
25
|
+
if (!apiKey || apiKey.trim() === '') {
|
|
26
|
+
throw new Error('apiKey is required and cannot be empty');
|
|
27
|
+
}
|
|
28
|
+
if (!apiSecret || apiSecret.trim() === '') {
|
|
29
|
+
throw new Error('apiSecret is required and cannot be empty');
|
|
30
|
+
}
|
|
31
|
+
this.apiKey = apiKey;
|
|
32
|
+
this.apiSecret = apiSecret;
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* Factory class for creating Chaim API credentials.
|
|
37
|
+
*
|
|
38
|
+
* @example
|
|
39
|
+
* ```typescript
|
|
40
|
+
* // Using AWS Secrets Manager (recommended for production)
|
|
41
|
+
* const credentials = ChaimCredentials.fromSecretsManager('chaim/api-credentials');
|
|
42
|
+
*
|
|
43
|
+
* // Using direct API keys (for development/testing)
|
|
44
|
+
* const credentials = ChaimCredentials.fromApiKeys(
|
|
45
|
+
* process.env.CHAIM_API_KEY!,
|
|
46
|
+
* process.env.CHAIM_API_SECRET!
|
|
47
|
+
* );
|
|
48
|
+
* ```
|
|
49
|
+
*/
|
|
50
|
+
class ChaimCredentials {
|
|
51
|
+
/**
|
|
52
|
+
* Create credentials from AWS Secrets Manager.
|
|
53
|
+
*
|
|
54
|
+
* The secret must contain JSON with `apiKey` and `apiSecret` fields:
|
|
55
|
+
* ```json
|
|
56
|
+
* {
|
|
57
|
+
* "apiKey": "your-chaim-api-key",
|
|
58
|
+
* "apiSecret": "your-chaim-api-secret"
|
|
59
|
+
* }
|
|
60
|
+
* ```
|
|
61
|
+
*
|
|
62
|
+
* @param secretName - The name or ARN of the secret in AWS Secrets Manager
|
|
63
|
+
* @returns Credentials configured to use Secrets Manager
|
|
64
|
+
*/
|
|
65
|
+
static fromSecretsManager(secretName) {
|
|
66
|
+
return new SecretsManagerCredentials(secretName);
|
|
67
|
+
}
|
|
68
|
+
/**
|
|
69
|
+
* Create credentials from direct API key and secret.
|
|
70
|
+
*
|
|
71
|
+
* Note: For production deployments, prefer `fromSecretsManager()` to avoid
|
|
72
|
+
* exposing credentials in CDK code or environment variables.
|
|
73
|
+
*
|
|
74
|
+
* @param apiKey - The Chaim API key
|
|
75
|
+
* @param apiSecret - The Chaim API secret
|
|
76
|
+
* @returns Credentials configured with direct API keys
|
|
77
|
+
*/
|
|
78
|
+
static fromApiKeys(apiKey, apiSecret) {
|
|
79
|
+
return new DirectCredentials(apiKey, apiSecret);
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
exports.ChaimCredentials = ChaimCredentials;
|
|
83
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY3JlZGVudGlhbHMuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvdHlwZXMvY3JlZGVudGlhbHMudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7O0FBa0JBOztHQUVHO0FBQ0gsTUFBTSx5QkFBeUI7SUFDYixjQUFjLEdBQUcsZ0JBQXlCLENBQUM7SUFDM0MsVUFBVSxDQUFTO0lBRW5DLFlBQVksVUFBa0I7UUFDNUIsSUFBSSxDQUFDLFVBQVUsSUFBSSxVQUFVLENBQUMsSUFBSSxFQUFFLEtBQUssRUFBRSxFQUFFO1lBQzNDLE1BQU0sSUFBSSxLQUFLLENBQUMsNENBQTRDLENBQUMsQ0FBQztTQUMvRDtRQUNELElBQUksQ0FBQyxVQUFVLEdBQUcsVUFBVSxDQUFDO0lBQy9CLENBQUM7Q0FDRjtBQUVEOztHQUVHO0FBQ0gsTUFBTSxpQkFBaUI7SUFDTCxjQUFjLEdBQUcsUUFBaUIsQ0FBQztJQUNuQyxNQUFNLENBQVM7SUFDZixTQUFTLENBQVM7SUFFbEMsWUFBWSxNQUFjLEVBQUUsU0FBaUI7UUFDM0MsSUFBSSxDQUFDLE1BQU0sSUFBSSxNQUFNLENBQUMsSUFBSSxFQUFFLEtBQUssRUFBRSxFQUFFO1lBQ25DLE1BQU0sSUFBSSxLQUFLLENBQUMsd0NBQXdDLENBQUMsQ0FBQztTQUMzRDtRQUNELElBQUksQ0FBQyxTQUFTLElBQUksU0FBUyxDQUFDLElBQUksRUFBRSxLQUFLLEVBQUUsRUFBRTtZQUN6QyxNQUFNLElBQUksS0FBSyxDQUFDLDJDQUEyQyxDQUFDLENBQUM7U0FDOUQ7UUFDRCxJQUFJLENBQUMsTUFBTSxHQUFHLE1BQU0sQ0FBQztRQUNyQixJQUFJLENBQUMsU0FBUyxHQUFHLFNBQVMsQ0FBQztJQUM3QixDQUFDO0NBQ0Y7QUFFRDs7Ozs7Ozs7Ozs7Ozs7R0FjRztBQUNILE1BQWEsZ0JBQWdCO0lBQzNCOzs7Ozs7Ozs7Ozs7O09BYUc7SUFDSSxNQUFNLENBQUMsa0JBQWtCLENBQUMsVUFBa0I7UUFDakQsT0FBTyxJQUFJLHlCQUF5QixDQUFDLFVBQVUsQ0FBQyxDQUFDO0lBQ25ELENBQUM7SUFFRDs7Ozs7Ozs7O09BU0c7SUFDSSxNQUFNLENBQUMsV0FBVyxDQUFDLE1BQWMsRUFBRSxTQUFpQjtRQUN6RCxPQUFPLElBQUksaUJBQWlCLENBQUMsTUFBTSxFQUFFLFNBQVMsQ0FBQyxDQUFDO0lBQ2xELENBQUM7Q0FDRjtBQWhDRCw0Q0FnQ0MiLCJzb3VyY2VzQ29udGVudCI6WyIvKipcbiAqIEludGVyZmFjZSBmb3IgQ2hhaW0gQVBJIGNyZWRlbnRpYWxzLlxuICogVXNlIENoYWltQ3JlZGVudGlhbHMgZmFjdG9yeSBtZXRob2RzIHRvIGNyZWF0ZSBpbnN0YW5jZXMuXG4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgSUNoYWltQ3JlZGVudGlhbHMge1xuICAvKiogVGhlIHR5cGUgb2YgY3JlZGVudGlhbCBjb25maWd1cmF0aW9uICovXG4gIHJlYWRvbmx5IGNyZWRlbnRpYWxUeXBlOiAnc2VjcmV0c01hbmFnZXInIHwgJ2RpcmVjdCc7XG5cbiAgLyoqIFNlY3JldCBuYW1lIGluIEFXUyBTZWNyZXRzIE1hbmFnZXIgKG9ubHkgZm9yIHNlY3JldHNNYW5hZ2VyIHR5cGUpICovXG4gIHJlYWRvbmx5IHNlY3JldE5hbWU/OiBzdHJpbmc7XG5cbiAgLyoqIEFQSSBrZXkgZm9yIGRpcmVjdCBhdXRoZW50aWNhdGlvbiAob25seSBmb3IgZGlyZWN0IHR5cGUpICovXG4gIHJlYWRvbmx5IGFwaUtleT86IHN0cmluZztcblxuICAvKiogQVBJIHNlY3JldCBmb3IgZGlyZWN0IGF1dGhlbnRpY2F0aW9uIChvbmx5IGZvciBkaXJlY3QgdHlwZSkgKi9cbiAgcmVhZG9ubHkgYXBpU2VjcmV0Pzogc3RyaW5nO1xufVxuXG4vKipcbiAqIEludGVybmFsIGltcGxlbWVudGF0aW9uIGZvciBTZWNyZXRzIE1hbmFnZXIgY3JlZGVudGlhbHMuXG4gKi9cbmNsYXNzIFNlY3JldHNNYW5hZ2VyQ3JlZGVudGlhbHMgaW1wbGVtZW50cyBJQ2hhaW1DcmVkZW50aWFscyB7XG4gIHB1YmxpYyByZWFkb25seSBjcmVkZW50aWFsVHlwZSA9ICdzZWNyZXRzTWFuYWdlcicgYXMgY29uc3Q7XG4gIHB1YmxpYyByZWFkb25seSBzZWNyZXROYW1lOiBzdHJpbmc7XG5cbiAgY29uc3RydWN0b3Ioc2VjcmV0TmFtZTogc3RyaW5nKSB7XG4gICAgaWYgKCFzZWNyZXROYW1lIHx8IHNlY3JldE5hbWUudHJpbSgpID09PSAnJykge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCdzZWNyZXROYW1lIGlzIHJlcXVpcmVkIGFuZCBjYW5ub3QgYmUgZW1wdHknKTtcbiAgICB9XG4gICAgdGhpcy5zZWNyZXROYW1lID0gc2VjcmV0TmFtZTtcbiAgfVxufVxuXG4vKipcbiAqIEludGVybmFsIGltcGxlbWVudGF0aW9uIGZvciBkaXJlY3QgQVBJIGNyZWRlbnRpYWxzLlxuICovXG5jbGFzcyBEaXJlY3RDcmVkZW50aWFscyBpbXBsZW1lbnRzIElDaGFpbUNyZWRlbnRpYWxzIHtcbiAgcHVibGljIHJlYWRvbmx5IGNyZWRlbnRpYWxUeXBlID0gJ2RpcmVjdCcgYXMgY29uc3Q7XG4gIHB1YmxpYyByZWFkb25seSBhcGlLZXk6IHN0cmluZztcbiAgcHVibGljIHJlYWRvbmx5IGFwaVNlY3JldDogc3RyaW5nO1xuXG4gIGNvbnN0cnVjdG9yKGFwaUtleTogc3RyaW5nLCBhcGlTZWNyZXQ6IHN0cmluZykge1xuICAgIGlmICghYXBpS2V5IHx8IGFwaUtleS50cmltKCkgPT09ICcnKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ2FwaUtleSBpcyByZXF1aXJlZCBhbmQgY2Fubm90IGJlIGVtcHR5Jyk7XG4gICAgfVxuICAgIGlmICghYXBpU2VjcmV0IHx8IGFwaVNlY3JldC50cmltKCkgPT09ICcnKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ2FwaVNlY3JldCBpcyByZXF1aXJlZCBhbmQgY2Fubm90IGJlIGVtcHR5Jyk7XG4gICAgfVxuICAgIHRoaXMuYXBpS2V5ID0gYXBpS2V5O1xuICAgIHRoaXMuYXBpU2VjcmV0ID0gYXBpU2VjcmV0O1xuICB9XG59XG5cbi8qKlxuICogRmFjdG9yeSBjbGFzcyBmb3IgY3JlYXRpbmcgQ2hhaW0gQVBJIGNyZWRlbnRpYWxzLlxuICpcbiAqIEBleGFtcGxlXG4gKiBgYGB0eXBlc2NyaXB0XG4gKiAvLyBVc2luZyBBV1MgU2VjcmV0cyBNYW5hZ2VyIChyZWNvbW1lbmRlZCBmb3IgcHJvZHVjdGlvbilcbiAqIGNvbnN0IGNyZWRlbnRpYWxzID0gQ2hhaW1DcmVkZW50aWFscy5mcm9tU2VjcmV0c01hbmFnZXIoJ2NoYWltL2FwaS1jcmVkZW50aWFscycpO1xuICpcbiAqIC8vIFVzaW5nIGRpcmVjdCBBUEkga2V5cyAoZm9yIGRldmVsb3BtZW50L3Rlc3RpbmcpXG4gKiBjb25zdCBjcmVkZW50aWFscyA9IENoYWltQ3JlZGVudGlhbHMuZnJvbUFwaUtleXMoXG4gKiAgIHByb2Nlc3MuZW52LkNIQUlNX0FQSV9LRVkhLFxuICogICBwcm9jZXNzLmVudi5DSEFJTV9BUElfU0VDUkVUIVxuICogKTtcbiAqIGBgYFxuICovXG5leHBvcnQgY2xhc3MgQ2hhaW1DcmVkZW50aWFscyB7XG4gIC8qKlxuICAgKiBDcmVhdGUgY3JlZGVudGlhbHMgZnJvbSBBV1MgU2VjcmV0cyBNYW5hZ2VyLlxuICAgKlxuICAgKiBUaGUgc2VjcmV0IG11c3QgY29udGFpbiBKU09OIHdpdGggYGFwaUtleWAgYW5kIGBhcGlTZWNyZXRgIGZpZWxkczpcbiAgICogYGBganNvblxuICAgKiB7XG4gICAqICAgXCJhcGlLZXlcIjogXCJ5b3VyLWNoYWltLWFwaS1rZXlcIixcbiAgICogICBcImFwaVNlY3JldFwiOiBcInlvdXItY2hhaW0tYXBpLXNlY3JldFwiXG4gICAqIH1cbiAgICogYGBgXG4gICAqXG4gICAqIEBwYXJhbSBzZWNyZXROYW1lIC0gVGhlIG5hbWUgb3IgQVJOIG9mIHRoZSBzZWNyZXQgaW4gQVdTIFNlY3JldHMgTWFuYWdlclxuICAgKiBAcmV0dXJucyBDcmVkZW50aWFscyBjb25maWd1cmVkIHRvIHVzZSBTZWNyZXRzIE1hbmFnZXJcbiAgICovXG4gIHB1YmxpYyBzdGF0aWMgZnJvbVNlY3JldHNNYW5hZ2VyKHNlY3JldE5hbWU6IHN0cmluZyk6IElDaGFpbUNyZWRlbnRpYWxzIHtcbiAgICByZXR1cm4gbmV3IFNlY3JldHNNYW5hZ2VyQ3JlZGVudGlhbHMoc2VjcmV0TmFtZSk7XG4gIH1cblxuICAvKipcbiAgICogQ3JlYXRlIGNyZWRlbnRpYWxzIGZyb20gZGlyZWN0IEFQSSBrZXkgYW5kIHNlY3JldC5cbiAgICpcbiAgICogTm90ZTogRm9yIHByb2R1Y3Rpb24gZGVwbG95bWVudHMsIHByZWZlciBgZnJvbVNlY3JldHNNYW5hZ2VyKClgIHRvIGF2b2lkXG4gICAqIGV4cG9zaW5nIGNyZWRlbnRpYWxzIGluIENESyBjb2RlIG9yIGVudmlyb25tZW50IHZhcmlhYmxlcy5cbiAgICpcbiAgICogQHBhcmFtIGFwaUtleSAtIFRoZSBDaGFpbSBBUEkga2V5XG4gICAqIEBwYXJhbSBhcGlTZWNyZXQgLSBUaGUgQ2hhaW0gQVBJIHNlY3JldFxuICAgKiBAcmV0dXJucyBDcmVkZW50aWFscyBjb25maWd1cmVkIHdpdGggZGlyZWN0IEFQSSBrZXlzXG4gICAqL1xuICBwdWJsaWMgc3RhdGljIGZyb21BcGlLZXlzKGFwaUtleTogc3RyaW5nLCBhcGlTZWNyZXQ6IHN0cmluZyk6IElDaGFpbUNyZWRlbnRpYWxzIHtcbiAgICByZXR1cm4gbmV3IERpcmVjdENyZWRlbnRpYWxzKGFwaUtleSwgYXBpU2VjcmV0KTtcbiAgfVxufVxuXG4iXX0=
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Base metadata interface for all data store types.
|
|
3
|
+
* Each data store binder extends this with store-specific fields.
|
|
4
|
+
*/
|
|
5
|
+
export interface BaseDataStoreMetadata {
|
|
6
|
+
/** Data store type identifier */
|
|
7
|
+
readonly type: string;
|
|
8
|
+
/** AWS region */
|
|
9
|
+
readonly region: string;
|
|
10
|
+
/** Encryption key ARN (if configured) */
|
|
11
|
+
readonly encryptionKeyArn?: string;
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* DynamoDB table metadata captured during binding.
|
|
15
|
+
*
|
|
16
|
+
* Note: Removed duplicate fields from v1.1:
|
|
17
|
+
* - arn (use tableArn instead - globally unique)
|
|
18
|
+
* - name (use tableName instead)
|
|
19
|
+
* - account (use top-level accountId instead)
|
|
20
|
+
*/
|
|
21
|
+
export interface DynamoDBMetadata extends BaseDataStoreMetadata {
|
|
22
|
+
readonly type: 'dynamodb';
|
|
23
|
+
/** Table name */
|
|
24
|
+
readonly tableName: string;
|
|
25
|
+
/** Table ARN (globally unique identifier) */
|
|
26
|
+
readonly tableArn: string;
|
|
27
|
+
/** Partition key attribute name */
|
|
28
|
+
readonly partitionKey: string;
|
|
29
|
+
/** Sort key attribute name (if composite key) */
|
|
30
|
+
readonly sortKey?: string;
|
|
31
|
+
/** Global Secondary Indexes */
|
|
32
|
+
readonly globalSecondaryIndexes?: GSIMetadata[];
|
|
33
|
+
/** Local Secondary Indexes */
|
|
34
|
+
readonly localSecondaryIndexes?: LSIMetadata[];
|
|
35
|
+
/** TTL attribute name (if enabled) */
|
|
36
|
+
readonly ttlAttribute?: string;
|
|
37
|
+
/** Whether DynamoDB Streams is enabled */
|
|
38
|
+
readonly streamEnabled?: boolean;
|
|
39
|
+
/** Stream view type (if streams enabled) */
|
|
40
|
+
readonly streamViewType?: string;
|
|
41
|
+
/** Billing mode */
|
|
42
|
+
readonly billingMode?: 'PAY_PER_REQUEST' | 'PROVISIONED';
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* Global Secondary Index metadata
|
|
46
|
+
*/
|
|
47
|
+
export interface GSIMetadata {
|
|
48
|
+
readonly indexName: string;
|
|
49
|
+
readonly partitionKey: string;
|
|
50
|
+
readonly sortKey?: string;
|
|
51
|
+
readonly projectionType: 'ALL' | 'KEYS_ONLY' | 'INCLUDE';
|
|
52
|
+
readonly nonKeyAttributes?: string[];
|
|
53
|
+
}
|
|
54
|
+
/**
|
|
55
|
+
* Local Secondary Index metadata
|
|
56
|
+
*/
|
|
57
|
+
export interface LSIMetadata {
|
|
58
|
+
readonly indexName: string;
|
|
59
|
+
readonly sortKey: string;
|
|
60
|
+
readonly projectionType: 'ALL' | 'KEYS_ONLY' | 'INCLUDE';
|
|
61
|
+
readonly nonKeyAttributes?: string[];
|
|
62
|
+
}
|
|
63
|
+
/**
|
|
64
|
+
* Union type for all supported data store metadata.
|
|
65
|
+
* Extend this union as new data stores are added.
|
|
66
|
+
*/
|
|
67
|
+
export type DataStoreMetadata = DynamoDBMetadata;
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
// Future: | AuroraMetadata | RDSMetadata | DocumentDBMetadata;
|
|
4
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZGF0YS1zdG9yZS1tZXRhZGF0YS5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy90eXBlcy9kYXRhLXN0b3JlLW1ldGFkYXRhLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7O0FBbUZBLCtEQUErRCIsInNvdXJjZXNDb250ZW50IjpbIi8qKlxuICogQmFzZSBtZXRhZGF0YSBpbnRlcmZhY2UgZm9yIGFsbCBkYXRhIHN0b3JlIHR5cGVzLlxuICogRWFjaCBkYXRhIHN0b3JlIGJpbmRlciBleHRlbmRzIHRoaXMgd2l0aCBzdG9yZS1zcGVjaWZpYyBmaWVsZHMuXG4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgQmFzZURhdGFTdG9yZU1ldGFkYXRhIHtcbiAgLyoqIERhdGEgc3RvcmUgdHlwZSBpZGVudGlmaWVyICovXG4gIHJlYWRvbmx5IHR5cGU6IHN0cmluZztcblxuICAvKiogQVdTIHJlZ2lvbiAqL1xuICByZWFkb25seSByZWdpb246IHN0cmluZztcblxuICAvKiogRW5jcnlwdGlvbiBrZXkgQVJOIChpZiBjb25maWd1cmVkKSAqL1xuICByZWFkb25seSBlbmNyeXB0aW9uS2V5QXJuPzogc3RyaW5nO1xufVxuXG4vKipcbiAqIER5bmFtb0RCIHRhYmxlIG1ldGFkYXRhIGNhcHR1cmVkIGR1cmluZyBiaW5kaW5nLlxuICogXG4gKiBOb3RlOiBSZW1vdmVkIGR1cGxpY2F0ZSBmaWVsZHMgZnJvbSB2MS4xOlxuICogLSBhcm4gKHVzZSB0YWJsZUFybiBpbnN0ZWFkIC0gZ2xvYmFsbHkgdW5pcXVlKVxuICogLSBuYW1lICh1c2UgdGFibGVOYW1lIGluc3RlYWQpXG4gKiAtIGFjY291bnQgKHVzZSB0b3AtbGV2ZWwgYWNjb3VudElkIGluc3RlYWQpXG4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgRHluYW1vREJNZXRhZGF0YSBleHRlbmRzIEJhc2VEYXRhU3RvcmVNZXRhZGF0YSB7XG4gIHJlYWRvbmx5IHR5cGU6ICdkeW5hbW9kYic7XG5cbiAgLyoqIFRhYmxlIG5hbWUgKi9cbiAgcmVhZG9ubHkgdGFibGVOYW1lOiBzdHJpbmc7XG5cbiAgLyoqIFRhYmxlIEFSTiAoZ2xvYmFsbHkgdW5pcXVlIGlkZW50aWZpZXIpICovXG4gIHJlYWRvbmx5IHRhYmxlQXJuOiBzdHJpbmc7XG5cbiAgLyoqIFBhcnRpdGlvbiBrZXkgYXR0cmlidXRlIG5hbWUgKi9cbiAgcmVhZG9ubHkgcGFydGl0aW9uS2V5OiBzdHJpbmc7XG5cbiAgLyoqIFNvcnQga2V5IGF0dHJpYnV0ZSBuYW1lIChpZiBjb21wb3NpdGUga2V5KSAqL1xuICByZWFkb25seSBzb3J0S2V5Pzogc3RyaW5nO1xuXG4gIC8qKiBHbG9iYWwgU2Vjb25kYXJ5IEluZGV4ZXMgKi9cbiAgcmVhZG9ubHkgZ2xvYmFsU2Vjb25kYXJ5SW5kZXhlcz86IEdTSU1ldGFkYXRhW107XG5cbiAgLyoqIExvY2FsIFNlY29uZGFyeSBJbmRleGVzICovXG4gIHJlYWRvbmx5IGxvY2FsU2Vjb25kYXJ5SW5kZXhlcz86IExTSU1ldGFkYXRhW107XG5cbiAgLyoqIFRUTCBhdHRyaWJ1dGUgbmFtZSAoaWYgZW5hYmxlZCkgKi9cbiAgcmVhZG9ubHkgdHRsQXR0cmlidXRlPzogc3RyaW5nO1xuXG4gIC8qKiBXaGV0aGVyIER5bmFtb0RCIFN0cmVhbXMgaXMgZW5hYmxlZCAqL1xuICByZWFkb25seSBzdHJlYW1FbmFibGVkPzogYm9vbGVhbjtcblxuICAvKiogU3RyZWFtIHZpZXcgdHlwZSAoaWYgc3RyZWFtcyBlbmFibGVkKSAqL1xuICByZWFkb25seSBzdHJlYW1WaWV3VHlwZT86IHN0cmluZztcblxuICAvKiogQmlsbGluZyBtb2RlICovXG4gIHJlYWRvbmx5IGJpbGxpbmdNb2RlPzogJ1BBWV9QRVJfUkVRVUVTVCcgfCAnUFJPVklTSU9ORUQnO1xufVxuXG4vKipcbiAqIEdsb2JhbCBTZWNvbmRhcnkgSW5kZXggbWV0YWRhdGFcbiAqL1xuZXhwb3J0IGludGVyZmFjZSBHU0lNZXRhZGF0YSB7XG4gIHJlYWRvbmx5IGluZGV4TmFtZTogc3RyaW5nO1xuICByZWFkb25seSBwYXJ0aXRpb25LZXk6IHN0cmluZztcbiAgcmVhZG9ubHkgc29ydEtleT86IHN0cmluZztcbiAgcmVhZG9ubHkgcHJvamVjdGlvblR5cGU6ICdBTEwnIHwgJ0tFWVNfT05MWScgfCAnSU5DTFVERSc7XG4gIHJlYWRvbmx5IG5vbktleUF0dHJpYnV0ZXM/OiBzdHJpbmdbXTtcbn1cblxuLyoqXG4gKiBMb2NhbCBTZWNvbmRhcnkgSW5kZXggbWV0YWRhdGFcbiAqL1xuZXhwb3J0IGludGVyZmFjZSBMU0lNZXRhZGF0YSB7XG4gIHJlYWRvbmx5IGluZGV4TmFtZTogc3RyaW5nO1xuICByZWFkb25seSBzb3J0S2V5OiBzdHJpbmc7XG4gIHJlYWRvbmx5IHByb2plY3Rpb25UeXBlOiAnQUxMJyB8ICdLRVlTX09OTFknIHwgJ0lOQ0xVREUnO1xuICByZWFkb25seSBub25LZXlBdHRyaWJ1dGVzPzogc3RyaW5nW107XG59XG5cbi8qKlxuICogVW5pb24gdHlwZSBmb3IgYWxsIHN1cHBvcnRlZCBkYXRhIHN0b3JlIG1ldGFkYXRhLlxuICogRXh0ZW5kIHRoaXMgdW5pb24gYXMgbmV3IGRhdGEgc3RvcmVzIGFyZSBhZGRlZC5cbiAqL1xuZXhwb3J0IHR5cGUgRGF0YVN0b3JlTWV0YWRhdGEgPSBEeW5hbW9EQk1ldGFkYXRhO1xuLy8gRnV0dXJlOiB8IEF1cm9yYU1ldGFkYXRhIHwgUkRTTWV0YWRhdGEgfCBEb2N1bWVudERCTWV0YWRhdGE7XG5cblxuIl19
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Behavior when schema ingestion fails during deployment.
|
|
3
|
+
*/
|
|
4
|
+
export declare enum FailureMode {
|
|
5
|
+
/**
|
|
6
|
+
* Log errors but return SUCCESS to CloudFormation.
|
|
7
|
+
* Deployment continues even if ingestion fails.
|
|
8
|
+
* This is the default.
|
|
9
|
+
*/
|
|
10
|
+
BEST_EFFORT = "BEST_EFFORT",
|
|
11
|
+
/**
|
|
12
|
+
* Return FAILED to CloudFormation on any ingestion error.
|
|
13
|
+
* WARNING: Deployment will roll back if ingestion fails.
|
|
14
|
+
*/
|
|
15
|
+
STRICT = "STRICT"
|
|
16
|
+
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.FailureMode = void 0;
|
|
4
|
+
/**
|
|
5
|
+
* Behavior when schema ingestion fails during deployment.
|
|
6
|
+
*/
|
|
7
|
+
var FailureMode;
|
|
8
|
+
(function (FailureMode) {
|
|
9
|
+
/**
|
|
10
|
+
* Log errors but return SUCCESS to CloudFormation.
|
|
11
|
+
* Deployment continues even if ingestion fails.
|
|
12
|
+
* This is the default.
|
|
13
|
+
*/
|
|
14
|
+
FailureMode["BEST_EFFORT"] = "BEST_EFFORT";
|
|
15
|
+
/**
|
|
16
|
+
* Return FAILED to CloudFormation on any ingestion error.
|
|
17
|
+
* WARNING: Deployment will roll back if ingestion fails.
|
|
18
|
+
*/
|
|
19
|
+
FailureMode["STRICT"] = "STRICT";
|
|
20
|
+
})(FailureMode = exports.FailureMode || (exports.FailureMode = {}));
|
|
21
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZmFpbHVyZS1tb2RlLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vc3JjL3R5cGVzL2ZhaWx1cmUtbW9kZS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7QUFBQTs7R0FFRztBQUNILElBQVksV0FhWDtBQWJELFdBQVksV0FBVztJQUNyQjs7OztPQUlHO0lBQ0gsMENBQTJCLENBQUE7SUFFM0I7OztPQUdHO0lBQ0gsZ0NBQWlCLENBQUE7QUFDbkIsQ0FBQyxFQWJXLFdBQVcsR0FBWCxtQkFBVyxLQUFYLG1CQUFXLFFBYXRCIiwic291cmNlc0NvbnRlbnQiOlsiLyoqXG4gKiBCZWhhdmlvciB3aGVuIHNjaGVtYSBpbmdlc3Rpb24gZmFpbHMgZHVyaW5nIGRlcGxveW1lbnQuXG4gKi9cbmV4cG9ydCBlbnVtIEZhaWx1cmVNb2RlIHtcbiAgLyoqXG4gICAqIExvZyBlcnJvcnMgYnV0IHJldHVybiBTVUNDRVNTIHRvIENsb3VkRm9ybWF0aW9uLlxuICAgKiBEZXBsb3ltZW50IGNvbnRpbnVlcyBldmVuIGlmIGluZ2VzdGlvbiBmYWlscy5cbiAgICogVGhpcyBpcyB0aGUgZGVmYXVsdC5cbiAgICovXG4gIEJFU1RfRUZGT1JUID0gJ0JFU1RfRUZGT1JUJyxcblxuICAvKipcbiAgICogUmV0dXJuIEZBSUxFRCB0byBDbG91ZEZvcm1hdGlvbiBvbiBhbnkgaW5nZXN0aW9uIGVycm9yLlxuICAgKiBXQVJOSU5HOiBEZXBsb3ltZW50IHdpbGwgcm9sbCBiYWNrIGlmIGluZ2VzdGlvbiBmYWlscy5cbiAgICovXG4gIFNUUklDVCA9ICdTVFJJQ1QnLFxufVxuXG4iXX0=
|