inanis 0.0.7-beta.15 → 0.0.7-beta.18
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/document-db/table-dynamo.js +10 -6
- package/dist/modules/data-model.d.ts +2 -0
- package/dist/modules/data-model.js +6 -0
- package/dist/stream/context.js +1 -1
- package/dist/stream/index.js +61 -12
- package/dist/stream/method.d.ts +1 -1
- package/dist/stream/method.js +9 -11
- package/package.json +4 -5
|
@@ -256,10 +256,12 @@ export class DynamoDbTable {
|
|
|
256
256
|
'#updatedAt': 'updatedAt'
|
|
257
257
|
};
|
|
258
258
|
for (let key in data) {
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
259
|
+
if (data[key] != null) {
|
|
260
|
+
let [mode, value] = data[key];
|
|
261
|
+
ExpressionAttributeValues[`:${key}`] = value;
|
|
262
|
+
ExpressionAttributeNames[`#${key}`] = key;
|
|
263
|
+
UpdateExpressions.push(`#${key} = #${key} ${mode} :${key}`);
|
|
264
|
+
}
|
|
263
265
|
}
|
|
264
266
|
await service.update({
|
|
265
267
|
TableName: this.tableName,
|
|
@@ -279,7 +281,8 @@ export class DynamoDbTable {
|
|
|
279
281
|
'#updatedAt': 'updatedAt'
|
|
280
282
|
};
|
|
281
283
|
for (let key in data) {
|
|
282
|
-
|
|
284
|
+
const value = data[key] == null ? null : data[key];
|
|
285
|
+
ExpressionAttributeValues[`:${key}`] = value;
|
|
283
286
|
ExpressionAttributeNames[`#${key}`] = key;
|
|
284
287
|
UpdateExpressions.push(`#${key} = :${key}`);
|
|
285
288
|
}
|
|
@@ -304,7 +307,8 @@ export class DynamoDbTable {
|
|
|
304
307
|
'#updatedAt': 'updatedAt'
|
|
305
308
|
};
|
|
306
309
|
for (let key in data) {
|
|
307
|
-
|
|
310
|
+
const value = data[key] == null ? null : data[key];
|
|
311
|
+
ExpressionAttributeValues[`:${key}`] = value;
|
|
308
312
|
ExpressionAttributeNames[`#${key}`] = key;
|
|
309
313
|
UpdateExpressions.push(`#${key} = :${key}`);
|
|
310
314
|
}
|
|
@@ -58,6 +58,8 @@ export declare class DataModel<T extends DataModelConfig<any, any, any>, D exten
|
|
|
58
58
|
data: D;
|
|
59
59
|
constructor(config: T, data: T['_initData']);
|
|
60
60
|
getPublic(): Pick<D, PublicKey>;
|
|
61
|
+
getCreateAt(): any;
|
|
62
|
+
getUpdateAt(): any;
|
|
61
63
|
copy(): this;
|
|
62
64
|
from(source: Partial<D> | DataModel<T, D, PublicKey>): void;
|
|
63
65
|
save(reader?: (_data: D) => Partial<D>): Promise<void>;
|
|
@@ -96,6 +96,12 @@ export class DataModel {
|
|
|
96
96
|
}
|
|
97
97
|
return output;
|
|
98
98
|
}
|
|
99
|
+
getCreateAt() {
|
|
100
|
+
return this.data.createdAt;
|
|
101
|
+
}
|
|
102
|
+
getUpdateAt() {
|
|
103
|
+
return this.data.updatedAt;
|
|
104
|
+
}
|
|
99
105
|
copy() {
|
|
100
106
|
const newData = structuredClone(this.data);
|
|
101
107
|
const model = new DataModel(this._config, newData);
|
package/dist/stream/context.js
CHANGED
|
@@ -29,10 +29,10 @@ export class StreamRouterContext {
|
|
|
29
29
|
name: `${this.method.action}@${this.method.router.path}`,
|
|
30
30
|
interceptorMessage: (data) => data
|
|
31
31
|
});
|
|
32
|
+
this.failMessages = this.method.failMessages;
|
|
32
33
|
this.interaction.on('action', step => {
|
|
33
34
|
this.interactionStepMessage = step.message;
|
|
34
35
|
});
|
|
35
|
-
// 綁定協助解構
|
|
36
36
|
const methods = Object.getOwnPropertyNames(StreamRouterContext.prototype);
|
|
37
37
|
for (let key of methods) {
|
|
38
38
|
if (key !== 'on' && key !== 'constructor' && typeof this[key] === 'function') {
|
package/dist/stream/index.js
CHANGED
|
@@ -5,15 +5,6 @@ import { rootException } from '../exception.js';
|
|
|
5
5
|
import { exportOpenApi } from './export-open-api.js';
|
|
6
6
|
import { Router } from './router.js';
|
|
7
7
|
import { toRouterName } from '../utils/string.js';
|
|
8
|
-
import { streamifyResponse, isInAWS } from 'lambda-stream';
|
|
9
|
-
if (isInAWS() === false) {
|
|
10
|
-
global['awslambda'] = {
|
|
11
|
-
streamifyResponse,
|
|
12
|
-
HttpResponseStream: {
|
|
13
|
-
from: () => null
|
|
14
|
-
}
|
|
15
|
-
};
|
|
16
|
-
}
|
|
17
8
|
const exception = rootException.checkout('APIManager');
|
|
18
9
|
const getLambdaGroup = (manager, method, path) => {
|
|
19
10
|
let sourcePath = `${method}@${path}`;
|
|
@@ -96,7 +87,8 @@ export class StreamAPIManager extends Event {
|
|
|
96
87
|
return null;
|
|
97
88
|
}
|
|
98
89
|
getMethod(path, method) {
|
|
99
|
-
let
|
|
90
|
+
let targetPath = path.endsWith('-no-stream') ? path.slice(0, -10) : path;
|
|
91
|
+
let router = this.getRouter(targetPath);
|
|
100
92
|
if (router == null) {
|
|
101
93
|
return null;
|
|
102
94
|
}
|
|
@@ -128,6 +120,7 @@ export class StreamAPIManager extends Event {
|
|
|
128
120
|
const outputs = {};
|
|
129
121
|
this.eachMethods((router, method) => {
|
|
130
122
|
const appendHandleName = 'Stream';
|
|
123
|
+
const isOffline = !!this.params.serverless?.isOffline;
|
|
131
124
|
const group = getLambdaGroup(this, method, router.path);
|
|
132
125
|
const handlerName = group.handlerName + appendHandleName;
|
|
133
126
|
if (outputs[handlerName] == null) {
|
|
@@ -142,7 +135,6 @@ export class StreamAPIManager extends Event {
|
|
|
142
135
|
};
|
|
143
136
|
responseStream = awslambda.HttpResponseStream.from(responseStream, httpResponseMetadata);
|
|
144
137
|
let callPath = event.requestContext.resourcePath;
|
|
145
|
-
let isOffline = !!this.params.serverless?.isOffline;
|
|
146
138
|
if (isOffline) {
|
|
147
139
|
callPath = '/' + callPath.split('/').slice(2).join('/');
|
|
148
140
|
}
|
|
@@ -152,6 +144,50 @@ export class StreamAPIManager extends Event {
|
|
|
152
144
|
}
|
|
153
145
|
await method.outputs.lambdaHandler(event, responseStream);
|
|
154
146
|
});
|
|
147
|
+
outputs[handlerName + 'NoStream'] = (event) => {
|
|
148
|
+
return new Promise((resolve) => {
|
|
149
|
+
let chunk = '';
|
|
150
|
+
const headers = {
|
|
151
|
+
'Content-Type': 'text/plain; charset=UTF-8',
|
|
152
|
+
'Access-Control-Allow-Origin': '*',
|
|
153
|
+
'Access-Control-Allow-Credentials': 'true'
|
|
154
|
+
};
|
|
155
|
+
const streamEvent = new Event();
|
|
156
|
+
const responseStream = {
|
|
157
|
+
on: streamEvent.on.bind(streamEvent),
|
|
158
|
+
end: () => {
|
|
159
|
+
streamEvent.emit('close', {});
|
|
160
|
+
resolve({
|
|
161
|
+
headers,
|
|
162
|
+
statusCode: 200,
|
|
163
|
+
body: chunk
|
|
164
|
+
});
|
|
165
|
+
},
|
|
166
|
+
write: (data) => {
|
|
167
|
+
chunk += data;
|
|
168
|
+
}
|
|
169
|
+
};
|
|
170
|
+
let callPath = event.requestContext.resourcePath;
|
|
171
|
+
if (isOffline) {
|
|
172
|
+
callPath = '/' + callPath.split('/').slice(2).join('/');
|
|
173
|
+
}
|
|
174
|
+
let method = this.getMethod(callPath, event.httpMethod.toLocaleLowerCase());
|
|
175
|
+
if (method == null) {
|
|
176
|
+
throw exception.create('No Stream Method Found');
|
|
177
|
+
}
|
|
178
|
+
method
|
|
179
|
+
.outputs
|
|
180
|
+
.lambdaHandler(event, responseStream)
|
|
181
|
+
.catch(err => {
|
|
182
|
+
console.error(err);
|
|
183
|
+
resolve({
|
|
184
|
+
headers,
|
|
185
|
+
statusCode: 400,
|
|
186
|
+
body: 'unknown error'
|
|
187
|
+
});
|
|
188
|
+
});
|
|
189
|
+
});
|
|
190
|
+
};
|
|
155
191
|
}
|
|
156
192
|
});
|
|
157
193
|
return outputs;
|
|
@@ -169,17 +205,30 @@ export class StreamAPIManager extends Event {
|
|
|
169
205
|
memorySize: group.memorySize,
|
|
170
206
|
events: []
|
|
171
207
|
};
|
|
208
|
+
outputs[group.name + 'NoStream'] = {
|
|
209
|
+
handler: group.handler + 'NoStream',
|
|
210
|
+
memorySize: group.memorySize,
|
|
211
|
+
events: []
|
|
212
|
+
};
|
|
172
213
|
if (params.handler) {
|
|
173
214
|
let newGroup = params.handler(outputs[group.name]);
|
|
174
215
|
if (newGroup) {
|
|
175
216
|
outputs[group.name] = newGroup;
|
|
176
217
|
}
|
|
218
|
+
let newNoStreamGroup = params.handler(outputs[group.name + 'NoStream']);
|
|
219
|
+
if (newNoStreamGroup) {
|
|
220
|
+
outputs[group.name + 'NoStream'] = newNoStreamGroup;
|
|
221
|
+
}
|
|
177
222
|
}
|
|
178
223
|
}
|
|
179
224
|
const m = router.methods[method];
|
|
180
225
|
const output = outputs[group.name];
|
|
226
|
+
const noStreamOutput = outputs[group.name + 'NoStream'];
|
|
181
227
|
output.events.push({
|
|
182
|
-
http: m.outputs.getServerlessHttp()
|
|
228
|
+
http: m.outputs.getServerlessHttp(true)
|
|
229
|
+
});
|
|
230
|
+
noStreamOutput.events.push({
|
|
231
|
+
http: m.outputs.getServerlessHttp(false)
|
|
183
232
|
});
|
|
184
233
|
});
|
|
185
234
|
return toOutputData(outputs);
|
package/dist/stream/method.d.ts
CHANGED
|
@@ -52,7 +52,7 @@ export declare class Method<Path extends string = any, Fails extends FailData =
|
|
|
52
52
|
run(context: StreamRouterContext): Promise<void>;
|
|
53
53
|
get outputs(): {
|
|
54
54
|
lambdaHandler: (event: APIGatewayEvent, responseStream: ResponseStream) => Promise<void>;
|
|
55
|
-
getServerlessHttp: () => Record<string, any>;
|
|
55
|
+
getServerlessHttp: (isStream: boolean) => Record<string, any>;
|
|
56
56
|
openApiPathItem: () => {
|
|
57
57
|
tags?: string[];
|
|
58
58
|
summary?: string;
|
package/dist/stream/method.js
CHANGED
|
@@ -51,6 +51,7 @@ export class Method {
|
|
|
51
51
|
await context.hook.notify('fail', {
|
|
52
52
|
error
|
|
53
53
|
});
|
|
54
|
+
throw error;
|
|
54
55
|
}
|
|
55
56
|
}
|
|
56
57
|
// =================
|
|
@@ -62,14 +63,9 @@ export class Method {
|
|
|
62
63
|
lambdaHandler: async (event, responseStream) => {
|
|
63
64
|
await this.inanis._install();
|
|
64
65
|
const context = await StreamRouterContext.fromAwsLambda(this, event, responseStream);
|
|
65
|
-
|
|
66
|
-
await this.run(context);
|
|
67
|
-
}
|
|
68
|
-
catch (error) {
|
|
69
|
-
console.log('response parse error:', error);
|
|
70
|
-
}
|
|
66
|
+
await this.run(context);
|
|
71
67
|
},
|
|
72
|
-
getServerlessHttp: () => {
|
|
68
|
+
getServerlessHttp: (isStream) => {
|
|
73
69
|
const http = {
|
|
74
70
|
cors: {
|
|
75
71
|
origin: '*',
|
|
@@ -80,12 +76,14 @@ export class Method {
|
|
|
80
76
|
...this.allowHeaders
|
|
81
77
|
]
|
|
82
78
|
},
|
|
83
|
-
path: this.router.path,
|
|
79
|
+
path: isStream === false ? this.router.path + '-no-stream' : this.router.path,
|
|
84
80
|
method: this.action,
|
|
85
81
|
authorizer: undefined,
|
|
86
|
-
response:
|
|
87
|
-
|
|
88
|
-
|
|
82
|
+
response: isStream === false
|
|
83
|
+
? undefined
|
|
84
|
+
: {
|
|
85
|
+
transferMode: 'STREAM'
|
|
86
|
+
}
|
|
89
87
|
};
|
|
90
88
|
if (this.router.nowAuthorizerExpression) {
|
|
91
89
|
http.authorizer = this.router.nowAuthorizerExpression.name;
|
package/package.json
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "inanis",
|
|
3
3
|
"type": "module",
|
|
4
|
-
"version": "0.0.7-beta.
|
|
4
|
+
"version": "0.0.7-beta.18",
|
|
5
5
|
"description": "Micro Service Best Tools.",
|
|
6
6
|
"main": "./dist/index.js",
|
|
7
7
|
"scripts": {
|
|
8
8
|
"test": "nyc mocha ./lib/**/*.test.ts ./lib/*.test.ts",
|
|
9
9
|
"build": "eslint 'src/**/*.{ts,tsx}' --fix && tsc",
|
|
10
|
-
"deploy": "
|
|
10
|
+
"deploy": "esno ./deploy.ts"
|
|
11
11
|
},
|
|
12
12
|
"bin": {
|
|
13
13
|
"ms-be-lib": "cli/index.js"
|
|
@@ -36,13 +36,13 @@
|
|
|
36
36
|
"cross-env": "^10.0.0",
|
|
37
37
|
"debug": "^4.4.1",
|
|
38
38
|
"eslint": "^9.32.0",
|
|
39
|
+
"esno": "^4.8.0",
|
|
39
40
|
"mocha": "^11.7.1",
|
|
40
41
|
"nyc": "^17.1.0",
|
|
41
42
|
"openapi-types": "^12.1.3",
|
|
42
43
|
"semver": "^7.7.2",
|
|
43
44
|
"supports-color": "^10.0.0",
|
|
44
45
|
"ts-loader": "^9.5.2",
|
|
45
|
-
"ts-node": "^10.9.2",
|
|
46
46
|
"typescript": "^5.8.3",
|
|
47
47
|
"typescript-eslint": "^8.38.0"
|
|
48
48
|
},
|
|
@@ -65,7 +65,6 @@
|
|
|
65
65
|
"json-schema-to-typescript": "^15.0.4",
|
|
66
66
|
"json-to-pretty-yaml": "^1.2.2",
|
|
67
67
|
"jsonwebtoken": "^9.0.2",
|
|
68
|
-
"lambda-stream": "^0.6.0",
|
|
69
68
|
"mime": "^4.1.0",
|
|
70
69
|
"mongodb": "^7.0.0",
|
|
71
70
|
"node-rsa": "^1.1.1",
|
|
@@ -78,4 +77,4 @@
|
|
|
78
77
|
"zod": "^4.2.1"
|
|
79
78
|
},
|
|
80
79
|
"packageManager": "yarn@4.1.1"
|
|
81
|
-
}
|
|
80
|
+
}
|