lemon-core 5.0.3 → 5.0.5
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/bin/lemon-fields-types.mjs +12 -0
- package/bin/lib/fields-types.mjs +629 -0
- package/dist/common/test-helper.js +6 -3
- package/dist/common/test-helper.js.map +1 -1
- package/dist/cores/api/api-service.js +2 -2
- package/dist/cores/api/api-service.js.map +1 -1
- package/dist/cores/aws/aws-s3-service.js +2 -2
- package/dist/cores/aws/aws-s3-service.js.map +1 -1
- package/dist/cores/aws/aws-sns-service.d.ts +6 -0
- package/dist/cores/aws/aws-sns-service.js +22 -3
- package/dist/cores/aws/aws-sns-service.js.map +1 -1
- package/dist/cores/aws/aws-sqs-service.js +5 -0
- package/dist/cores/aws/aws-sqs-service.js.map +1 -1
- package/dist/cores/config/config-service.js +3 -1
- package/dist/cores/config/config-service.js.map +1 -1
- package/dist/cores/lambda/lambda-handler.js +4 -1
- package/dist/cores/lambda/lambda-handler.js.map +1 -1
- package/dist/cores/lambda/lambda-notification-handler.js +4 -1
- package/dist/cores/lambda/lambda-notification-handler.js.map +1 -1
- package/dist/cores/lambda/lambda-web-handler.js +23 -10
- package/dist/cores/lambda/lambda-web-handler.js.map +1 -1
- package/dist/cores/protocol/aws-lambda-helper.d.ts +13 -0
- package/dist/cores/protocol/aws-lambda-helper.js +64 -41
- package/dist/cores/protocol/aws-lambda-helper.js.map +1 -1
- package/dist/cores/protocol/local-transport.d.ts +135 -0
- package/dist/cores/protocol/local-transport.js +392 -0
- package/dist/cores/protocol/local-transport.js.map +1 -0
- package/dist/cores/protocol/protocol-service.d.ts +3 -2
- package/dist/cores/protocol/protocol-service.js +33 -10
- package/dist/cores/protocol/protocol-service.js.map +1 -1
- package/dist/cores/protocol/protocol-sign.d.ts +12 -0
- package/dist/cores/protocol/protocol-sign.js +17 -1
- package/dist/cores/protocol/protocol-sign.js.map +1 -1
- package/dist/engine/engine.js +26 -13
- package/dist/engine/engine.js.map +1 -1
- package/dist/engine/utilities.d.ts +2 -2
- package/dist/engine/utilities.js +6 -39
- package/dist/engine/utilities.js.map +1 -1
- package/dist/esm/index.mjs +1 -0
- package/dist/helpers/helpers.js +3 -7
- package/dist/helpers/helpers.js.map +1 -1
- package/dist/index.d.ts +3 -0
- package/dist/index.js +4 -1
- package/dist/index.js.map +1 -1
- package/dist/lib/log-mask.d.ts +19 -0
- package/dist/lib/log-mask.js +55 -0
- package/dist/lib/log-mask.js.map +1 -0
- package/dist/lib/qs-compat.d.ts +11 -0
- package/dist/lib/qs-compat.js +89 -0
- package/dist/lib/qs-compat.js.map +1 -0
- package/dist/lib/safe-json.d.ts +23 -0
- package/dist/lib/safe-json.js +78 -0
- package/dist/lib/safe-json.js.map +1 -0
- package/package.json +32 -25
|
@@ -0,0 +1,392 @@
|
|
|
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 () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
36
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
37
|
+
};
|
|
38
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
39
|
+
exports.$localTransport = exports.deliveries = exports.drain = exports.localWeb = exports.localSqs = exports.localSns = exports.selfHostOf = exports.queueOf = exports.topicOf = exports.isActive = exports.transportLog = exports.LOCAL_TRANSPORT_CAP = exports.LOCAL_ACCOUNT_ID = exports.LOCAL_TRANSPORT = void 0;
|
|
40
|
+
/**
|
|
41
|
+
* `local-transport.ts`
|
|
42
|
+
* - opt-in local transport (mock delivery): in local mode, `sns.publish()`, `sqs.sendMessage()` and the protocol
|
|
43
|
+
* `execute/notify/enqueue/broadcast` deliver to this service in-process, with no AWS SDK client.
|
|
44
|
+
* - on only if env `LOCAL_TRANSPORT=mock` and `$U.isLocalMode()` (`LOCAL_MODE=1`, no `AWS_LAMBDA_FUNCTION_NAME`).
|
|
45
|
+
* in Lambda the env is ignored (one warn line). without the env nothing changes.
|
|
46
|
+
* - self only: a target that is not this service throws `501 NOT SUPPORTED` (no AWS call, no silent drop).
|
|
47
|
+
* no target and no env `MY_SNS_ENDPOINT`/`MY_SQS_ENDPOINT` (a local run) = this service's topic/queue.
|
|
48
|
+
* - fidelity: each delivery is a real Lambda event record, run by the engine's `LambdaHandler.handle()`.
|
|
49
|
+
* SNS/SQS kinds are async (`setImmediate`), `execute` is sync. `drain()` waits for all and returns them.
|
|
50
|
+
* - loop guard: over `LOCAL_TRANSPORT_CAP` (deliveries in one burst, or chain depth) → `508 LOOP DETECTED`.
|
|
51
|
+
* a burst ends at `drain()` or when nothing is pending (idle), so a long-running server never stays capped.
|
|
52
|
+
* - keeps only the last `LOCAL_TRANSPORT_CAP.kept` (100) finished deliveries (the oldest are dropped).
|
|
53
|
+
*
|
|
54
|
+
*
|
|
55
|
+
* @author Steve Jung <steve@lemoncloud.io>
|
|
56
|
+
* @date 2026-10-30 initial version.
|
|
57
|
+
* @date 2026-10-30 the burst count resets when idle (not only at `drain()`); keep the last 100 deliveries.
|
|
58
|
+
*
|
|
59
|
+
* @copyright (C) lemoncloud.io 2026 - All Rights Reserved.
|
|
60
|
+
*/
|
|
61
|
+
const async_hooks_1 = require("async_hooks");
|
|
62
|
+
const crypto_1 = require("crypto");
|
|
63
|
+
const url_1 = __importDefault(require("url"));
|
|
64
|
+
const engine_1 = require("../../engine/");
|
|
65
|
+
const test_helper_1 = require("../../common/test-helper");
|
|
66
|
+
//* lazy namespace: this file is in the engine closure (via `aws-sns-service`), so nothing runs `$U` at load.
|
|
67
|
+
const NS = (() => {
|
|
68
|
+
let ns;
|
|
69
|
+
return () => (ns ??= engine_1.$U.NS('MOCK', 'magenta'));
|
|
70
|
+
})();
|
|
71
|
+
/**
|
|
72
|
+
* env name of the local transport (`mock` = on, in local mode only).
|
|
73
|
+
*/
|
|
74
|
+
exports.LOCAL_TRANSPORT = 'LOCAL_TRANSPORT';
|
|
75
|
+
/**
|
|
76
|
+
* placeholder account of the local ARNs, URLs and the fake Lambda context.
|
|
77
|
+
*/
|
|
78
|
+
exports.LOCAL_ACCOUNT_ID = '000000000000';
|
|
79
|
+
/**
|
|
80
|
+
* loop guard: max deliveries in one burst (until `drain()` or idle), and max chain depth (a send from a delivery is +1).
|
|
81
|
+
* - `kept`: max finished deliveries kept for `drain()`/`deliveries()` (the oldest are dropped).
|
|
82
|
+
*/
|
|
83
|
+
exports.LOCAL_TRANSPORT_CAP = { deliveries: 50, depth: 8, kept: 100 };
|
|
84
|
+
/**
|
|
85
|
+
* the log writer (one `_inf` line); an object, so a spec can spy on `inf`.
|
|
86
|
+
*/
|
|
87
|
+
exports.transportLog = {
|
|
88
|
+
inf: (line) => (0, engine_1._inf)(NS(), line),
|
|
89
|
+
};
|
|
90
|
+
//* chain of the current delivery: `depth` (1 = sent by a client request), `async` (inside an SNS/SQS delivery).
|
|
91
|
+
const $chain = new async_hooks_1.AsyncLocalStorage();
|
|
92
|
+
//* process-wide state: pending deliveries, running sync `execute()`s, finished deliveries, count in this burst,
|
|
93
|
+
//* cap logged, warned keys.
|
|
94
|
+
const $state = {
|
|
95
|
+
pending: new Set(),
|
|
96
|
+
running: 0,
|
|
97
|
+
list: [],
|
|
98
|
+
count: 0,
|
|
99
|
+
capped: false,
|
|
100
|
+
warned: new Set(),
|
|
101
|
+
};
|
|
102
|
+
//* keep one finished delivery (the last `LOCAL_TRANSPORT_CAP.kept` only).
|
|
103
|
+
const record = (delivery) => {
|
|
104
|
+
$state.list.push(delivery);
|
|
105
|
+
if ($state.list.length > exports.LOCAL_TRANSPORT_CAP.kept)
|
|
106
|
+
$state.list.splice(0, $state.list.length - exports.LOCAL_TRANSPORT_CAP.kept);
|
|
107
|
+
};
|
|
108
|
+
//* end of a burst: nothing pending and no sync `execute()` running → reset the count and the cap line.
|
|
109
|
+
const resetIfIdle = () => {
|
|
110
|
+
if ($state.pending.size || $state.running)
|
|
111
|
+
return;
|
|
112
|
+
$state.count = 0;
|
|
113
|
+
$state.capped = false;
|
|
114
|
+
};
|
|
115
|
+
//* the configured region (env `REGION`, as the SNS service).
|
|
116
|
+
const region = () => `${engine_1.$engine.environ('REGION', 'ap-northeast-2') || 'ap-northeast-2'}`;
|
|
117
|
+
//* log one warn line per reason (never twice in a process).
|
|
118
|
+
const warnOnce = (key, line) => {
|
|
119
|
+
if ($state.warned.has(key))
|
|
120
|
+
return;
|
|
121
|
+
$state.warned.add(key);
|
|
122
|
+
exports.transportLog.inf(line);
|
|
123
|
+
};
|
|
124
|
+
/**
|
|
125
|
+
* true if the local transport is on: env `LOCAL_TRANSPORT=mock` and local mode (never in Lambda).
|
|
126
|
+
* - read from `process.env` on every call. an ignored value logs one warn line.
|
|
127
|
+
*/
|
|
128
|
+
const isActive = () => {
|
|
129
|
+
const val = `${process.env[exports.LOCAL_TRANSPORT] ?? ''}`;
|
|
130
|
+
if (!val)
|
|
131
|
+
return false;
|
|
132
|
+
//* the reason to ignore ('' = active).
|
|
133
|
+
const why = val !== 'mock'
|
|
134
|
+
? 'unknown value'
|
|
135
|
+
: process.env.AWS_LAMBDA_FUNCTION_NAME
|
|
136
|
+
? 'in Lambda'
|
|
137
|
+
: !engine_1.$U.isLocalMode()
|
|
138
|
+
? 'not local mode'
|
|
139
|
+
: '';
|
|
140
|
+
if (!why)
|
|
141
|
+
return true;
|
|
142
|
+
warnOnce(`${val}/${why}`, `WARN! env.${exports.LOCAL_TRANSPORT}[${val.substring(0, 32)}] is ignored - ${why}`);
|
|
143
|
+
return false;
|
|
144
|
+
};
|
|
145
|
+
exports.isActive = isActive;
|
|
146
|
+
//* topic name of an SNS target: `arn:aws:sns:<region>:<account>:<topic>` → `<topic>`, a name as is.
|
|
147
|
+
const topicOf = (target) => `${target || ''}`.split(':').pop() || '';
|
|
148
|
+
exports.topicOf = topicOf;
|
|
149
|
+
//* queue name of an SQS endpoint: `https://sqs.<region>.amazonaws.com/<account>/<queue>` → `<queue>`, a name as is.
|
|
150
|
+
const queueOf = (endpoint) => `${endpoint || ''}`
|
|
151
|
+
.split('/')
|
|
152
|
+
.filter(_ => !!_)
|
|
153
|
+
.pop() || '';
|
|
154
|
+
exports.queueOf = queueOf;
|
|
155
|
+
//* host of a protocol uri like `sns://<acct>@<host>/<path>#<ver>`.
|
|
156
|
+
const hostOf = (uri) => `${url_1.default.parse(uri).hostname || ''}`;
|
|
157
|
+
/**
|
|
158
|
+
* host of this service by protocol (`sns://self`, `sqs://self`, `web://self`).
|
|
159
|
+
*
|
|
160
|
+
* @param type protocol type.
|
|
161
|
+
* @param service (optional) the protocol service (default: the engine's).
|
|
162
|
+
* @param config (optional) its config service.
|
|
163
|
+
*/
|
|
164
|
+
const selfHostOf = async (type, service, config) => {
|
|
165
|
+
//* lazy: the protocol module loads the AWS services (no import cycle at load).
|
|
166
|
+
const svc = service ?? (await Promise.resolve().then(() => __importStar(require('./index')))).default.service;
|
|
167
|
+
return hostOf(svc.asProtocolURI(type, { service: 'self' }, config));
|
|
168
|
+
};
|
|
169
|
+
exports.selfHostOf = selfHostOf;
|
|
170
|
+
//* throw `501` if the name is not one of this service's names.
|
|
171
|
+
const assertSelf = (name, selves) => {
|
|
172
|
+
if (!name || !selves.filter(_ => !!_).includes(name))
|
|
173
|
+
throw new Error(`501 NOT SUPPORTED - local transport: ${name} is not this service`);
|
|
174
|
+
};
|
|
175
|
+
//* loop guard: admit one delivery (returns its depth), or refuse with `508` (one `[MOCK] cap` line until `drain()`).
|
|
176
|
+
const admit = (kind, target) => {
|
|
177
|
+
const depth = ($chain.getStore()?.depth ?? 0) + 1;
|
|
178
|
+
if ($state.count >= exports.LOCAL_TRANSPORT_CAP.deliveries || depth > exports.LOCAL_TRANSPORT_CAP.depth) {
|
|
179
|
+
if (!$state.capped) {
|
|
180
|
+
$state.capped = true;
|
|
181
|
+
exports.transportLog.inf(`[MOCK] cap kind=${kind} target=${target} deliveries=${$state.count} depth=${depth}`);
|
|
182
|
+
}
|
|
183
|
+
const error = `508 LOOP DETECTED - local transport`;
|
|
184
|
+
record({ kind, target, messageId: '', error });
|
|
185
|
+
throw new Error(error);
|
|
186
|
+
}
|
|
187
|
+
$state.count++;
|
|
188
|
+
return depth;
|
|
189
|
+
};
|
|
190
|
+
//* a fake Lambda context of this service (placeholder account).
|
|
191
|
+
const asContext = (name) => ({
|
|
192
|
+
callbackWaitsForEmptyEventLoop: true,
|
|
193
|
+
functionName: name,
|
|
194
|
+
functionVersion: '$LATEST',
|
|
195
|
+
invokedFunctionArn: `arn:aws:lambda:${region()}:${exports.LOCAL_ACCOUNT_ID}:function:${name}`,
|
|
196
|
+
memoryLimitInMB: '1024',
|
|
197
|
+
awsRequestId: (0, crypto_1.randomUUID)(),
|
|
198
|
+
logGroupName: `/aws/lambda/${name}`,
|
|
199
|
+
logStreamName: 'local-transport',
|
|
200
|
+
getRemainingTimeInMillis: () => 30000,
|
|
201
|
+
done: () => { },
|
|
202
|
+
fail: () => { },
|
|
203
|
+
succeed: () => { },
|
|
204
|
+
});
|
|
205
|
+
//* run one event through the engine's `LambdaHandler.handle()` (never rejects, as in Lambda).
|
|
206
|
+
const handleEvent = async (event) => {
|
|
207
|
+
//* lazy: the lambda module imports the protocol and AWS modules (no import cycle at load).
|
|
208
|
+
const $lambda = (await Promise.resolve().then(() => __importStar(require('../lambda')))).default;
|
|
209
|
+
const context = asContext(await (0, exports.selfHostOf)('web'));
|
|
210
|
+
return $lambda.lambda.handle(event, context);
|
|
211
|
+
};
|
|
212
|
+
//* the error of a finished SNS/SQS delivery ('' if none): SQS `batchItemFailures`, or the failure result `{ error }`.
|
|
213
|
+
const errorOf = (result) => {
|
|
214
|
+
const failures = Array.isArray(result?.batchItemFailures) ? result.batchItemFailures : [];
|
|
215
|
+
if (failures.length)
|
|
216
|
+
return `500 BATCH ITEM FAILURES - ${failures.map(_ => _?.itemIdentifier).join(',')}`;
|
|
217
|
+
if (result && typeof result === 'object' && typeof result.error === 'string')
|
|
218
|
+
return result.error;
|
|
219
|
+
return '';
|
|
220
|
+
};
|
|
221
|
+
//* schedule one async delivery (`setImmediate`), tracked until `drain()`.
|
|
222
|
+
const deliverAsync = (kind, target, depth, messageId, event) => {
|
|
223
|
+
exports.transportLog.inf(`[MOCK] deliver kind=${kind} target=${target} message=${messageId}`);
|
|
224
|
+
const job = new Promise(resolve => setImmediate(() => {
|
|
225
|
+
$chain
|
|
226
|
+
.run({ depth, async: true }, () => handleEvent(event))
|
|
227
|
+
.then(result => {
|
|
228
|
+
const error = errorOf(result);
|
|
229
|
+
record({ kind, target, messageId, result, ...(error ? { error } : {}) });
|
|
230
|
+
})
|
|
231
|
+
.catch(e => record({ kind, target, messageId, error: (0, test_helper_1.GETERR)(e) }))
|
|
232
|
+
.finally(() => resolve());
|
|
233
|
+
}));
|
|
234
|
+
$state.pending.add(job);
|
|
235
|
+
//* done: forget it, and end the burst if this was the last one.
|
|
236
|
+
job.then(() => {
|
|
237
|
+
$state.pending.delete(job);
|
|
238
|
+
resetIfIdle();
|
|
239
|
+
});
|
|
240
|
+
};
|
|
241
|
+
/**
|
|
242
|
+
* deliver an SNS message to this service: a `aws:sns` record → `LambdaHandler.handle()` (async).
|
|
243
|
+
*
|
|
244
|
+
* @param target topic name or ARN.
|
|
245
|
+
* @param msg subject, message (the `default` string), attributes.
|
|
246
|
+
* @param selfHost (optional) `sns://self` host (default: by the engine's protocol service).
|
|
247
|
+
* @returns the message id `mock-<uuid>`.
|
|
248
|
+
*/
|
|
249
|
+
const localSns = async (target, msg, selfHost) => {
|
|
250
|
+
const self = selfHost ?? (await (0, exports.selfHostOf)('sns'));
|
|
251
|
+
//* '' (no target, no env `MY_SNS_ENDPOINT`) → this service's topic, as the Lambda deploy sets the env.
|
|
252
|
+
const topic = (0, exports.topicOf)(target) || self;
|
|
253
|
+
assertSelf(topic, [(0, exports.topicOf)(`${engine_1.$engine.environ('MY_SNS_ENDPOINT', '') || ''}`), self]);
|
|
254
|
+
const depth = admit('sns', topic);
|
|
255
|
+
const messageId = `mock-${(0, crypto_1.randomUUID)()}`;
|
|
256
|
+
const TopicArn = `arn:aws:sns:${region()}:${exports.LOCAL_ACCOUNT_ID}:${topic}`;
|
|
257
|
+
//* attributes as the Lambda record has them (`Type`, `Value`).
|
|
258
|
+
const MessageAttributes = Object.entries(msg.MessageAttributes || {}).reduce((M, [k, v]) => ({ ...M, [k]: { Type: v.DataType, Value: v.StringValue } }), {});
|
|
259
|
+
const record = {
|
|
260
|
+
EventSource: 'aws:sns',
|
|
261
|
+
EventVersion: '1.0',
|
|
262
|
+
EventSubscriptionArn: `${TopicArn}:${(0, crypto_1.randomUUID)()}`,
|
|
263
|
+
Sns: {
|
|
264
|
+
Type: 'Notification',
|
|
265
|
+
MessageId: messageId,
|
|
266
|
+
TopicArn,
|
|
267
|
+
Subject: msg.Subject ?? null,
|
|
268
|
+
Message: msg.Message,
|
|
269
|
+
Timestamp: new Date().toISOString(),
|
|
270
|
+
MessageAttributes,
|
|
271
|
+
},
|
|
272
|
+
};
|
|
273
|
+
deliverAsync('sns', topic, depth, messageId, { Records: [record] });
|
|
274
|
+
return messageId;
|
|
275
|
+
};
|
|
276
|
+
exports.localSns = localSns;
|
|
277
|
+
/**
|
|
278
|
+
* deliver an SQS message to this service: a `aws:sqs` record → `LambdaHandler.handle()` (async, no delay).
|
|
279
|
+
*
|
|
280
|
+
* @param endpoint queue url or name.
|
|
281
|
+
* @param msg body and attributes.
|
|
282
|
+
* @param selfHost (optional) `sqs://self` host (default: by the engine's protocol service).
|
|
283
|
+
* @returns the message id `mock-<uuid>`.
|
|
284
|
+
*/
|
|
285
|
+
const localSqs = async (endpoint, msg, selfHost) => {
|
|
286
|
+
const self = selfHost ?? (await (0, exports.selfHostOf)('sqs'));
|
|
287
|
+
//* '' (no endpoint, no env `MY_SQS_ENDPOINT`) → this service's queue, as the Lambda deploy sets the env.
|
|
288
|
+
const queue = (0, exports.queueOf)(endpoint) || self;
|
|
289
|
+
assertSelf(queue, [(0, exports.queueOf)(`${engine_1.$engine.environ('MY_SQS_ENDPOINT', '') || ''}`), self]);
|
|
290
|
+
const depth = admit('sqs', queue);
|
|
291
|
+
const messageId = `mock-${(0, crypto_1.randomUUID)()}`;
|
|
292
|
+
const now = `${Date.now()}`;
|
|
293
|
+
//* attributes as the Lambda record has them (`dataType`, `stringValue`).
|
|
294
|
+
const messageAttributes = Object.entries(msg.MessageAttributes || {}).reduce((M, [k, v]) => ({
|
|
295
|
+
...M,
|
|
296
|
+
[k]: { dataType: v.DataType, stringValue: v.StringValue, stringListValues: [], binaryListValues: [] },
|
|
297
|
+
}), {});
|
|
298
|
+
const record = {
|
|
299
|
+
messageId,
|
|
300
|
+
receiptHandle: `mock-${(0, crypto_1.randomUUID)()}`,
|
|
301
|
+
body: msg.MessageBody,
|
|
302
|
+
attributes: {
|
|
303
|
+
ApproximateReceiveCount: '1',
|
|
304
|
+
SentTimestamp: now,
|
|
305
|
+
SenderId: exports.LOCAL_ACCOUNT_ID,
|
|
306
|
+
ApproximateFirstReceiveTimestamp: now,
|
|
307
|
+
},
|
|
308
|
+
messageAttributes,
|
|
309
|
+
md5OfBody: (0, crypto_1.createHash)('md5')
|
|
310
|
+
.update(`${msg.MessageBody ?? ''}`)
|
|
311
|
+
.digest('hex'),
|
|
312
|
+
eventSource: 'aws:sqs',
|
|
313
|
+
eventSourceARN: `arn:aws:sqs:${region()}:${exports.LOCAL_ACCOUNT_ID}:${queue}`,
|
|
314
|
+
awsRegion: region(),
|
|
315
|
+
};
|
|
316
|
+
deliverAsync('sqs', queue, depth, messageId, { Records: [record] });
|
|
317
|
+
return messageId;
|
|
318
|
+
};
|
|
319
|
+
exports.localSqs = localSqs;
|
|
320
|
+
/**
|
|
321
|
+
* run a protocol `execute()` on this service: the web event → `LambdaHandler.handle()` (sync, like a sync invoke).
|
|
322
|
+
* - the result is parsed like `invokeLambda()` (a non-2xx throws). `useEvent` → async, returns the 202 output.
|
|
323
|
+
*
|
|
324
|
+
* @param fn function name (host of the `web://` uri).
|
|
325
|
+
* @param event the web event of `WEBProtocolTransformer`.
|
|
326
|
+
* @param selfHost `web://self` host of the calling protocol service.
|
|
327
|
+
* @param options `param` for logging, `useEvent` for an async invoke.
|
|
328
|
+
*/
|
|
329
|
+
const localWeb = async (fn, event, selfHost, options) => {
|
|
330
|
+
assertSelf(fn, [selfHost]);
|
|
331
|
+
const depth = admit('protocol', fn);
|
|
332
|
+
//* lazy: `aws-lambda-helper` runs `$U` at load (this file is in the engine closure).
|
|
333
|
+
const { asInvokeResult } = await Promise.resolve().then(() => __importStar(require('./aws-lambda-helper')));
|
|
334
|
+
const messageId = `mock-${(0, crypto_1.randomUUID)()}`;
|
|
335
|
+
//* async invoke (`InvocationType: Event`): deliver later, return the 202 output.
|
|
336
|
+
if (options?.useEvent) {
|
|
337
|
+
deliverAsync('protocol', fn, depth, messageId, event);
|
|
338
|
+
return asInvokeResult(fn, { StatusCode: 202 }, { ...options, useEvent: true });
|
|
339
|
+
}
|
|
340
|
+
exports.transportLog.inf(`[MOCK] deliver kind=protocol target=${fn} message=${messageId}`);
|
|
341
|
+
$state.running++;
|
|
342
|
+
try {
|
|
343
|
+
const result = await $chain.run({ depth, async: false }, () => handleEvent(event));
|
|
344
|
+
const Payload = new TextEncoder().encode(JSON.stringify(result ?? {}));
|
|
345
|
+
const body = await asInvokeResult(fn, { StatusCode: 200, Payload }, options);
|
|
346
|
+
record({ kind: 'protocol', target: fn, messageId, result: body });
|
|
347
|
+
return body;
|
|
348
|
+
}
|
|
349
|
+
catch (e) {
|
|
350
|
+
record({ kind: 'protocol', target: fn, messageId, error: (0, test_helper_1.GETERR)(e) });
|
|
351
|
+
throw e;
|
|
352
|
+
}
|
|
353
|
+
finally {
|
|
354
|
+
//* the sync call is over: end the burst if nothing else is pending.
|
|
355
|
+
$state.running--;
|
|
356
|
+
resetIfIdle();
|
|
357
|
+
}
|
|
358
|
+
};
|
|
359
|
+
exports.localWeb = localWeb;
|
|
360
|
+
/**
|
|
361
|
+
* wait for every pending delivery (incl. the ones they send), then return the finished list and clear it.
|
|
362
|
+
* - resets the loop-guard count (idle also does). process-wide: it takes every delivery, not only the caller's.
|
|
363
|
+
* - must not be called inside an SNS/SQS delivery (it would wait for itself).
|
|
364
|
+
*/
|
|
365
|
+
const drain = async () => {
|
|
366
|
+
if ($chain.getStore()?.async)
|
|
367
|
+
throw new Error(`500 INVALID STATE - drain() inside a delivery (local transport)`);
|
|
368
|
+
while ($state.pending.size)
|
|
369
|
+
await Promise.all([...$state.pending]);
|
|
370
|
+
const list = $state.list.splice(0);
|
|
371
|
+
$state.count = 0;
|
|
372
|
+
$state.capped = false;
|
|
373
|
+
return list;
|
|
374
|
+
};
|
|
375
|
+
exports.drain = drain;
|
|
376
|
+
/**
|
|
377
|
+
* the finished deliveries since the last `drain()`, the last 100 only (a copy; it does not wait or clear).
|
|
378
|
+
*/
|
|
379
|
+
const deliveries = () => [...$state.list];
|
|
380
|
+
exports.deliveries = deliveries;
|
|
381
|
+
/**
|
|
382
|
+
* the public API of the local transport (exported from the package root).
|
|
383
|
+
*/
|
|
384
|
+
exports.$localTransport = {
|
|
385
|
+
/** true if `LOCAL_TRANSPORT=mock` and local mode */
|
|
386
|
+
isActive: exports.isActive,
|
|
387
|
+
/** wait for all pending deliveries, return them, and clear */
|
|
388
|
+
drain: exports.drain,
|
|
389
|
+
/** the finished deliveries since the last `drain()` */
|
|
390
|
+
deliveries: exports.deliveries,
|
|
391
|
+
};
|
|
392
|
+
//# sourceMappingURL=local-transport.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"local-transport.js","sourceRoot":"","sources":["../../../src/cores/protocol/local-transport.ts"],"names":[],"mappings":"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"}
|
|
@@ -2,6 +2,7 @@ import { NextContext } from 'lemon-model';
|
|
|
2
2
|
import { STAGE, ProtocolService, ProtocolParam, ProtocolTransformer, ProtocolBody, CallbackParam, ProtocolExecuteOptions } from './../core-services';
|
|
3
3
|
import { APIGatewayProxyEvent, SNSMessage, SQSRecord } from 'aws-lambda';
|
|
4
4
|
import { ConfigService } from './../config/config-service';
|
|
5
|
+
import { HEADER_PROTOCOL_CONTEXT } from './protocol-sign';
|
|
5
6
|
/**
|
|
6
7
|
* a message attribute of SNS/SQS (local structural type = the SDK `MessageAttributeValue`; v5 B2-c).
|
|
7
8
|
*/
|
|
@@ -13,8 +14,9 @@ interface MyMessageAttributeValue {
|
|
|
13
14
|
/**
|
|
14
15
|
* header name to exchange `next-context`
|
|
15
16
|
* ONLY for internal communication.
|
|
17
|
+
* - v5 B10-3: defined in `protocol-sign.ts`, re-exported here (same name, same value).
|
|
16
18
|
*/
|
|
17
|
-
export
|
|
19
|
+
export { HEADER_PROTOCOL_CONTEXT };
|
|
18
20
|
/**
|
|
19
21
|
* type: MyProtocolType
|
|
20
22
|
* - supportable type of protocol
|
|
@@ -220,4 +222,3 @@ export declare class SQSProtocolTransformer implements ProtocolTransformer<SQSEv
|
|
|
220
222
|
*/
|
|
221
223
|
transformToParam(event: SQSRecord): MyProtocolParam;
|
|
222
224
|
}
|
|
223
|
-
export {};
|
|
@@ -44,6 +44,7 @@ exports.SQSProtocolTransformer = exports.SNSProtocolTransformer = exports.WEBPro
|
|
|
44
44
|
*
|
|
45
45
|
* @author Steve Jung <steve@lemoncloud.io>
|
|
46
46
|
* @date 2019-11-27 initial version.
|
|
47
|
+
* @date 2026-10-30 `execute/notify/enqueue/broadcast`: the local transport (`LOCAL_TRANSPORT=mock`) delivers in-process.
|
|
47
48
|
*
|
|
48
49
|
* @copyright (C) lemoncloud.io 2019 - All Rights Reserved.
|
|
49
50
|
*/
|
|
@@ -56,8 +57,11 @@ const config_1 = __importDefault(require("../config/")); // load config-module.
|
|
|
56
57
|
const aws_1 = __importDefault(require("../aws/")); // load config-module.
|
|
57
58
|
const qs_1 = __importDefault(require("qs"));
|
|
58
59
|
const aws_lambda_helper_1 = require("./aws-lambda-helper");
|
|
60
|
+
const local_transport_1 = require("./local-transport");
|
|
61
|
+
const aws_sns_service_1 = require("../aws/aws-sns-service");
|
|
59
62
|
const perf_1 = require("../../lib/perf");
|
|
60
63
|
const protocol_sign_1 = require("./protocol-sign");
|
|
64
|
+
Object.defineProperty(exports, "HEADER_PROTOCOL_CONTEXT", { enumerable: true, get: function () { return protocol_sign_1.HEADER_PROTOCOL_CONTEXT; } });
|
|
61
65
|
const NS = engine_1.$U.NS('PRTS', 'yellow'); // NAMESPACE TO BE PRINTED.
|
|
62
66
|
/**
|
|
63
67
|
* SDK packages, imported on the first use (not at import; v5 B2-c, K6). This file keeps its own loaders.
|
|
@@ -69,11 +73,6 @@ let $sqs;
|
|
|
69
73
|
const loadSns = () => ($sns ??= (0, perf_1.measureAsync)(engine_1._inf, engine_1.$U.NS('PERF', 'cyan'), 'lazy-load @aws-sdk/client-sns', () => Promise.resolve().then(() => __importStar(require('@aws-sdk/client-sns')))));
|
|
70
74
|
// loader of `@aws-sdk/client-sqs`.
|
|
71
75
|
const loadSqs = () => ($sqs ??= (0, perf_1.measureAsync)(engine_1._inf, engine_1.$U.NS('PERF', 'cyan'), 'lazy-load @aws-sdk/client-sqs', () => Promise.resolve().then(() => __importStar(require('@aws-sdk/client-sqs')))));
|
|
72
|
-
/**
|
|
73
|
-
* header name to exchange `next-context`
|
|
74
|
-
* ONLY for internal communication.
|
|
75
|
-
*/
|
|
76
|
-
exports.HEADER_PROTOCOL_CONTEXT = engine_1.$U.env('HEADER_PROTOCOL_CONTEXT', 'x-protocol-context');
|
|
77
76
|
/**
|
|
78
77
|
* class: `MyConfigService`
|
|
79
78
|
* - main implementation for `protocol-service`
|
|
@@ -328,6 +327,11 @@ class MyProtocolService {
|
|
|
328
327
|
// const url = new URL(uri);
|
|
329
328
|
const $url = url_1.default.parse(uri);
|
|
330
329
|
const payload = this.transformEvent(uri, param);
|
|
330
|
+
//* local transport (opt-in, local mode only): run this service's handler in-process (sync), no AWS call.
|
|
331
|
+
if ((0, local_transport_1.isActive)()) {
|
|
332
|
+
const selfHost = await (0, local_transport_1.selfHostOf)('web', this, config);
|
|
333
|
+
return (0, local_transport_1.localWeb)(`${$url.hostname || ''}`, payload, selfHost, { param, useEvent });
|
|
334
|
+
}
|
|
331
335
|
const awsCfg = (0, tools_1.awsConfig)(engine_1.default);
|
|
332
336
|
return (0, aws_lambda_helper_1.invokeLambda)($url.hostname, payload, { param, config: awsCfg, useEvent });
|
|
333
337
|
}
|
|
@@ -347,7 +351,12 @@ class MyProtocolService {
|
|
|
347
351
|
(0, engine_1._inf)(NS, `> uri[${service}] =`, uri);
|
|
348
352
|
const cbUrl = callback ? this.asCallbackURI(param.context, callback) : null;
|
|
349
353
|
const params = this.sns.transformToEvent(uri, param, cbUrl);
|
|
350
|
-
|
|
354
|
+
//* local transport (opt-in, local mode only): deliver to this service's topic in-process, no AWS call.
|
|
355
|
+
if ((0, local_transport_1.isActive)()) {
|
|
356
|
+
const message = { ...params, Message: JSON.parse(params.Message).default };
|
|
357
|
+
return (0, local_transport_1.localSns)(params.TopicArn, message, await (0, local_transport_1.selfHostOf)('sns', this, config));
|
|
358
|
+
}
|
|
359
|
+
const arn = params.TopicArn; // "arn:aws:sns:ap-northeast-2:123456789012:lemon-metrics-sns-dev"
|
|
351
360
|
// _inf(NS, `> arn[${service}] =`, arn);
|
|
352
361
|
(0, engine_1._inf)(NS, `> payload[${arn}] =`, engine_1.$U.json(params));
|
|
353
362
|
//* call sns
|
|
@@ -389,6 +398,9 @@ class MyProtocolService {
|
|
|
389
398
|
(0, engine_1._inf)(NS, `> callback[${service}] =`, cbUrl);
|
|
390
399
|
const params = this.sqs.transformToEvent(uri, param, cbUrl);
|
|
391
400
|
params.DelaySeconds = delaySeconds;
|
|
401
|
+
//* local transport (opt-in, local mode only): deliver to this service's queue in-process (no delay), no AWS call.
|
|
402
|
+
if ((0, local_transport_1.isActive)())
|
|
403
|
+
return (0, local_transport_1.localSqs)(params.QueueUrl, params, await (0, local_transport_1.selfHostOf)('sqs', this, config));
|
|
392
404
|
const endpoint = params.QueueUrl; // https://sqs.${arr[3]}.amazonaws.com
|
|
393
405
|
// _inf(NS, `> endpoint[${service}] =`, endpoint);
|
|
394
406
|
(0, engine_1._inf)(NS, `> payload[${endpoint}] =`, engine_1.$U.json(params));
|
|
@@ -421,6 +433,17 @@ class MyProtocolService {
|
|
|
421
433
|
const service = this.myProtocolURI(context);
|
|
422
434
|
(0, engine_1._log)(NS, `broadcast(${service})..`);
|
|
423
435
|
(0, engine_1._log)(NS, `> body[${service}] =`, engine_1.$U.json(body));
|
|
436
|
+
//* local transport (opt-in, local mode only): deliver to this service's topic in-process (no endpoint lookup).
|
|
437
|
+
if ((0, local_transport_1.isActive)()) {
|
|
438
|
+
const [accountId, requestId] = [`${context?.accountId || ''}`, `${context?.requestId || ''}`];
|
|
439
|
+
const MessageAttributes = {};
|
|
440
|
+
if (accountId)
|
|
441
|
+
MessageAttributes['accountId'] = { DataType: 'String', StringValue: accountId };
|
|
442
|
+
if (requestId)
|
|
443
|
+
MessageAttributes['requestId'] = { DataType: 'String', StringValue: requestId };
|
|
444
|
+
const message = { Subject: `x-protocol-service/broadcast`, Message: engine_1.$U.json(body), MessageAttributes };
|
|
445
|
+
return (0, local_transport_1.localSns)((0, aws_sns_service_1.snsTargetOf)(endpoint), message, await (0, local_transport_1.selfHostOf)('sns', this));
|
|
446
|
+
}
|
|
424
447
|
const arn = await aws_1.default.sns.endpoint(endpoint);
|
|
425
448
|
(0, engine_1._inf)(NS, `> arn[${endpoint}] =`, arn);
|
|
426
449
|
const accountId = `${(context && context.accountId) || ''}`;
|
|
@@ -493,7 +516,7 @@ class WEBProtocolTransformer {
|
|
|
493
516
|
const event = {
|
|
494
517
|
...base,
|
|
495
518
|
headers: {
|
|
496
|
-
[
|
|
519
|
+
[protocol_sign_1.HEADER_PROTOCOL_CONTEXT]: contextJson,
|
|
497
520
|
...(signature ? { [protocol_sign_1.HEADER_PROTOCOL_SIGNATURE]: signature } : {}),
|
|
498
521
|
},
|
|
499
522
|
path,
|
|
@@ -532,7 +555,7 @@ class WEBProtocolTransformer {
|
|
|
532
555
|
const _context = (context) => {
|
|
533
556
|
if (context)
|
|
534
557
|
return context; // use given context.
|
|
535
|
-
const ctx = headers[
|
|
558
|
+
const ctx = headers[protocol_sign_1.HEADER_PROTOCOL_CONTEXT];
|
|
536
559
|
if (!ctx)
|
|
537
560
|
return null; // no context.
|
|
538
561
|
if (typeof ctx !== 'string')
|
|
@@ -613,7 +636,7 @@ class SNSProtocolTransformer {
|
|
|
613
636
|
transformToEvent(uri, param, callback) {
|
|
614
637
|
// const uri = this.service.asProtocolURI('sns', param);
|
|
615
638
|
const context = param.context || {};
|
|
616
|
-
const arn = (0, engine_1.getHelloArn)(param.context); // "arn:aws:sns:ap-northeast-2:
|
|
639
|
+
const arn = (0, engine_1.getHelloArn)(param.context); // "arn:aws:sns:ap-northeast-2:123456789012:lemon-metrics-sns-dev"
|
|
617
640
|
//* build TopicArn via url.
|
|
618
641
|
const url = url_1.default.parse(uri);
|
|
619
642
|
const end = url.host || url.hostname;
|
|
@@ -695,7 +718,7 @@ class SQSProtocolTransformer {
|
|
|
695
718
|
transformToEvent(uri, param, callback) {
|
|
696
719
|
// const uri = this.service.asProtocolURI('sns', param);
|
|
697
720
|
const context = param.context || {};
|
|
698
|
-
const arn = (0, engine_1.getHelloArn)(param.context); // "arn:aws:sns:ap-northeast-2:
|
|
721
|
+
const arn = (0, engine_1.getHelloArn)(param.context); // "arn:aws:sns:ap-northeast-2:123456789012:lemon-metrics-sns-dev"
|
|
699
722
|
//* build TopicArn via url.
|
|
700
723
|
const url = url_1.default.parse(uri);
|
|
701
724
|
const arr = arn.split(':');
|