@ftschopp/dynatable-core 1.0.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/CHANGELOG.md +62 -0
- package/README.md +17 -0
- package/dist/builders/batch-get/create-batch-get-builder.d.ts +18 -0
- package/dist/builders/batch-get/create-batch-get-builder.d.ts.map +1 -0
- package/dist/builders/batch-get/create-batch-get-builder.js +71 -0
- package/dist/builders/batch-get/index.d.ts +3 -0
- package/dist/builders/batch-get/index.d.ts.map +1 -0
- package/dist/builders/batch-get/index.js +18 -0
- package/dist/builders/batch-get/types.d.ts +25 -0
- package/dist/builders/batch-get/types.d.ts.map +1 -0
- package/dist/builders/batch-get/types.js +2 -0
- package/dist/builders/batch-write/create-batch-write-builder.d.ts +12 -0
- package/dist/builders/batch-write/create-batch-write-builder.d.ts.map +1 -0
- package/dist/builders/batch-write/create-batch-write-builder.js +35 -0
- package/dist/builders/batch-write/index.d.ts +3 -0
- package/dist/builders/batch-write/index.d.ts.map +1 -0
- package/dist/builders/batch-write/index.js +18 -0
- package/dist/builders/batch-write/types.d.ts +30 -0
- package/dist/builders/batch-write/types.d.ts.map +1 -0
- package/dist/builders/batch-write/types.js +2 -0
- package/dist/builders/delete/create-delete-builder.d.ts +9 -0
- package/dist/builders/delete/create-delete-builder.d.ts.map +1 -0
- package/dist/builders/delete/create-delete-builder.js +72 -0
- package/dist/builders/delete/index.d.ts +3 -0
- package/dist/builders/delete/index.d.ts.map +1 -0
- package/dist/builders/delete/index.js +18 -0
- package/dist/builders/delete/types.d.ts +11 -0
- package/dist/builders/delete/types.d.ts.map +1 -0
- package/dist/builders/delete/types.js +2 -0
- package/dist/builders/get/create-get-builder.d.ts +12 -0
- package/dist/builders/get/create-get-builder.d.ts.map +1 -0
- package/dist/builders/get/create-get-builder.js +95 -0
- package/dist/builders/get/index.d.ts +3 -0
- package/dist/builders/get/index.d.ts.map +1 -0
- package/dist/builders/get/index.js +18 -0
- package/dist/builders/get/types.d.ts +28 -0
- package/dist/builders/get/types.d.ts.map +1 -0
- package/dist/builders/get/types.js +2 -0
- package/dist/builders/index.d.ts +12 -0
- package/dist/builders/index.d.ts.map +1 -0
- package/dist/builders/index.js +29 -0
- package/dist/builders/put/create-put-builder.d.ts +9 -0
- package/dist/builders/put/create-put-builder.d.ts.map +1 -0
- package/dist/builders/put/create-put-builder.js +104 -0
- package/dist/builders/put/index.d.ts +3 -0
- package/dist/builders/put/index.d.ts.map +1 -0
- package/dist/builders/put/index.js +18 -0
- package/dist/builders/put/types.d.ts +17 -0
- package/dist/builders/put/types.d.ts.map +1 -0
- package/dist/builders/put/types.js +2 -0
- package/dist/builders/query/create-query-builder.d.ts +9 -0
- package/dist/builders/query/create-query-builder.d.ts.map +1 -0
- package/dist/builders/query/create-query-builder.js +283 -0
- package/dist/builders/query/index.d.ts +3 -0
- package/dist/builders/query/index.d.ts.map +1 -0
- package/dist/builders/query/index.js +18 -0
- package/dist/builders/query/types.d.ts +79 -0
- package/dist/builders/query/types.d.ts.map +1 -0
- package/dist/builders/query/types.js +2 -0
- package/dist/builders/scan/create-scan-builder.d.ts +12 -0
- package/dist/builders/scan/create-scan-builder.d.ts.map +1 -0
- package/dist/builders/scan/create-scan-builder.js +103 -0
- package/dist/builders/scan/index.d.ts +3 -0
- package/dist/builders/scan/index.d.ts.map +1 -0
- package/dist/builders/scan/index.js +18 -0
- package/dist/builders/scan/types.d.ts +43 -0
- package/dist/builders/scan/types.d.ts.map +1 -0
- package/dist/builders/scan/types.js +2 -0
- package/dist/builders/shared/conditions.d.ts +18 -0
- package/dist/builders/shared/conditions.d.ts.map +1 -0
- package/dist/builders/shared/conditions.js +48 -0
- package/dist/builders/shared/index.d.ts +4 -0
- package/dist/builders/shared/index.d.ts.map +1 -0
- package/dist/builders/shared/index.js +19 -0
- package/dist/builders/shared/operators.d.ts +12 -0
- package/dist/builders/shared/operators.d.ts.map +1 -0
- package/dist/builders/shared/operators.js +197 -0
- package/dist/builders/shared/types.d.ts +77 -0
- package/dist/builders/shared/types.d.ts.map +1 -0
- package/dist/builders/shared/types.js +6 -0
- package/dist/builders/transact-get/create-transact-get-builder.d.ts +18 -0
- package/dist/builders/transact-get/create-transact-get-builder.d.ts.map +1 -0
- package/dist/builders/transact-get/create-transact-get-builder.js +60 -0
- package/dist/builders/transact-get/index.d.ts +3 -0
- package/dist/builders/transact-get/index.d.ts.map +1 -0
- package/dist/builders/transact-get/index.js +18 -0
- package/dist/builders/transact-get/types.d.ts +28 -0
- package/dist/builders/transact-get/types.d.ts.map +1 -0
- package/dist/builders/transact-get/types.js +2 -0
- package/dist/builders/transact-write/create-transact-write-builder.d.ts +18 -0
- package/dist/builders/transact-write/create-transact-write-builder.d.ts.map +1 -0
- package/dist/builders/transact-write/create-transact-write-builder.js +97 -0
- package/dist/builders/transact-write/index.d.ts +3 -0
- package/dist/builders/transact-write/index.d.ts.map +1 -0
- package/dist/builders/transact-write/index.js +18 -0
- package/dist/builders/transact-write/types.d.ts +34 -0
- package/dist/builders/transact-write/types.d.ts.map +1 -0
- package/dist/builders/transact-write/types.js +2 -0
- package/dist/builders/update/create-update-builder.d.ts +14 -0
- package/dist/builders/update/create-update-builder.d.ts.map +1 -0
- package/dist/builders/update/create-update-builder.js +180 -0
- package/dist/builders/update/index.d.ts +3 -0
- package/dist/builders/update/index.d.ts.map +1 -0
- package/dist/builders/update/index.js +18 -0
- package/dist/builders/update/types.d.ts +35 -0
- package/dist/builders/update/types.d.ts.map +1 -0
- package/dist/builders/update/types.js +2 -0
- package/dist/core/types.d.ts +224 -0
- package/dist/core/types.d.ts.map +1 -0
- package/dist/core/types.js +3 -0
- package/dist/entity.d.ts +73 -0
- package/dist/entity.d.ts.map +1 -0
- package/dist/entity.js +161 -0
- package/dist/index.d.ts +4 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +20 -0
- package/dist/table.d.ts +70 -0
- package/dist/table.d.ts.map +1 -0
- package/dist/table.js +69 -0
- package/dist/utils/dynamodb-logger.d.ts +118 -0
- package/dist/utils/dynamodb-logger.d.ts.map +1 -0
- package/dist/utils/dynamodb-logger.js +125 -0
- package/dist/utils/model-utils.d.ts +24 -0
- package/dist/utils/model-utils.d.ts.map +1 -0
- package/dist/utils/model-utils.js +88 -0
- package/dist/utils/zod-utils.d.ts +13 -0
- package/dist/utils/zod-utils.d.ts.map +1 -0
- package/dist/utils/zod-utils.js +35 -0
- package/eslint.config.mjs +4 -0
- package/jest.config.js +11 -0
- package/package.json +36 -0
- package/src/builders/README.md +272 -0
- package/src/builders/batch-get/README.md +98 -0
- package/src/builders/batch-get/create-batch-get-builder.test.ts +165 -0
- package/src/builders/batch-get/create-batch-get-builder.ts +106 -0
- package/src/builders/batch-get/index.ts +2 -0
- package/src/builders/batch-get/types.ts +29 -0
- package/src/builders/batch-write/README.md +204 -0
- package/src/builders/batch-write/create-batch-write-builder.test.ts +173 -0
- package/src/builders/batch-write/create-batch-write-builder.ts +49 -0
- package/src/builders/batch-write/index.ts +2 -0
- package/src/builders/batch-write/types.ts +33 -0
- package/src/builders/delete/create-delete-builder.test.ts +294 -0
- package/src/builders/delete/create-delete-builder.ts +100 -0
- package/src/builders/delete/index.ts +2 -0
- package/src/builders/delete/types.ts +11 -0
- package/src/builders/get/create-get-builder.test.ts +272 -0
- package/src/builders/get/create-get-builder.ts +140 -0
- package/src/builders/get/index.ts +2 -0
- package/src/builders/get/types.ts +30 -0
- package/src/builders/index.ts +14 -0
- package/src/builders/put/create-put-builder.test.ts +213 -0
- package/src/builders/put/create-put-builder.ts +151 -0
- package/src/builders/put/index.ts +2 -0
- package/src/builders/put/types.ts +18 -0
- package/src/builders/query/create-query-builder.test.ts +230 -0
- package/src/builders/query/create-query-builder.ts +353 -0
- package/src/builders/query/index.ts +2 -0
- package/src/builders/query/types.ts +95 -0
- package/src/builders/scan/create-scan-builder.test.ts +260 -0
- package/src/builders/scan/create-scan-builder.ts +217 -0
- package/src/builders/scan/index.ts +2 -0
- package/src/builders/scan/types.ts +49 -0
- package/src/builders/shared/conditions.ts +58 -0
- package/src/builders/shared/index.ts +3 -0
- package/src/builders/shared/operators.test.ts +270 -0
- package/src/builders/shared/operators.ts +200 -0
- package/src/builders/shared/types.ts +100 -0
- package/src/builders/transact-get/README.md +167 -0
- package/src/builders/transact-get/create-transact-get-builder.test.ts +239 -0
- package/src/builders/transact-get/create-transact-get-builder.ts +67 -0
- package/src/builders/transact-get/index.ts +2 -0
- package/src/builders/transact-get/types.ts +31 -0
- package/src/builders/transact-write/README.md +166 -0
- package/src/builders/transact-write/create-transact-write-builder.test.ts +288 -0
- package/src/builders/transact-write/create-transact-write-builder.ts +118 -0
- package/src/builders/transact-write/index.ts +2 -0
- package/src/builders/transact-write/types.ts +33 -0
- package/src/builders/update/create-update-builder.test.ts +333 -0
- package/src/builders/update/create-update-builder.ts +284 -0
- package/src/builders/update/index.ts +2 -0
- package/src/builders/update/types.ts +42 -0
- package/src/core/types.test.ts +506 -0
- package/src/core/types.ts +290 -0
- package/src/entity.ts +337 -0
- package/src/index.ts +22 -0
- package/src/table.ts +109 -0
- package/src/utils/dynamodb-logger.test.ts +246 -0
- package/src/utils/dynamodb-logger.ts +175 -0
- package/src/utils/model-utils.test.ts +232 -0
- package/src/utils/model-utils.ts +101 -0
- package/src/utils/zod-utils.test.ts +272 -0
- package/src/utils/zod-utils.ts +36 -0
- package/tests/integration/instagram-clone.integration.test.ts +966 -0
- package/tests/integration/pagination-timestamps.integration.test.ts +375 -0
- package/tests/integration/transactions.integration.test.ts +529 -0
- package/tsconfig.json +12 -0
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Configuration for DynamoDB operation logging
|
|
3
|
+
*/
|
|
4
|
+
export interface DynamoDBLoggerConfig {
|
|
5
|
+
/**
|
|
6
|
+
* Enable/disable logging. Default: false
|
|
7
|
+
*/
|
|
8
|
+
enabled: boolean;
|
|
9
|
+
/**
|
|
10
|
+
* Log the request parameters. Default: true
|
|
11
|
+
*/
|
|
12
|
+
logParams?: boolean;
|
|
13
|
+
/**
|
|
14
|
+
* Log the response data. Default: false
|
|
15
|
+
*/
|
|
16
|
+
logResponse?: boolean;
|
|
17
|
+
/**
|
|
18
|
+
* Custom logger function. Default: console.log
|
|
19
|
+
*/
|
|
20
|
+
loggerFn?: (message: string) => void;
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* DynamoDB Logger interface
|
|
24
|
+
*/
|
|
25
|
+
export type DynamoDBLogger = {
|
|
26
|
+
/**
|
|
27
|
+
* Log a DynamoDB operation with its parameters and optionally the response
|
|
28
|
+
*/
|
|
29
|
+
log: <TParams, TResponse>(operationName: string, params: TParams, response?: TResponse) => void;
|
|
30
|
+
};
|
|
31
|
+
/**
|
|
32
|
+
* Creates a DynamoDB logger instance with the given configuration
|
|
33
|
+
* This is the main factory function for creating loggers
|
|
34
|
+
*
|
|
35
|
+
* @example Basic logger with request parameters only
|
|
36
|
+
* ```typescript
|
|
37
|
+
* const logger = createDynamoDBLogger({
|
|
38
|
+
* enabled: true,
|
|
39
|
+
* logParams: true,
|
|
40
|
+
* logResponse: false,
|
|
41
|
+
* });
|
|
42
|
+
* ```
|
|
43
|
+
*
|
|
44
|
+
* @example Full logging (params + response)
|
|
45
|
+
* ```typescript
|
|
46
|
+
* const logger = createDynamoDBLogger({
|
|
47
|
+
* enabled: true,
|
|
48
|
+
* logParams: true,
|
|
49
|
+
* logResponse: true,
|
|
50
|
+
* });
|
|
51
|
+
* ```
|
|
52
|
+
*
|
|
53
|
+
* @example Using with a table
|
|
54
|
+
* ```typescript
|
|
55
|
+
* const logger = createDynamoDBLogger({
|
|
56
|
+
* enabled: true,
|
|
57
|
+
* logParams: true,
|
|
58
|
+
* logResponse: true,
|
|
59
|
+
* });
|
|
60
|
+
*
|
|
61
|
+
* const userTable = createTable({
|
|
62
|
+
* tableName: 'Users',
|
|
63
|
+
* client: dynamoDBClient,
|
|
64
|
+
* schema: userSchema,
|
|
65
|
+
* logger, // Pass logger to table
|
|
66
|
+
* });
|
|
67
|
+
*
|
|
68
|
+
* // Operations will be logged automatically
|
|
69
|
+
* const user = await userTable.get({ username: 'johndoe' }).execute();
|
|
70
|
+
* ```
|
|
71
|
+
*
|
|
72
|
+
* @example Custom logger function (Winston, Pino, etc.)
|
|
73
|
+
* ```typescript
|
|
74
|
+
* import winston from 'winston';
|
|
75
|
+
*
|
|
76
|
+
* const winstonLogger = winston.createLogger({
|
|
77
|
+
* level: 'info',
|
|
78
|
+
* format: winston.format.json(),
|
|
79
|
+
* transports: [new winston.transports.Console()],
|
|
80
|
+
* });
|
|
81
|
+
*
|
|
82
|
+
* const logger = createDynamoDBLogger({
|
|
83
|
+
* enabled: true,
|
|
84
|
+
* logParams: true,
|
|
85
|
+
* logResponse: true,
|
|
86
|
+
* loggerFn: (message) => winstonLogger.info(message),
|
|
87
|
+
* });
|
|
88
|
+
* ```
|
|
89
|
+
*
|
|
90
|
+
* @example Output format
|
|
91
|
+
* ```
|
|
92
|
+
* ================================================================================
|
|
93
|
+
* [DynamoDB] GetCommand - 2025-12-29T10:30:45.123Z
|
|
94
|
+
* ================================================================================
|
|
95
|
+
*
|
|
96
|
+
* 📤 Request Parameters:
|
|
97
|
+
* {
|
|
98
|
+
* "TableName": "Users",
|
|
99
|
+
* "Key": {
|
|
100
|
+
* "PK": "USER#johndoe",
|
|
101
|
+
* "SK": "PROFILE"
|
|
102
|
+
* }
|
|
103
|
+
* }
|
|
104
|
+
*
|
|
105
|
+
* 📥 Response:
|
|
106
|
+
* {
|
|
107
|
+
* "Item": {
|
|
108
|
+
* "PK": "USER#johndoe",
|
|
109
|
+
* "SK": "PROFILE",
|
|
110
|
+
* "username": "johndoe",
|
|
111
|
+
* "email": "john@example.com"
|
|
112
|
+
* }
|
|
113
|
+
* }
|
|
114
|
+
* ================================================================================
|
|
115
|
+
* ```
|
|
116
|
+
*/
|
|
117
|
+
export declare const createDynamoDBLogger: (config: DynamoDBLoggerConfig) => DynamoDBLogger;
|
|
118
|
+
//# sourceMappingURL=dynamodb-logger.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"dynamodb-logger.d.ts","sourceRoot":"","sources":["../../src/utils/dynamodb-logger.ts"],"names":[],"mappings":"AAEA;;GAEG;AACH,MAAM,WAAW,oBAAoB;IACnC;;OAEG;IACH,OAAO,EAAE,OAAO,CAAC;IAEjB;;OAEG;IACH,SAAS,CAAC,EAAE,OAAO,CAAC;IAEpB;;OAEG;IACH,WAAW,CAAC,EAAE,OAAO,CAAC;IAEtB;;OAEG;IACH,QAAQ,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,CAAC;CACtC;AAED;;GAEG;AACH,MAAM,MAAM,cAAc,GAAG;IAC3B;;OAEG;IACH,GAAG,EAAE,CAAC,OAAO,EAAE,SAAS,EAAE,aAAa,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,QAAQ,CAAC,EAAE,SAAS,KAAK,IAAI,CAAC;CACjG,CAAC;AAkCF;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAqFG;AACH,eAAO,MAAM,oBAAoB,GAAI,QAAQ,oBAAoB,KAAG,cAmBnE,CAAC"}
|
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/* eslint-disable @typescript-eslint/no-explicit-any */
|
|
3
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
4
|
+
exports.createDynamoDBLogger = void 0;
|
|
5
|
+
/**
|
|
6
|
+
* Pure function to format log message
|
|
7
|
+
* This function has no side effects and is easily testable
|
|
8
|
+
*/
|
|
9
|
+
const formatLogMessage = (operationName, timestamp, params, response, config) => {
|
|
10
|
+
const parts = [
|
|
11
|
+
'\n' + '='.repeat(80),
|
|
12
|
+
`[DynamoDB] ${operationName} - ${timestamp}`,
|
|
13
|
+
'='.repeat(80),
|
|
14
|
+
];
|
|
15
|
+
if (config.logParams && params) {
|
|
16
|
+
parts.push('\n📤 Request Parameters:');
|
|
17
|
+
parts.push(JSON.stringify(params, null, 2));
|
|
18
|
+
}
|
|
19
|
+
if (config.logResponse && response) {
|
|
20
|
+
parts.push('\n📥 Response:');
|
|
21
|
+
parts.push(JSON.stringify(response, null, 2));
|
|
22
|
+
}
|
|
23
|
+
parts.push('='.repeat(80) + '\n');
|
|
24
|
+
return parts.join('\n');
|
|
25
|
+
};
|
|
26
|
+
/**
|
|
27
|
+
* Creates a DynamoDB logger instance with the given configuration
|
|
28
|
+
* This is the main factory function for creating loggers
|
|
29
|
+
*
|
|
30
|
+
* @example Basic logger with request parameters only
|
|
31
|
+
* ```typescript
|
|
32
|
+
* const logger = createDynamoDBLogger({
|
|
33
|
+
* enabled: true,
|
|
34
|
+
* logParams: true,
|
|
35
|
+
* logResponse: false,
|
|
36
|
+
* });
|
|
37
|
+
* ```
|
|
38
|
+
*
|
|
39
|
+
* @example Full logging (params + response)
|
|
40
|
+
* ```typescript
|
|
41
|
+
* const logger = createDynamoDBLogger({
|
|
42
|
+
* enabled: true,
|
|
43
|
+
* logParams: true,
|
|
44
|
+
* logResponse: true,
|
|
45
|
+
* });
|
|
46
|
+
* ```
|
|
47
|
+
*
|
|
48
|
+
* @example Using with a table
|
|
49
|
+
* ```typescript
|
|
50
|
+
* const logger = createDynamoDBLogger({
|
|
51
|
+
* enabled: true,
|
|
52
|
+
* logParams: true,
|
|
53
|
+
* logResponse: true,
|
|
54
|
+
* });
|
|
55
|
+
*
|
|
56
|
+
* const userTable = createTable({
|
|
57
|
+
* tableName: 'Users',
|
|
58
|
+
* client: dynamoDBClient,
|
|
59
|
+
* schema: userSchema,
|
|
60
|
+
* logger, // Pass logger to table
|
|
61
|
+
* });
|
|
62
|
+
*
|
|
63
|
+
* // Operations will be logged automatically
|
|
64
|
+
* const user = await userTable.get({ username: 'johndoe' }).execute();
|
|
65
|
+
* ```
|
|
66
|
+
*
|
|
67
|
+
* @example Custom logger function (Winston, Pino, etc.)
|
|
68
|
+
* ```typescript
|
|
69
|
+
* import winston from 'winston';
|
|
70
|
+
*
|
|
71
|
+
* const winstonLogger = winston.createLogger({
|
|
72
|
+
* level: 'info',
|
|
73
|
+
* format: winston.format.json(),
|
|
74
|
+
* transports: [new winston.transports.Console()],
|
|
75
|
+
* });
|
|
76
|
+
*
|
|
77
|
+
* const logger = createDynamoDBLogger({
|
|
78
|
+
* enabled: true,
|
|
79
|
+
* logParams: true,
|
|
80
|
+
* logResponse: true,
|
|
81
|
+
* loggerFn: (message) => winstonLogger.info(message),
|
|
82
|
+
* });
|
|
83
|
+
* ```
|
|
84
|
+
*
|
|
85
|
+
* @example Output format
|
|
86
|
+
* ```
|
|
87
|
+
* ================================================================================
|
|
88
|
+
* [DynamoDB] GetCommand - 2025-12-29T10:30:45.123Z
|
|
89
|
+
* ================================================================================
|
|
90
|
+
*
|
|
91
|
+
* 📤 Request Parameters:
|
|
92
|
+
* {
|
|
93
|
+
* "TableName": "Users",
|
|
94
|
+
* "Key": {
|
|
95
|
+
* "PK": "USER#johndoe",
|
|
96
|
+
* "SK": "PROFILE"
|
|
97
|
+
* }
|
|
98
|
+
* }
|
|
99
|
+
*
|
|
100
|
+
* 📥 Response:
|
|
101
|
+
* {
|
|
102
|
+
* "Item": {
|
|
103
|
+
* "PK": "USER#johndoe",
|
|
104
|
+
* "SK": "PROFILE",
|
|
105
|
+
* "username": "johndoe",
|
|
106
|
+
* "email": "john@example.com"
|
|
107
|
+
* }
|
|
108
|
+
* }
|
|
109
|
+
* ================================================================================
|
|
110
|
+
* ```
|
|
111
|
+
*/
|
|
112
|
+
const createDynamoDBLogger = (config) => {
|
|
113
|
+
const logFn = config.loggerFn || console.log;
|
|
114
|
+
return {
|
|
115
|
+
log: (operationName, params, response) => {
|
|
116
|
+
if (!config.enabled) {
|
|
117
|
+
return;
|
|
118
|
+
}
|
|
119
|
+
const timestamp = new Date().toISOString();
|
|
120
|
+
const message = formatLogMessage(operationName, timestamp, params, response, config);
|
|
121
|
+
logFn(message);
|
|
122
|
+
},
|
|
123
|
+
};
|
|
124
|
+
};
|
|
125
|
+
exports.createDynamoDBLogger = createDynamoDBLogger;
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { InferModel, ModelDefinition } from '@/core/types';
|
|
2
|
+
/**
|
|
3
|
+
* Extracts all variable names from a template string
|
|
4
|
+
* @param template - Template string with ${variable} syntax
|
|
5
|
+
* @returns Array of variable names found in the template
|
|
6
|
+
*/
|
|
7
|
+
export declare const extractTemplateVars: (template: string) => string[];
|
|
8
|
+
/**
|
|
9
|
+
* Resolves a string template with provided data
|
|
10
|
+
* @throws Error if any required template variable is missing from data
|
|
11
|
+
*/
|
|
12
|
+
export declare const resolveTemplate: (template: string, data: Record<string, any>) => string;
|
|
13
|
+
/**
|
|
14
|
+
* Resolves all keys or indexes for a model
|
|
15
|
+
*/
|
|
16
|
+
export declare const resolveKeys: <M extends ModelDefinition>(model: M, input: Record<string, any>, type?: "key" | "index" | "both") => Record<string, string>;
|
|
17
|
+
/**
|
|
18
|
+
* Applies default and generated values to validated input
|
|
19
|
+
*/
|
|
20
|
+
export declare const applyPostDefaults: <M extends ModelDefinition>(model: M, validatedItem: Record<string, any>, options?: {
|
|
21
|
+
isUpdate?: boolean;
|
|
22
|
+
timestamps?: boolean;
|
|
23
|
+
}) => InferModel<M>;
|
|
24
|
+
//# sourceMappingURL=model-utils.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"model-utils.d.ts","sourceRoot":"","sources":["../../src/utils/model-utils.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,UAAU,EAAiB,eAAe,EAAE,MAAM,cAAc,CAAC;AAG1E;;;;GAIG;AACH,eAAO,MAAM,mBAAmB,GAAI,UAAU,MAAM,KAAG,MAAM,EAG5D,CAAC;AAEF;;;GAGG;AACH,eAAO,MAAM,eAAe,GAAI,UAAU,MAAM,EAAE,MAAM,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,KAAG,MAoB7E,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,WAAW,GAAI,CAAC,SAAS,eAAe,EACnD,OAAO,CAAC,EACR,OAAO,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,EAC1B,OAAM,KAAK,GAAG,OAAO,GAAG,MAAc,KACrC,MAAM,CAAC,MAAM,EAAE,MAAM,CAWvB,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,iBAAiB,GAAI,CAAC,SAAS,eAAe,EACzD,OAAO,CAAC,EACR,eAAe,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,EAClC,UAAU;IAAE,QAAQ,CAAC,EAAE,OAAO,CAAC;IAAC,UAAU,CAAC,EAAE,OAAO,CAAA;CAAE,KACrD,UAAU,CAAC,CAAC,CAgCd,CAAC"}
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/* eslint-disable @typescript-eslint/no-explicit-any */
|
|
3
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
4
|
+
exports.applyPostDefaults = exports.resolveKeys = exports.resolveTemplate = exports.extractTemplateVars = void 0;
|
|
5
|
+
const ulid_1 = require("ulid");
|
|
6
|
+
/**
|
|
7
|
+
* Extracts all variable names from a template string
|
|
8
|
+
* @param template - Template string with ${variable} syntax
|
|
9
|
+
* @returns Array of variable names found in the template
|
|
10
|
+
*/
|
|
11
|
+
const extractTemplateVars = (template) => {
|
|
12
|
+
const matches = template.matchAll(/\${(.*?)}/g);
|
|
13
|
+
return Array.from(matches, (m) => m[1]).filter((v) => v !== undefined);
|
|
14
|
+
};
|
|
15
|
+
exports.extractTemplateVars = extractTemplateVars;
|
|
16
|
+
/**
|
|
17
|
+
* Resolves a string template with provided data
|
|
18
|
+
* @throws Error if any required template variable is missing from data
|
|
19
|
+
*/
|
|
20
|
+
const resolveTemplate = (template, data) => {
|
|
21
|
+
const missing = [];
|
|
22
|
+
const result = template.replace(/\${(.*?)}/g, (_, key) => {
|
|
23
|
+
const value = data[key];
|
|
24
|
+
if (value === undefined) {
|
|
25
|
+
missing.push(key);
|
|
26
|
+
return `\${${key}}`; // Keep placeholder for error message
|
|
27
|
+
}
|
|
28
|
+
return String(value);
|
|
29
|
+
});
|
|
30
|
+
if (missing.length > 0) {
|
|
31
|
+
throw new Error(`Missing required field(s) for key template: ${missing.join(', ')}. ` +
|
|
32
|
+
`Template: "${template}"`);
|
|
33
|
+
}
|
|
34
|
+
return result;
|
|
35
|
+
};
|
|
36
|
+
exports.resolveTemplate = resolveTemplate;
|
|
37
|
+
/**
|
|
38
|
+
* Resolves all keys or indexes for a model
|
|
39
|
+
*/
|
|
40
|
+
const resolveKeys = (model, input, type = 'key') => {
|
|
41
|
+
const out = {};
|
|
42
|
+
const process = (keys) => {
|
|
43
|
+
if (!keys)
|
|
44
|
+
return;
|
|
45
|
+
for (const [k, def] of Object.entries(keys)) {
|
|
46
|
+
out[k] = (0, exports.resolveTemplate)(def.value, input);
|
|
47
|
+
}
|
|
48
|
+
};
|
|
49
|
+
if (type === 'key' || type === 'both')
|
|
50
|
+
process(model.key);
|
|
51
|
+
if (type === 'index' || type === 'both')
|
|
52
|
+
process(model.index);
|
|
53
|
+
return out;
|
|
54
|
+
};
|
|
55
|
+
exports.resolveKeys = resolveKeys;
|
|
56
|
+
/**
|
|
57
|
+
* Applies default and generated values to validated input
|
|
58
|
+
*/
|
|
59
|
+
const applyPostDefaults = (model, validatedItem, options) => {
|
|
60
|
+
const result = { ...validatedItem };
|
|
61
|
+
for (const [key, attr] of Object.entries(model.attributes)) {
|
|
62
|
+
if (result[key] === undefined) {
|
|
63
|
+
if (attr.generate === 'ulid') {
|
|
64
|
+
result[key] = (0, ulid_1.ulid)();
|
|
65
|
+
}
|
|
66
|
+
else if (attr.generate === 'uuid') {
|
|
67
|
+
result[key] = crypto.randomUUID();
|
|
68
|
+
}
|
|
69
|
+
else if (attr.default !== undefined) {
|
|
70
|
+
result[key] = typeof attr.default === 'function' ? attr.default() : attr.default;
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
// Apply timestamps if enabled
|
|
75
|
+
const enableTimestamps = options?.timestamps ?? false;
|
|
76
|
+
const isUpdate = options?.isUpdate ?? false;
|
|
77
|
+
if (enableTimestamps) {
|
|
78
|
+
const now = new Date().toISOString();
|
|
79
|
+
// Only set createdAt on new items (not updates)
|
|
80
|
+
if (!isUpdate && result.createdAt === undefined) {
|
|
81
|
+
result.createdAt = now;
|
|
82
|
+
}
|
|
83
|
+
// Always set updatedAt
|
|
84
|
+
result.updatedAt = now;
|
|
85
|
+
}
|
|
86
|
+
return result;
|
|
87
|
+
};
|
|
88
|
+
exports.applyPostDefaults = applyPostDefaults;
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { AttributeDefinition, ModelDefinition } from '@/core/types';
|
|
2
|
+
import { ZodObject, ZodType } from 'zod';
|
|
3
|
+
/**
|
|
4
|
+
* Converts an attribute definition to a Zod schema type
|
|
5
|
+
*/
|
|
6
|
+
export declare const typeToZod: (attr: AttributeDefinition) => ZodType;
|
|
7
|
+
/**
|
|
8
|
+
* Converts a model definition to a Zod object schema
|
|
9
|
+
* Uses passthrough mode to allow additional fields like createdAt/updatedAt
|
|
10
|
+
* that are added by applyPostDefaults when timestamps are enabled
|
|
11
|
+
*/
|
|
12
|
+
export declare const modelToZod: (model: ModelDefinition) => ZodObject<any>;
|
|
13
|
+
//# sourceMappingURL=zod-utils.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"zod-utils.d.ts","sourceRoot":"","sources":["../../src/utils/zod-utils.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,mBAAmB,EAAE,eAAe,EAAE,MAAM,cAAc,CAAC;AACpE,OAAO,EAAK,SAAS,EAAE,OAAO,EAAE,MAAM,KAAK,CAAC;AAE5C;;GAEG;AACH,eAAO,MAAM,SAAS,GAAI,MAAM,mBAAmB,KAAG,OAarD,CAAC;AAEF;;;;GAIG;AACH,eAAO,MAAM,UAAU,GAAI,OAAO,eAAe,KAAG,SAAS,CAAC,GAAG,CAMhE,CAAC"}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/* eslint-disable @typescript-eslint/no-explicit-any */
|
|
3
|
+
// -------------------- Zod Conversion --------------------
|
|
4
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
5
|
+
exports.modelToZod = exports.typeToZod = void 0;
|
|
6
|
+
const zod_1 = require("zod");
|
|
7
|
+
/**
|
|
8
|
+
* Converts an attribute definition to a Zod schema type
|
|
9
|
+
*/
|
|
10
|
+
const typeToZod = (attr) => {
|
|
11
|
+
const zodType = attr.type === String
|
|
12
|
+
? zod_1.z.string()
|
|
13
|
+
: attr.type === Number
|
|
14
|
+
? zod_1.z.number()
|
|
15
|
+
: attr.type === Boolean
|
|
16
|
+
? zod_1.z.boolean()
|
|
17
|
+
: attr.type === Date
|
|
18
|
+
? zod_1.z.date()
|
|
19
|
+
: zod_1.z.unknown();
|
|
20
|
+
return attr.required ? zodType : zodType.optional();
|
|
21
|
+
};
|
|
22
|
+
exports.typeToZod = typeToZod;
|
|
23
|
+
/**
|
|
24
|
+
* Converts a model definition to a Zod object schema
|
|
25
|
+
* Uses passthrough mode to allow additional fields like createdAt/updatedAt
|
|
26
|
+
* that are added by applyPostDefaults when timestamps are enabled
|
|
27
|
+
*/
|
|
28
|
+
const modelToZod = (model) => {
|
|
29
|
+
const shape = {};
|
|
30
|
+
for (const [key, attr] of Object.entries(model.attributes)) {
|
|
31
|
+
shape[key] = (0, exports.typeToZod)(attr);
|
|
32
|
+
}
|
|
33
|
+
return zod_1.z.object(shape).passthrough();
|
|
34
|
+
};
|
|
35
|
+
exports.modelToZod = modelToZod;
|
package/jest.config.js
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/** @type {import('jest').Config} */
|
|
2
|
+
module.exports = {
|
|
3
|
+
preset: 'ts-jest',
|
|
4
|
+
testEnvironment: 'node',
|
|
5
|
+
testMatch: ['**/?(*.)+(test).[tj]s'],
|
|
6
|
+
testPathIgnorePatterns: ['/node_modules/', '/dist/'],
|
|
7
|
+
roots: ['<rootDir>/src', '<rootDir>/tests'],
|
|
8
|
+
moduleNameMapper: {
|
|
9
|
+
'^@/(.*)$': '<rootDir>/src/$1',
|
|
10
|
+
},
|
|
11
|
+
};
|
package/package.json
ADDED
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@ftschopp/dynatable-core",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "Core library for DynamoDB single table design",
|
|
5
|
+
"main": "dist/index.js",
|
|
6
|
+
"types": "dist/index.d.ts",
|
|
7
|
+
"publishConfig": {
|
|
8
|
+
"access": "public"
|
|
9
|
+
},
|
|
10
|
+
"scripts": {
|
|
11
|
+
"build": "tsc",
|
|
12
|
+
"clean": "rm -rf .turbo && rm -rf node_modules && rm -rf dist",
|
|
13
|
+
"test": "jest"
|
|
14
|
+
},
|
|
15
|
+
"devDependencies": {
|
|
16
|
+
"@repo/eslint-config": "*",
|
|
17
|
+
"@repo/typescript-config": "*",
|
|
18
|
+
"@types/jest": "^30.0.0",
|
|
19
|
+
"@types/node": "^25.0.3",
|
|
20
|
+
"aws-sdk-client-mock": "^4.1.0",
|
|
21
|
+
"eslint": "^9.39.2",
|
|
22
|
+
"jest": "^30.2.0",
|
|
23
|
+
"ts-jest": "^29.4.6",
|
|
24
|
+
"ts-node": "^10.9.2",
|
|
25
|
+
"typescript": "5.9.3"
|
|
26
|
+
},
|
|
27
|
+
"dependencies": {
|
|
28
|
+
"@aws-sdk/client-dynamodb": "^3.965.0",
|
|
29
|
+
"@aws-sdk/lib-dynamodb": "^3.965.0",
|
|
30
|
+
"@aws-sdk/util-dynamodb": "^3.965.0",
|
|
31
|
+
"@types/ramda": "^0.31.1",
|
|
32
|
+
"ramda": "^0.32.0",
|
|
33
|
+
"ulid": "^3.0.2",
|
|
34
|
+
"zod": "^4.3.5"
|
|
35
|
+
}
|
|
36
|
+
}
|