@voxgig/build 4.0.0 → 4.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/build.ts +33 -0
- package/dist/build.d.ts +14 -1
- package/dist/build.js +23 -1
- package/dist/build.js.map +1 -1
- package/dist/env/lambda/generate.d.ts +7 -1
- package/dist/env/lambda/generate.js +55 -0
- package/dist/env/lambda/generate.js.map +1 -1
- package/dist/env/lambda/res_yml.d.ts +1 -0
- package/dist/env/lambda/res_yml.js +12 -41
- package/dist/env/lambda/res_yml.js.map +1 -1
- package/dist/env/lambda/srv_handler.d.ts +1 -0
- package/dist/env/lambda/srv_handler.js +10 -21
- package/dist/env/lambda/srv_handler.js.map +1 -1
- package/dist/env/lambda/srv_yml.d.ts +1 -0
- package/dist/env/lambda/srv_yml.js +11 -9
- package/dist/env/lambda/srv_yml.js.map +1 -1
- package/env/lambda/generate.ts +105 -0
- package/env/lambda/res_yml.ts +140 -0
- package/env/lambda/srv_handler.ts +132 -0
- package/env/lambda/srv_yml.ts +201 -0
- package/package.json +6 -4
- package/tm/lambda/res.queue.yml.frag +6 -0
- package/tm/lambda/res.role.yml.frag +35 -0
- package/tm/lambda/srv.yml.frag +6 -0
- package/tm/lambda/srv_handler.js.frag +17 -0
- package/tm/lambda/srv_handler.ts.frag +17 -0
package/build.ts
CHANGED
|
@@ -17,6 +17,15 @@ import { srv_yml } from './env/lambda/srv_yml'
|
|
|
17
17
|
import { srv_handler } from './env/lambda/srv_handler'
|
|
18
18
|
import { resources_yml } from './env/lambda/res_yml'
|
|
19
19
|
|
|
20
|
+
import {
|
|
21
|
+
generate, empty, TM,
|
|
22
|
+
loadFragment, renderFragment, listFragments, PKG_TM,
|
|
23
|
+
} from './env/lambda/generate'
|
|
24
|
+
|
|
25
|
+
import { MsgMetaShape } from './shape/msg'
|
|
26
|
+
import { CoreConfShape, CloudConfShape } from './shape/conf'
|
|
27
|
+
import { res_dynamo_yml } from './yml/res_dynamo_yml'
|
|
28
|
+
|
|
20
29
|
|
|
21
30
|
const EnvLambda = {
|
|
22
31
|
srv_yml,
|
|
@@ -25,6 +34,30 @@ const EnvLambda = {
|
|
|
25
34
|
}
|
|
26
35
|
|
|
27
36
|
|
|
37
|
+
// Fragment tooling (used by voxgig-system template list/eject/diff, and
|
|
38
|
+
// available to project code).
|
|
39
|
+
const Fragments = {
|
|
40
|
+
load: loadFragment,
|
|
41
|
+
render: renderFragment,
|
|
42
|
+
list: listFragments,
|
|
43
|
+
folder: PKG_TM,
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
|
|
28
47
|
export {
|
|
29
48
|
EnvLambda,
|
|
49
|
+
Fragments,
|
|
50
|
+
|
|
51
|
+
// Building blocks for ejected project templates (src/gen/<name>.ts
|
|
52
|
+
// copies import these from '@voxgig/build' instead of package
|
|
53
|
+
// internals - see voxgig-system template eject --code).
|
|
54
|
+
generate,
|
|
55
|
+
empty,
|
|
56
|
+
TM,
|
|
57
|
+
loadFragment,
|
|
58
|
+
renderFragment,
|
|
59
|
+
MsgMetaShape,
|
|
60
|
+
CoreConfShape,
|
|
61
|
+
CloudConfShape,
|
|
62
|
+
res_dynamo_yml,
|
|
30
63
|
}
|
package/dist/build.d.ts
CHANGED
|
@@ -1,6 +1,11 @@
|
|
|
1
|
+
import { generate, empty, TM, loadFragment, renderFragment, listFragments } from './env/lambda/generate';
|
|
2
|
+
import { MsgMetaShape } from './shape/msg';
|
|
3
|
+
import { CoreConfShape, CloudConfShape } from './shape/conf';
|
|
4
|
+
import { res_dynamo_yml } from './yml/res_dynamo_yml';
|
|
1
5
|
declare const EnvLambda: {
|
|
2
6
|
srv_yml: (model: any, spec: {
|
|
3
7
|
folder: string;
|
|
8
|
+
tm?: string;
|
|
4
9
|
}) => Promise<void>;
|
|
5
10
|
srv_handler: (model: any, spec: {
|
|
6
11
|
folder: string;
|
|
@@ -9,11 +14,19 @@ declare const EnvLambda: {
|
|
|
9
14
|
folder: string;
|
|
10
15
|
};
|
|
11
16
|
lang?: string;
|
|
17
|
+
tm?: string;
|
|
12
18
|
}) => Promise<void>;
|
|
13
19
|
resources_yml: (model: any, spec: {
|
|
14
20
|
folder: string;
|
|
15
21
|
filename: string;
|
|
16
22
|
custom: string;
|
|
23
|
+
tm?: string;
|
|
17
24
|
}) => Promise<void>;
|
|
18
25
|
};
|
|
19
|
-
|
|
26
|
+
declare const Fragments: {
|
|
27
|
+
load: typeof loadFragment;
|
|
28
|
+
render: typeof renderFragment;
|
|
29
|
+
list: typeof listFragments;
|
|
30
|
+
folder: string;
|
|
31
|
+
};
|
|
32
|
+
export { EnvLambda, Fragments, generate, empty, TM, loadFragment, renderFragment, MsgMetaShape, CoreConfShape, CloudConfShape, res_dynamo_yml, };
|
package/dist/build.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
/* Copyright © 2022-2026 Voxgig Ltd, MIT License. */
|
|
3
3
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
4
|
-
exports.EnvLambda = void 0;
|
|
4
|
+
exports.res_dynamo_yml = exports.CloudConfShape = exports.CoreConfShape = exports.MsgMetaShape = exports.renderFragment = exports.loadFragment = exports.TM = exports.empty = exports.generate = exports.Fragments = exports.EnvLambda = void 0;
|
|
5
5
|
// EnvLambda: generation of the Lambda deployment templates, built on the
|
|
6
6
|
// jostraca templating library. The templates live in env/lambda/, one file
|
|
7
7
|
// per output for convenience:
|
|
@@ -17,10 +17,32 @@ exports.EnvLambda = void 0;
|
|
|
17
17
|
const srv_yml_1 = require("./env/lambda/srv_yml");
|
|
18
18
|
const srv_handler_1 = require("./env/lambda/srv_handler");
|
|
19
19
|
const res_yml_1 = require("./env/lambda/res_yml");
|
|
20
|
+
const generate_1 = require("./env/lambda/generate");
|
|
21
|
+
Object.defineProperty(exports, "generate", { enumerable: true, get: function () { return generate_1.generate; } });
|
|
22
|
+
Object.defineProperty(exports, "empty", { enumerable: true, get: function () { return generate_1.empty; } });
|
|
23
|
+
Object.defineProperty(exports, "TM", { enumerable: true, get: function () { return generate_1.TM; } });
|
|
24
|
+
Object.defineProperty(exports, "loadFragment", { enumerable: true, get: function () { return generate_1.loadFragment; } });
|
|
25
|
+
Object.defineProperty(exports, "renderFragment", { enumerable: true, get: function () { return generate_1.renderFragment; } });
|
|
26
|
+
const msg_1 = require("./shape/msg");
|
|
27
|
+
Object.defineProperty(exports, "MsgMetaShape", { enumerable: true, get: function () { return msg_1.MsgMetaShape; } });
|
|
28
|
+
const conf_1 = require("./shape/conf");
|
|
29
|
+
Object.defineProperty(exports, "CoreConfShape", { enumerable: true, get: function () { return conf_1.CoreConfShape; } });
|
|
30
|
+
Object.defineProperty(exports, "CloudConfShape", { enumerable: true, get: function () { return conf_1.CloudConfShape; } });
|
|
31
|
+
const res_dynamo_yml_1 = require("./yml/res_dynamo_yml");
|
|
32
|
+
Object.defineProperty(exports, "res_dynamo_yml", { enumerable: true, get: function () { return res_dynamo_yml_1.res_dynamo_yml; } });
|
|
20
33
|
const EnvLambda = {
|
|
21
34
|
srv_yml: srv_yml_1.srv_yml,
|
|
22
35
|
srv_handler: srv_handler_1.srv_handler,
|
|
23
36
|
resources_yml: res_yml_1.resources_yml,
|
|
24
37
|
};
|
|
25
38
|
exports.EnvLambda = EnvLambda;
|
|
39
|
+
// Fragment tooling (used by voxgig-system template list/eject/diff, and
|
|
40
|
+
// available to project code).
|
|
41
|
+
const Fragments = {
|
|
42
|
+
load: generate_1.loadFragment,
|
|
43
|
+
render: generate_1.renderFragment,
|
|
44
|
+
list: generate_1.listFragments,
|
|
45
|
+
folder: generate_1.PKG_TM,
|
|
46
|
+
};
|
|
47
|
+
exports.Fragments = Fragments;
|
|
26
48
|
//# sourceMappingURL=build.js.map
|
package/dist/build.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"build.js","sourceRoot":"","sources":["../build.ts"],"names":[],"mappings":";AAAA,oDAAoD;;;AAEpD,yEAAyE;AACzE,2EAA2E;AAC3E,8BAA8B;AAC9B,EAAE;AACF,yEAAyE;AACzE,uEAAuE;AACvE,yEAAyE;AACzE,EAAE;AACF,yEAAyE;AACzE,2EAA2E;AAC3E,wEAAwE;AACxE,qCAAqC;AAErC,kDAA8C;AAC9C,0DAAsD;AACtD,kDAAoD;
|
|
1
|
+
{"version":3,"file":"build.js","sourceRoot":"","sources":["../build.ts"],"names":[],"mappings":";AAAA,oDAAoD;;;AAEpD,yEAAyE;AACzE,2EAA2E;AAC3E,8BAA8B;AAC9B,EAAE;AACF,yEAAyE;AACzE,uEAAuE;AACvE,yEAAyE;AACzE,EAAE;AACF,yEAAyE;AACzE,2EAA2E;AAC3E,wEAAwE;AACxE,qCAAqC;AAErC,kDAA8C;AAC9C,0DAAsD;AACtD,kDAAoD;AAEpD,oDAG8B;AA+B5B,yFAjCA,mBAAQ,OAiCA;AACR,sFAlCU,gBAAK,OAkCV;AACL,mFAnCiB,aAAE,OAmCjB;AACF,6FAnCA,uBAAY,OAmCA;AACZ,+FApCc,yBAAc,OAoCd;AAjChB,qCAA0C;AAkCxC,6FAlCO,kBAAY,OAkCP;AAjCd,uCAA4D;AAkC1D,8FAlCO,oBAAa,OAkCP;AACb,+FAnCsB,qBAAc,OAmCtB;AAlChB,yDAAqD;AAmCnD,+FAnCO,+BAAc,OAmCP;AAhChB,MAAM,SAAS,GAAG;IAChB,OAAO,EAAP,iBAAO;IACP,WAAW,EAAX,yBAAW;IACX,aAAa,EAAb,uBAAa;CACd,CAAA;AAcC,8BAAS;AAXX,wEAAwE;AACxE,8BAA8B;AAC9B,MAAM,SAAS,GAAG;IAChB,IAAI,EAAE,uBAAY;IAClB,MAAM,EAAE,yBAAc;IACtB,IAAI,EAAE,wBAAa;IACnB,MAAM,EAAE,iBAAM;CACf,CAAA;AAKC,8BAAS"}
|
|
@@ -1,7 +1,13 @@
|
|
|
1
|
+
declare const PKG_TM: string;
|
|
2
|
+
declare function loadFragment(name: string, spec?: {
|
|
3
|
+
tm?: string;
|
|
4
|
+
}): string;
|
|
5
|
+
declare function renderFragment(src: string, slots: Record<string, any>): string;
|
|
6
|
+
declare function listFragments(): string[];
|
|
1
7
|
declare function generate(folder: string, files: {
|
|
2
8
|
name: string;
|
|
3
9
|
content: string;
|
|
4
10
|
}[]): Promise<void>;
|
|
5
11
|
declare function empty(o: any): boolean;
|
|
6
12
|
declare function TM(str: string): string;
|
|
7
|
-
export { generate, empty, TM, };
|
|
13
|
+
export { generate, empty, TM, loadFragment, renderFragment, listFragments, PKG_TM, };
|
|
@@ -1,13 +1,68 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
/* Copyright © 2022-2026 Voxgig Ltd, MIT License. */
|
|
3
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
4
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
5
|
+
};
|
|
3
6
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
7
|
+
exports.PKG_TM = void 0;
|
|
4
8
|
exports.generate = generate;
|
|
5
9
|
exports.empty = empty;
|
|
6
10
|
exports.TM = TM;
|
|
11
|
+
exports.loadFragment = loadFragment;
|
|
12
|
+
exports.renderFragment = renderFragment;
|
|
13
|
+
exports.listFragments = listFragments;
|
|
7
14
|
// Shared generation utilities for the lambda templates. File output goes
|
|
8
15
|
// through the jostraca templating library (Project/File/Content components),
|
|
9
16
|
// which also maintains .jostraca/ build metadata next to the outputs.
|
|
17
|
+
const fs_1 = __importDefault(require("fs"));
|
|
18
|
+
const path_1 = __importDefault(require("path"));
|
|
10
19
|
const jostraca_1 = require("jostraca");
|
|
20
|
+
// The text shape of each generated output lives in a jostraca-style
|
|
21
|
+
// fragment file with $$slot$$ placeholders. Fragments ship with this
|
|
22
|
+
// package under tm/lambda/, and a project can shadow any of them by
|
|
23
|
+
// placing a same-named file in its own tm folder (passed as spec.tm by
|
|
24
|
+
// the project's build actions). The fragment file's final newline is
|
|
25
|
+
// dropped at load, so slot values fully control trailing bytes.
|
|
26
|
+
// Package tm folder: compiled code lives at <pkg>/dist/env/lambda (three
|
|
27
|
+
// levels down), but test transforms run the source at <pkg>/env/lambda
|
|
28
|
+
// (two levels down) - probe both.
|
|
29
|
+
const PKG_TM = [
|
|
30
|
+
path_1.default.join(__dirname, '..', '..', '..', 'tm', 'lambda'),
|
|
31
|
+
path_1.default.join(__dirname, '..', '..', 'tm', 'lambda'),
|
|
32
|
+
].find((p) => fs_1.default.existsSync(p)) ||
|
|
33
|
+
path_1.default.join(__dirname, '..', '..', '..', 'tm', 'lambda');
|
|
34
|
+
exports.PKG_TM = PKG_TM;
|
|
35
|
+
function loadFragment(name, spec) {
|
|
36
|
+
const candidates = [];
|
|
37
|
+
if (spec === null || spec === void 0 ? void 0 : spec.tm) {
|
|
38
|
+
candidates.push(path_1.default.join(spec.tm, name));
|
|
39
|
+
}
|
|
40
|
+
candidates.push(path_1.default.join(PKG_TM, name));
|
|
41
|
+
for (const c of candidates) {
|
|
42
|
+
if (fs_1.default.existsSync(c)) {
|
|
43
|
+
let src = fs_1.default.readFileSync(c, 'utf8');
|
|
44
|
+
if (src.endsWith('\n')) {
|
|
45
|
+
src = src.substring(0, src.length - 1);
|
|
46
|
+
}
|
|
47
|
+
return src;
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
throw new Error('@voxgig/build: fragment not found: ' + name +
|
|
51
|
+
' (looked in ' + candidates.join(', ') + ')');
|
|
52
|
+
}
|
|
53
|
+
// Literal $$slot$$ substitution (split/join - values are never
|
|
54
|
+
// interpreted, so ${...}, $&, etc. pass through untouched).
|
|
55
|
+
function renderFragment(src, slots) {
|
|
56
|
+
let out = src;
|
|
57
|
+
for (const key of Object.keys(slots)) {
|
|
58
|
+
out = out.split('$$' + key + '$$').join(String(slots[key]));
|
|
59
|
+
}
|
|
60
|
+
return out;
|
|
61
|
+
}
|
|
62
|
+
// Fragment names shipped by this package (for tooling: list/eject).
|
|
63
|
+
function listFragments() {
|
|
64
|
+
return fs_1.default.readdirSync(PKG_TM).filter((f) => f.endsWith('.frag')).sort();
|
|
65
|
+
}
|
|
11
66
|
// Generate one or more files in folder, each with exact content.
|
|
12
67
|
async function generate(folder, files) {
|
|
13
68
|
const jostraca = (0, jostraca_1.Jostraca)();
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"generate.js","sourceRoot":"","sources":["../../../env/lambda/generate.ts"],"names":[],"mappings":";AAAA,oDAAoD
|
|
1
|
+
{"version":3,"file":"generate.js","sourceRoot":"","sources":["../../../env/lambda/generate.ts"],"names":[],"mappings":"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"}
|
|
@@ -15,6 +15,8 @@ const conf_1 = require("../../shape/conf");
|
|
|
15
15
|
const res_dynamo_yml_1 = require("../../yml/res_dynamo_yml");
|
|
16
16
|
const generate_1 = require("./generate");
|
|
17
17
|
const resources_yml = async (model, spec) => {
|
|
18
|
+
const queueFrag = (0, generate_1.loadFragment)('res.queue.yml.frag', spec);
|
|
19
|
+
const roleFrag = (0, generate_1.loadFragment)('res.role.yml.frag', spec);
|
|
18
20
|
const core = (0, conf_1.CoreConfShape)(model.main.conf.core);
|
|
19
21
|
const appname = core.name;
|
|
20
22
|
const AppName = (0, util_1.camelify)(appname);
|
|
@@ -58,12 +60,11 @@ const resources_yml = async (model, spec) => {
|
|
|
58
60
|
(queue_suffix || '') +
|
|
59
61
|
(stage_suffix || '');
|
|
60
62
|
let queueTimeout = queue.timeout || 30;
|
|
61
|
-
return
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
`;
|
|
63
|
+
return (0, generate_1.renderFragment)(queueFrag, {
|
|
64
|
+
resname,
|
|
65
|
+
queueName,
|
|
66
|
+
queueTimeout,
|
|
67
|
+
});
|
|
67
68
|
}
|
|
68
69
|
return '';
|
|
69
70
|
}).filter(n => '' !== n).join('');
|
|
@@ -72,41 +73,11 @@ const resources_yml = async (model, spec) => {
|
|
|
72
73
|
let customLambdaPolicyStatementPath = path_1.default.join(spec.folder, 'res.lambda.policy.statements.yml');
|
|
73
74
|
let customLambdaPolicyStatementContent = fs_1.default.existsSync(customLambdaPolicyStatementPath) ?
|
|
74
75
|
fs_1.default.readFileSync(customLambdaPolicyStatementPath) : '';
|
|
75
|
-
content +=
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
AssumeRolePolicyDocument:
|
|
81
|
-
Version: '2012-10-17'
|
|
82
|
-
Statement:
|
|
83
|
-
- Effect: Allow
|
|
84
|
-
Principal:
|
|
85
|
-
Service:
|
|
86
|
-
- lambda.amazonaws.com
|
|
87
|
-
- events.amazonaws.com
|
|
88
|
-
- ecs-tasks.amazonaws.com
|
|
89
|
-
Action: sts:AssumeRole
|
|
90
|
-
Policies:
|
|
91
|
-
- PolicyName: LambdaServiceAccess
|
|
92
|
-
PolicyDocument:
|
|
93
|
-
Version: '2012-10-17'
|
|
94
|
-
Statement:
|
|
95
|
-
- Effect: Allow
|
|
96
|
-
Action:
|
|
97
|
-
- dynamodb:DescribeTable
|
|
98
|
-
- dynamodb:GetItem
|
|
99
|
-
- dynamodb:PutItem
|
|
100
|
-
- dynamodb:UpdateItem
|
|
101
|
-
- dynamodb:DeleteItem
|
|
102
|
-
- dynamodb:Query
|
|
103
|
-
- dynamodb:Scan
|
|
104
|
-
Resource:
|
|
105
|
-
${dynamoResources.map(r => ' - ' + r.arn).join('\n')}
|
|
106
|
-
${customLambdaPolicyStatementContent}
|
|
107
|
-
ManagedPolicyArns:
|
|
108
|
-
- arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole
|
|
109
|
-
`;
|
|
76
|
+
content += (0, generate_1.renderFragment)(roleFrag, {
|
|
77
|
+
AppName,
|
|
78
|
+
dynamoArns: dynamoResources.map(r => ' - ' + r.arn).join('\n'),
|
|
79
|
+
customPolicy: customLambdaPolicyStatementContent,
|
|
80
|
+
});
|
|
110
81
|
if (spec.custom) {
|
|
111
82
|
content = fs_1.default.readFileSync(spec.custom).toString() + '\n\n\n' + content;
|
|
112
83
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"res_yml.js","sourceRoot":"","sources":["../../../env/lambda/res_yml.ts"],"names":[],"mappings":";AAAA,oDAAoD;;;;;;AAEpD,sEAAsE;AACtE,sDAAsD;AAEtD,4CAAmB;AACnB,gDAAuB;AAEvB,uCAA6C;AAE7C,yCAA8C;AAC9C,2CAAgE;AAEhE,6DAAyD;AAEzD,
|
|
1
|
+
{"version":3,"file":"res_yml.js","sourceRoot":"","sources":["../../../env/lambda/res_yml.ts"],"names":[],"mappings":"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"}
|
|
@@ -10,7 +10,7 @@ const generate_1 = require("./generate");
|
|
|
10
10
|
// Only create if does not exist
|
|
11
11
|
const srv_handler = async (model, spec) => {
|
|
12
12
|
let lang = spec.lang || 'js';
|
|
13
|
-
|
|
13
|
+
const frag = (0, generate_1.loadFragment)('srv_handler.' + lang + '.frag', spec);
|
|
14
14
|
const files = [];
|
|
15
15
|
Object
|
|
16
16
|
.entries(model.main.srv)
|
|
@@ -82,26 +82,15 @@ const srv_handler = async (model, spec) => {
|
|
|
82
82
|
}
|
|
83
83
|
});
|
|
84
84
|
});
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
event${TS ? ':any' : ''},
|
|
95
|
-
context${TS ? ':any' : ''}
|
|
96
|
-
) => {
|
|
97
|
-
${modify}
|
|
98
|
-
let seneca = await getSeneca('${name}', complete)
|
|
99
|
-
${prepare}
|
|
100
|
-
let handler = seneca.export('gateway-lambda/${handler}')
|
|
101
|
-
let res = await handler(event, context)
|
|
102
|
-
return res
|
|
103
|
-
}
|
|
104
|
-
`;
|
|
85
|
+
const content = (0, generate_1.renderFragment)(frag, {
|
|
86
|
+
envFolder,
|
|
87
|
+
start,
|
|
88
|
+
name,
|
|
89
|
+
complete,
|
|
90
|
+
modify,
|
|
91
|
+
prepare,
|
|
92
|
+
handler,
|
|
93
|
+
});
|
|
105
94
|
files.push({ name: name + '.' + lang, content });
|
|
106
95
|
});
|
|
107
96
|
if (0 < files.length) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"srv_handler.js","sourceRoot":"","sources":["../../../env/lambda/srv_handler.ts"],"names":[],"mappings":";AAAA,oDAAoD;;;AAEpD,uEAAuE;AACvE,4EAA4E;AAE5E,uCAAgD;AAEhD,yCAA8C;AAE9C,
|
|
1
|
+
{"version":3,"file":"srv_handler.js","sourceRoot":"","sources":["../../../env/lambda/srv_handler.ts"],"names":[],"mappings":"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"}
|
|
@@ -16,6 +16,7 @@ const srv_yml = async (model, spec) => {
|
|
|
16
16
|
const core = (0, conf_1.CoreConfShape)(model.main.conf.core);
|
|
17
17
|
let appname = core.name;
|
|
18
18
|
let AppName = (0, util_1.camelify)(appname);
|
|
19
|
+
const frag = (0, generate_1.loadFragment)('srv.yml.frag', spec);
|
|
19
20
|
let srv_yml_prefix_path = path_1.default.join(spec.folder, 'srv.prefix.yml');
|
|
20
21
|
let srv_yml_suffix_path = path_1.default.join(spec.folder, 'srv.suffix.yml');
|
|
21
22
|
let prefixContent = fs_1.default.existsSync(srv_yml_prefix_path) ?
|
|
@@ -37,13 +38,6 @@ const srv_yml = async (model, spec) => {
|
|
|
37
38
|
if ((_c = (_b = (_a = srv.gen) === null || _a === void 0 ? void 0 : _a.custom) === null || _b === void 0 ? void 0 : _b.lambda) === null || _c === void 0 ? void 0 : _c.srv_yml) {
|
|
38
39
|
return srv.gen.custom.lambda.srv_yml;
|
|
39
40
|
}
|
|
40
|
-
// TODO: this should be a JSON structure exported as YAML
|
|
41
|
-
let srvyml = `${name}:
|
|
42
|
-
handler: ${handler.path.prefix}${name}${handler.path.suffix}
|
|
43
|
-
role: Basic${AppName}LambdaRole
|
|
44
|
-
timeout: ${lambda.timeout}
|
|
45
|
-
memorySize: ${lambda.memory || 1024}
|
|
46
|
-
`;
|
|
47
41
|
const web = srv.api.web;
|
|
48
42
|
let events = '';
|
|
49
43
|
let onEvents = srv.on;
|
|
@@ -148,13 +142,21 @@ ${corsprops}
|
|
|
148
142
|
}
|
|
149
143
|
}
|
|
150
144
|
}
|
|
145
|
+
let eventsBlock = '';
|
|
151
146
|
if ('' !== events) {
|
|
152
|
-
|
|
147
|
+
eventsBlock = (0, generate_1.TM)(`
|
|
153
148
|
events:
|
|
154
149
|
${events}
|
|
155
150
|
`);
|
|
156
151
|
}
|
|
157
|
-
return
|
|
152
|
+
return (0, generate_1.renderFragment)(frag, {
|
|
153
|
+
name,
|
|
154
|
+
handler: handler.path.prefix + name + handler.path.suffix,
|
|
155
|
+
AppName,
|
|
156
|
+
timeout: lambda.timeout,
|
|
157
|
+
memory: lambda.memory || 1024,
|
|
158
|
+
events: eventsBlock,
|
|
159
|
+
});
|
|
158
160
|
}).join('\n\n\n') +
|
|
159
161
|
suffixContent;
|
|
160
162
|
await (0, generate_1.generate)(spec.folder, [{ name: 'srv.yml', content }]);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"srv_yml.js","sourceRoot":"","sources":["../../../env/lambda/srv_yml.ts"],"names":[],"mappings":";AAAA,oDAAoD;;;;;;AAEpD,0EAA0E;AAC1E,iDAAiD;AAEjD,4CAAmB;AACnB,gDAAuB;AAEvB,uCAAuC;AAEvC,2CAAgD;AAEhD,
|
|
1
|
+
{"version":3,"file":"srv_yml.js","sourceRoot":"","sources":["../../../env/lambda/srv_yml.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
/* Copyright © 2022-2026 Voxgig Ltd, MIT License. */
|
|
2
|
+
|
|
3
|
+
// Shared generation utilities for the lambda templates. File output goes
|
|
4
|
+
// through the jostraca templating library (Project/File/Content components),
|
|
5
|
+
// which also maintains .jostraca/ build metadata next to the outputs.
|
|
6
|
+
|
|
7
|
+
import Fs from 'fs'
|
|
8
|
+
import Path from 'path'
|
|
9
|
+
|
|
10
|
+
import { Jostraca, Project, File, Content } from 'jostraca'
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
// The text shape of each generated output lives in a jostraca-style
|
|
14
|
+
// fragment file with $$slot$$ placeholders. Fragments ship with this
|
|
15
|
+
// package under tm/lambda/, and a project can shadow any of them by
|
|
16
|
+
// placing a same-named file in its own tm folder (passed as spec.tm by
|
|
17
|
+
// the project's build actions). The fragment file's final newline is
|
|
18
|
+
// dropped at load, so slot values fully control trailing bytes.
|
|
19
|
+
|
|
20
|
+
// Package tm folder: compiled code lives at <pkg>/dist/env/lambda (three
|
|
21
|
+
// levels down), but test transforms run the source at <pkg>/env/lambda
|
|
22
|
+
// (two levels down) - probe both.
|
|
23
|
+
const PKG_TM = [
|
|
24
|
+
Path.join(__dirname, '..', '..', '..', 'tm', 'lambda'),
|
|
25
|
+
Path.join(__dirname, '..', '..', 'tm', 'lambda'),
|
|
26
|
+
].find((p) => Fs.existsSync(p)) ||
|
|
27
|
+
Path.join(__dirname, '..', '..', '..', 'tm', 'lambda')
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
function loadFragment(name: string, spec?: { tm?: string }): string {
|
|
31
|
+
const candidates = []
|
|
32
|
+
if (spec?.tm) {
|
|
33
|
+
candidates.push(Path.join(spec.tm, name))
|
|
34
|
+
}
|
|
35
|
+
candidates.push(Path.join(PKG_TM, name))
|
|
36
|
+
|
|
37
|
+
for (const c of candidates) {
|
|
38
|
+
if (Fs.existsSync(c)) {
|
|
39
|
+
let src = Fs.readFileSync(c, 'utf8')
|
|
40
|
+
if (src.endsWith('\n')) {
|
|
41
|
+
src = src.substring(0, src.length - 1)
|
|
42
|
+
}
|
|
43
|
+
return src
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
throw new Error('@voxgig/build: fragment not found: ' + name +
|
|
47
|
+
' (looked in ' + candidates.join(', ') + ')')
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
// Literal $$slot$$ substitution (split/join - values are never
|
|
52
|
+
// interpreted, so ${...}, $&, etc. pass through untouched).
|
|
53
|
+
function renderFragment(src: string, slots: Record<string, any>): string {
|
|
54
|
+
let out = src
|
|
55
|
+
for (const key of Object.keys(slots)) {
|
|
56
|
+
out = out.split('$$' + key + '$$').join(String(slots[key]))
|
|
57
|
+
}
|
|
58
|
+
return out
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
|
|
62
|
+
// Fragment names shipped by this package (for tooling: list/eject).
|
|
63
|
+
function listFragments(): string[] {
|
|
64
|
+
return Fs.readdirSync(PKG_TM).filter((f) => f.endsWith('.frag')).sort()
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
|
|
68
|
+
// Generate one or more files in folder, each with exact content.
|
|
69
|
+
async function generate(
|
|
70
|
+
folder: string,
|
|
71
|
+
files: { name: string, content: string }[]
|
|
72
|
+
) {
|
|
73
|
+
const jostraca = Jostraca()
|
|
74
|
+
|
|
75
|
+
await jostraca.generate({ folder }, () => {
|
|
76
|
+
Project({}, () => {
|
|
77
|
+
for (const f of files) {
|
|
78
|
+
File({ name: f.name }, () => {
|
|
79
|
+
Content(f.content)
|
|
80
|
+
})
|
|
81
|
+
}
|
|
82
|
+
})
|
|
83
|
+
})
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
|
|
87
|
+
function empty(o: any) {
|
|
88
|
+
return null == o ? true : 0 === Object.keys(o).length
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
// Strip inital newline
|
|
92
|
+
function TM(str: string) {
|
|
93
|
+
return str.replace(/^\n/, '')
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
|
|
97
|
+
export {
|
|
98
|
+
generate,
|
|
99
|
+
empty,
|
|
100
|
+
TM,
|
|
101
|
+
loadFragment,
|
|
102
|
+
renderFragment,
|
|
103
|
+
listFragments,
|
|
104
|
+
PKG_TM,
|
|
105
|
+
}
|
|
@@ -0,0 +1,140 @@
|
|
|
1
|
+
/* Copyright © 2022-2026 Voxgig Ltd, MIT License. */
|
|
2
|
+
|
|
3
|
+
// gen/serverless resources template: SQS queues, DynamoDB tables (via
|
|
4
|
+
// yml/res_dynamo_yml), and the basic Lambda IAM role.
|
|
5
|
+
|
|
6
|
+
import Fs from 'fs'
|
|
7
|
+
import Path from 'path'
|
|
8
|
+
|
|
9
|
+
import { dive, camelify } from '@voxgig/util'
|
|
10
|
+
|
|
11
|
+
import { MsgMetaShape } from '../../shape/msg'
|
|
12
|
+
import { CoreConfShape, CloudConfShape } from '../../shape/conf'
|
|
13
|
+
|
|
14
|
+
import { res_dynamo_yml } from '../../yml/res_dynamo_yml'
|
|
15
|
+
|
|
16
|
+
import { generate, loadFragment, renderFragment } from './generate'
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
const resources_yml = async (model: any, spec: {
|
|
20
|
+
folder: string,
|
|
21
|
+
filename: string
|
|
22
|
+
custom: string,
|
|
23
|
+
tm?: string
|
|
24
|
+
}) => {
|
|
25
|
+
|
|
26
|
+
const queueFrag = loadFragment('res.queue.yml.frag', spec)
|
|
27
|
+
const roleFrag = loadFragment('res.role.yml.frag', spec)
|
|
28
|
+
|
|
29
|
+
const core = CoreConfShape(model.main.conf.core)
|
|
30
|
+
|
|
31
|
+
const appname = core.name
|
|
32
|
+
const AppName = camelify(appname)
|
|
33
|
+
|
|
34
|
+
const cloud = CloudConfShape(model.main.conf.cloud)
|
|
35
|
+
|
|
36
|
+
const region = cloud.aws.region
|
|
37
|
+
const accountid = cloud.aws.accountid
|
|
38
|
+
|
|
39
|
+
let filename = spec.filename || 'resources.yml'
|
|
40
|
+
|
|
41
|
+
let resources_yml_prefix_path = Path.join(spec.folder, 'res.prefix.yml')
|
|
42
|
+
let resources_yml_suffix_path = Path.join(spec.folder, 'res.suffix.yml')
|
|
43
|
+
|
|
44
|
+
let prefixContent = Fs.existsSync(resources_yml_prefix_path) ?
|
|
45
|
+
Fs.readFileSync(resources_yml_prefix_path) : ''
|
|
46
|
+
let suffixContent = Fs.existsSync(resources_yml_suffix_path) ?
|
|
47
|
+
Fs.readFileSync(resources_yml_suffix_path) : ''
|
|
48
|
+
|
|
49
|
+
const dynamoResources: { arn: string }[] = []
|
|
50
|
+
|
|
51
|
+
let content =
|
|
52
|
+
`# START
|
|
53
|
+
`
|
|
54
|
+
|
|
55
|
+
content +=
|
|
56
|
+
prefixContent +
|
|
57
|
+
|
|
58
|
+
await res_dynamo_yml(model, { dynamoResources, region, accountid })
|
|
59
|
+
|
|
60
|
+
// content +=
|
|
61
|
+
let queueDefs = dive(model.main.msg, 128).map((entry: any) => {
|
|
62
|
+
let path = entry[0]
|
|
63
|
+
let msgMeta = MsgMetaShape(entry[1])
|
|
64
|
+
|
|
65
|
+
let pathname = path
|
|
66
|
+
.map((p: string) =>
|
|
67
|
+
(p[0] + '').toUpperCase() + p.substring(1))
|
|
68
|
+
.join('')
|
|
69
|
+
|
|
70
|
+
// console.log('MQ', pathname, msgMeta)
|
|
71
|
+
|
|
72
|
+
if (msgMeta.transport?.queue?.active) {
|
|
73
|
+
// console.log('MM', path, msgMeta)
|
|
74
|
+
let queue = msgMeta.transport.queue
|
|
75
|
+
let name = queue.name || pathname
|
|
76
|
+
|
|
77
|
+
// TODO: aontu should do this, but needs recursive child conjuncts
|
|
78
|
+
let stage_suffix =
|
|
79
|
+
(false === queue.stage?.active) ? '' : '-${self:provider.stage,"dev"}'
|
|
80
|
+
|
|
81
|
+
let queue_suffix = (null == queue.suffix || '' == queue.suffix) ? '' :
|
|
82
|
+
'-' + queue.suffix
|
|
83
|
+
|
|
84
|
+
let resname = 'Queue' + name
|
|
85
|
+
|
|
86
|
+
let queueName =
|
|
87
|
+
(queue.prefix || '') +
|
|
88
|
+
path.reduce((s: string, p: string, i: number) =>
|
|
89
|
+
(s += p + (i % 2 ?
|
|
90
|
+
(i == path.length - 1 ? '' : '-') : '_')), '') +
|
|
91
|
+
(queue_suffix || '') +
|
|
92
|
+
(stage_suffix || '')
|
|
93
|
+
|
|
94
|
+
let queueTimeout = queue.timeout || 30
|
|
95
|
+
|
|
96
|
+
return renderFragment(queueFrag, {
|
|
97
|
+
resname,
|
|
98
|
+
queueName,
|
|
99
|
+
queueTimeout,
|
|
100
|
+
})
|
|
101
|
+
}
|
|
102
|
+
return ''
|
|
103
|
+
}).filter(n => '' !== n).join('')
|
|
104
|
+
|
|
105
|
+
// console.log('queueDefs', queueDefs)
|
|
106
|
+
|
|
107
|
+
content += '\n\n' + queueDefs
|
|
108
|
+
|
|
109
|
+
let customLambdaPolicyStatementPath =
|
|
110
|
+
Path.join(spec.folder, 'res.lambda.policy.statements.yml')
|
|
111
|
+
let customLambdaPolicyStatementContent = Fs.existsSync(customLambdaPolicyStatementPath) ?
|
|
112
|
+
Fs.readFileSync(customLambdaPolicyStatementPath) : ''
|
|
113
|
+
|
|
114
|
+
|
|
115
|
+
|
|
116
|
+
content += renderFragment(roleFrag, {
|
|
117
|
+
AppName,
|
|
118
|
+
dynamoArns: dynamoResources.map(r => ' - ' + r.arn).join('\n'),
|
|
119
|
+
customPolicy: customLambdaPolicyStatementContent,
|
|
120
|
+
})
|
|
121
|
+
|
|
122
|
+
|
|
123
|
+
|
|
124
|
+
if (spec.custom) {
|
|
125
|
+
content = Fs.readFileSync(spec.custom).toString() + '\n\n\n' + content
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
content += suffixContent
|
|
129
|
+
|
|
130
|
+
content += `
|
|
131
|
+
# END
|
|
132
|
+
`
|
|
133
|
+
|
|
134
|
+
await generate(spec.folder, [{ name: filename, content }])
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
|
|
138
|
+
export {
|
|
139
|
+
resources_yml,
|
|
140
|
+
}
|
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
/* Copyright © 2022-2026 Voxgig Ltd, MIT License. */
|
|
2
|
+
|
|
3
|
+
// Lambda handler template: one handler source file per lambda service,
|
|
4
|
+
// bootstrapping Seneca via the env folder and delegating to gateway-lambda.
|
|
5
|
+
|
|
6
|
+
import { dive, get, pinify } from '@voxgig/util'
|
|
7
|
+
|
|
8
|
+
import { MsgMetaShape } from '../../shape/msg'
|
|
9
|
+
|
|
10
|
+
import { generate, loadFragment, renderFragment } from './generate'
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
// Only create if does not exist
|
|
14
|
+
const srv_handler = async (model: any, spec: {
|
|
15
|
+
folder: string
|
|
16
|
+
start?: string
|
|
17
|
+
env?: {
|
|
18
|
+
folder: string
|
|
19
|
+
}
|
|
20
|
+
lang?: string
|
|
21
|
+
tm?: string
|
|
22
|
+
}) => {
|
|
23
|
+
let lang = spec.lang || 'js'
|
|
24
|
+
|
|
25
|
+
const frag = loadFragment('srv_handler.' + lang + '.frag', spec)
|
|
26
|
+
|
|
27
|
+
const files: { name: string, content: string }[] = []
|
|
28
|
+
|
|
29
|
+
Object
|
|
30
|
+
.entries(model.main.srv)
|
|
31
|
+
.filter((entry: any) => entry[1].env?.lambda)
|
|
32
|
+
.forEach((entry: any) => {
|
|
33
|
+
const name = entry[0]
|
|
34
|
+
const srv = entry[1]
|
|
35
|
+
|
|
36
|
+
if ('custom' === srv.env.lambda.kind) {
|
|
37
|
+
return
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
let start = spec.start || 'setup'
|
|
41
|
+
let envFolder = spec.env?.folder || '../../../env/lambda'
|
|
42
|
+
|
|
43
|
+
let handler = 'handler'
|
|
44
|
+
let modify = ''
|
|
45
|
+
|
|
46
|
+
// if (!srv.api.web.active) {
|
|
47
|
+
// if (srv.on && 0 < Object.keys(srv.on).length) {
|
|
48
|
+
// handler = 'eventhandler'
|
|
49
|
+
// modify = `
|
|
50
|
+
// event = {
|
|
51
|
+
// ...event,
|
|
52
|
+
// // TODO: @voxgig/system? util needed to handle this dynamically
|
|
53
|
+
// seneca$: { msg: '${srv.on[Object.keys(srv.on)[0]].events[0].msg}' },
|
|
54
|
+
// }
|
|
55
|
+
// `
|
|
56
|
+
// }
|
|
57
|
+
// }
|
|
58
|
+
|
|
59
|
+
|
|
60
|
+
let prepare = ''
|
|
61
|
+
let complete = ''
|
|
62
|
+
|
|
63
|
+
|
|
64
|
+
dive(model.main.msg.aim[name], 128).map((entry: any) => {
|
|
65
|
+
let path = ['aim', name, ...entry[0]]
|
|
66
|
+
let msgMeta = MsgMetaShape(entry[1])
|
|
67
|
+
let pin = pinify(path)
|
|
68
|
+
if (msgMeta.transport?.queue?.active) {
|
|
69
|
+
complete += `
|
|
70
|
+
seneca.listen({type:'sqs',pin:'${pin}'})`
|
|
71
|
+
}
|
|
72
|
+
})
|
|
73
|
+
|
|
74
|
+
|
|
75
|
+
dive(model.main.srv[name].out, 128).map((entry: any) => {
|
|
76
|
+
let path = entry[0]
|
|
77
|
+
let msgMetaMaybe = get(model.main.msg, path)
|
|
78
|
+
// console.log(name, path, msgMetaMaybe)
|
|
79
|
+
if (msgMetaMaybe?.$) {
|
|
80
|
+
let msgMeta = MsgMetaShape(msgMetaMaybe?.$)
|
|
81
|
+
let pin = pinify(path)
|
|
82
|
+
|
|
83
|
+
if (msgMeta.transport?.queue?.active) {
|
|
84
|
+
complete += `
|
|
85
|
+
seneca.client({type:'sqs',pin:'${pin}'})`
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
})
|
|
89
|
+
|
|
90
|
+
let makeGatewayHandler = false
|
|
91
|
+
let onlist = model.main.srv[name].on || {}
|
|
92
|
+
Object.entries(onlist).map((onitem: any) => {
|
|
93
|
+
onitem[1].events.map((event: any) => {
|
|
94
|
+
if ('s3' === event.source) {
|
|
95
|
+
if (!makeGatewayHandler) {
|
|
96
|
+
complete += `
|
|
97
|
+
|
|
98
|
+
const makeGatewayHandler = seneca.export('s3-store/makeGatewayHandler')`
|
|
99
|
+
makeGatewayHandler = true
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
complete += `
|
|
103
|
+
seneca
|
|
104
|
+
.act('sys:gateway,kind:lambda,add:hook,hook:handler', {
|
|
105
|
+
handler: makeGatewayHandler('${event.msg}') })`
|
|
106
|
+
}
|
|
107
|
+
})
|
|
108
|
+
})
|
|
109
|
+
|
|
110
|
+
|
|
111
|
+
const content = renderFragment(frag, {
|
|
112
|
+
envFolder,
|
|
113
|
+
start,
|
|
114
|
+
name,
|
|
115
|
+
complete,
|
|
116
|
+
modify,
|
|
117
|
+
prepare,
|
|
118
|
+
handler,
|
|
119
|
+
})
|
|
120
|
+
|
|
121
|
+
files.push({ name: name + '.' + lang, content })
|
|
122
|
+
})
|
|
123
|
+
|
|
124
|
+
if (0 < files.length) {
|
|
125
|
+
await generate(spec.folder, files)
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
|
|
130
|
+
export {
|
|
131
|
+
srv_handler,
|
|
132
|
+
}
|
|
@@ -0,0 +1,201 @@
|
|
|
1
|
+
/* Copyright © 2022-2026 Voxgig Ltd, MIT License. */
|
|
2
|
+
|
|
3
|
+
// gen/serverless/srv.yml template: one Serverless function definition per
|
|
4
|
+
// lambda-active service, derived from the model.
|
|
5
|
+
|
|
6
|
+
import Fs from 'fs'
|
|
7
|
+
import Path from 'path'
|
|
8
|
+
|
|
9
|
+
import { camelify } from '@voxgig/util'
|
|
10
|
+
|
|
11
|
+
import { CoreConfShape } from '../../shape/conf'
|
|
12
|
+
|
|
13
|
+
import { generate, empty, TM, loadFragment, renderFragment } from './generate'
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
const srv_yml = async (model: any, spec: {
|
|
17
|
+
folder: string
|
|
18
|
+
tm?: string
|
|
19
|
+
}) => {
|
|
20
|
+
|
|
21
|
+
const core = CoreConfShape(model.main.conf.core)
|
|
22
|
+
|
|
23
|
+
let appname = core.name
|
|
24
|
+
let AppName = camelify(appname)
|
|
25
|
+
|
|
26
|
+
const frag = loadFragment('srv.yml.frag', spec)
|
|
27
|
+
|
|
28
|
+
let srv_yml_prefix_path = Path.join(spec.folder, 'srv.prefix.yml')
|
|
29
|
+
let srv_yml_suffix_path = Path.join(spec.folder, 'srv.suffix.yml')
|
|
30
|
+
|
|
31
|
+
let prefixContent = Fs.existsSync(srv_yml_prefix_path) ?
|
|
32
|
+
Fs.readFileSync(srv_yml_prefix_path) : ''
|
|
33
|
+
let suffixContent = Fs.existsSync(srv_yml_suffix_path) ?
|
|
34
|
+
Fs.readFileSync(srv_yml_suffix_path) : ''
|
|
35
|
+
|
|
36
|
+
let content =
|
|
37
|
+
|
|
38
|
+
prefixContent +
|
|
39
|
+
Object
|
|
40
|
+
.entries(model.main.srv)
|
|
41
|
+
.filter((entry: any) => entry[1].env?.lambda?.active)
|
|
42
|
+
.map((entry: any) => {
|
|
43
|
+
const name = entry[0]
|
|
44
|
+
const srv = entry[1]
|
|
45
|
+
|
|
46
|
+
const lambda = srv.env.lambda
|
|
47
|
+
const handler = lambda.handler
|
|
48
|
+
|
|
49
|
+
// NOTE: gen.custom convention: allows for complete overwrite
|
|
50
|
+
// as a get-out-of-jail
|
|
51
|
+
if (srv.gen?.custom?.lambda?.srv_yml) {
|
|
52
|
+
return srv.gen.custom.lambda.srv_yml
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
const web = srv.api.web
|
|
56
|
+
|
|
57
|
+
let events = ''
|
|
58
|
+
|
|
59
|
+
let onEvents = srv.on
|
|
60
|
+
|
|
61
|
+
if (onEvents) {
|
|
62
|
+
Object.entries(onEvents).forEach((entry: any[]) => {
|
|
63
|
+
// let name = entry[0]
|
|
64
|
+
let spec = entry[1]
|
|
65
|
+
|
|
66
|
+
if ('aws' === spec.provider) {
|
|
67
|
+
spec.events.forEach((ev: any) => {
|
|
68
|
+
if ('s3' === ev.source) {
|
|
69
|
+
events += TM(`
|
|
70
|
+
- s3:
|
|
71
|
+
bucket: ${ev.bucket}
|
|
72
|
+
event: ${ev.event}
|
|
73
|
+
existing: true
|
|
74
|
+
`)
|
|
75
|
+
if (ev.rules) {
|
|
76
|
+
events += TM(`
|
|
77
|
+
rules:
|
|
78
|
+
`)
|
|
79
|
+
if (ev.rules.prefix) {
|
|
80
|
+
events += TM(`
|
|
81
|
+
- prefix: ${ev.rules.prefix}
|
|
82
|
+
`)
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
if (ev.rules.suffix) {
|
|
86
|
+
events += TM(`
|
|
87
|
+
- suffix: ${ev.rules.suffix}
|
|
88
|
+
`)
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
else if ('schedule' === ev.source) {
|
|
93
|
+
let entries =
|
|
94
|
+
'string' === typeof ev.recur ? [ev.recur] : (ev.recur || [])
|
|
95
|
+
let recur = entries.map((entry: string) => {
|
|
96
|
+
let schedule = `
|
|
97
|
+
- schedule:
|
|
98
|
+
rate: ${entry}`
|
|
99
|
+
if (ev.msg) {
|
|
100
|
+
schedule += `
|
|
101
|
+
input:
|
|
102
|
+
msg: ${JSON.stringify(ev.msg)} `
|
|
103
|
+
}
|
|
104
|
+
return schedule
|
|
105
|
+
})
|
|
106
|
+
|
|
107
|
+
events += TM(`
|
|
108
|
+
${recur}
|
|
109
|
+
`)
|
|
110
|
+
|
|
111
|
+
}
|
|
112
|
+
else if ('sqs' === ev.source) {
|
|
113
|
+
events += TM(`
|
|
114
|
+
- sqs:
|
|
115
|
+
arn:
|
|
116
|
+
Fn::GetAtt:
|
|
117
|
+
- ${ev.qrn}
|
|
118
|
+
- Arn
|
|
119
|
+
batchSize: 1
|
|
120
|
+
`)
|
|
121
|
+
|
|
122
|
+
}
|
|
123
|
+
})
|
|
124
|
+
}
|
|
125
|
+
})
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
// TODO: move to `on`
|
|
129
|
+
if (web.active) {
|
|
130
|
+
let prefix = web.path.prefix
|
|
131
|
+
let suffix = web.path.suffix
|
|
132
|
+
let area = web.path.area
|
|
133
|
+
let method = web.method
|
|
134
|
+
let corsflag = 'false'
|
|
135
|
+
let corsprops = ''
|
|
136
|
+
|
|
137
|
+
let methods = method.split(',')
|
|
138
|
+
// console.log('METHODS', methods)
|
|
139
|
+
|
|
140
|
+
if (web.cors.active) {
|
|
141
|
+
corsflag = 'true'
|
|
142
|
+
if (web.cors.props && !empty(web.cors.props)) {
|
|
143
|
+
corsflag = ''
|
|
144
|
+
corsprops = Object
|
|
145
|
+
.entries(web.cors.props)
|
|
146
|
+
.reduce(((a: any, nv: any) => (
|
|
147
|
+
a += ` ${nv[0]}: ${nv[1]}\n`
|
|
148
|
+
, a)), '')
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
if ('v2' === web.lambda?.gateway) {
|
|
153
|
+
for (let method of methods) {
|
|
154
|
+
events += TM(`
|
|
155
|
+
- httpApi:
|
|
156
|
+
path: "${prefix}${area}${name}${suffix}"
|
|
157
|
+
method: ${method}
|
|
158
|
+
`)
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
else {
|
|
162
|
+
for (let method of methods) {
|
|
163
|
+
events += TM(`
|
|
164
|
+
- http:
|
|
165
|
+
path: "${prefix}${area}${name}${suffix}"
|
|
166
|
+
method: ${method}
|
|
167
|
+
cors: ${corsflag}
|
|
168
|
+
${corsprops}
|
|
169
|
+
`)
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
|
|
175
|
+
|
|
176
|
+
let eventsBlock = ''
|
|
177
|
+
if ('' !== events) {
|
|
178
|
+
eventsBlock = TM(`
|
|
179
|
+
events:
|
|
180
|
+
${events}
|
|
181
|
+
`)
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
return renderFragment(frag, {
|
|
185
|
+
name,
|
|
186
|
+
handler: handler.path.prefix + name + handler.path.suffix,
|
|
187
|
+
AppName,
|
|
188
|
+
timeout: lambda.timeout,
|
|
189
|
+
memory: lambda.memory || 1024,
|
|
190
|
+
events: eventsBlock,
|
|
191
|
+
})
|
|
192
|
+
}).join('\n\n\n') +
|
|
193
|
+
suffixContent
|
|
194
|
+
|
|
195
|
+
await generate(spec.folder, [{ name: 'srv.yml', content }])
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
|
|
199
|
+
export {
|
|
200
|
+
srv_yml,
|
|
201
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@voxgig/build",
|
|
3
|
-
"version": "4.
|
|
3
|
+
"version": "4.1.0",
|
|
4
4
|
"main": "dist/build.js",
|
|
5
5
|
"type": "commonjs",
|
|
6
6
|
"types": "dist/build.d.ts",
|
|
@@ -18,7 +18,7 @@
|
|
|
18
18
|
"url": "git://github.com/voxgig/build.git"
|
|
19
19
|
},
|
|
20
20
|
"scripts": {
|
|
21
|
-
"model-s01": "voxgig-model test/s01/model/model.
|
|
21
|
+
"model-s01": "voxgig-model test/s01/model/model.aontu",
|
|
22
22
|
"test": "jest --coverage",
|
|
23
23
|
"test-some": "jest -t",
|
|
24
24
|
"test-watch": "jest --coverage --watchAll",
|
|
@@ -42,7 +42,9 @@
|
|
|
42
42
|
"lib",
|
|
43
43
|
"dist",
|
|
44
44
|
"bin",
|
|
45
|
-
"LICENSE"
|
|
45
|
+
"LICENSE",
|
|
46
|
+
"tm",
|
|
47
|
+
"env"
|
|
46
48
|
],
|
|
47
49
|
"dependencies": {
|
|
48
50
|
"@voxgig/util": "0.5.4",
|
|
@@ -54,7 +56,7 @@
|
|
|
54
56
|
"@types/jest": "^29.5.12",
|
|
55
57
|
"@types/js-yaml": "^4.0.9",
|
|
56
58
|
"@types/node": "26.1.2",
|
|
57
|
-
"@voxgig/model": "^2.
|
|
59
|
+
"@voxgig/model": "^9.2.4",
|
|
58
60
|
"@voxgig/system": "^1.2.0",
|
|
59
61
|
"esbuild": "^0.23.0",
|
|
60
62
|
"jest": "^29.7.0",
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
|
|
2
|
+
Basic$$AppName$$LambdaRole:
|
|
3
|
+
Type: AWS::IAM::Role
|
|
4
|
+
Properties:
|
|
5
|
+
RoleName: Basic$$AppName$$LambdaRole${self:custom.index.BasicLambdaRole,"01"}
|
|
6
|
+
AssumeRolePolicyDocument:
|
|
7
|
+
Version: '2012-10-17'
|
|
8
|
+
Statement:
|
|
9
|
+
- Effect: Allow
|
|
10
|
+
Principal:
|
|
11
|
+
Service:
|
|
12
|
+
- lambda.amazonaws.com
|
|
13
|
+
- events.amazonaws.com
|
|
14
|
+
- ecs-tasks.amazonaws.com
|
|
15
|
+
Action: sts:AssumeRole
|
|
16
|
+
Policies:
|
|
17
|
+
- PolicyName: LambdaServiceAccess
|
|
18
|
+
PolicyDocument:
|
|
19
|
+
Version: '2012-10-17'
|
|
20
|
+
Statement:
|
|
21
|
+
- Effect: Allow
|
|
22
|
+
Action:
|
|
23
|
+
- dynamodb:DescribeTable
|
|
24
|
+
- dynamodb:GetItem
|
|
25
|
+
- dynamodb:PutItem
|
|
26
|
+
- dynamodb:UpdateItem
|
|
27
|
+
- dynamodb:DeleteItem
|
|
28
|
+
- dynamodb:Query
|
|
29
|
+
- dynamodb:Scan
|
|
30
|
+
Resource:
|
|
31
|
+
$$dynamoArns$$
|
|
32
|
+
$$customPolicy$$
|
|
33
|
+
ManagedPolicyArns:
|
|
34
|
+
- arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole
|
|
35
|
+
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
const getSeneca = require('$$envFolder$$/$$start$$')
|
|
2
|
+
|
|
3
|
+
function complete(seneca: any) {$$complete$$
|
|
4
|
+
}
|
|
5
|
+
|
|
6
|
+
exports.handler = async (
|
|
7
|
+
event,
|
|
8
|
+
context
|
|
9
|
+
) => {
|
|
10
|
+
$$modify$$
|
|
11
|
+
let seneca = await getSeneca('$$name$$', complete)
|
|
12
|
+
$$prepare$$
|
|
13
|
+
let handler = seneca.export('gateway-lambda/$$handler$$')
|
|
14
|
+
let res = await handler(event, context)
|
|
15
|
+
return res
|
|
16
|
+
}
|
|
17
|
+
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { getSeneca } from '$$envFolder$$/$$start$$'
|
|
2
|
+
|
|
3
|
+
function complete(seneca: any) {$$complete$$
|
|
4
|
+
}
|
|
5
|
+
|
|
6
|
+
exports.handler = async (
|
|
7
|
+
event:any,
|
|
8
|
+
context:any
|
|
9
|
+
) => {
|
|
10
|
+
$$modify$$
|
|
11
|
+
let seneca = await getSeneca('$$name$$', complete)
|
|
12
|
+
$$prepare$$
|
|
13
|
+
let handler = seneca.export('gateway-lambda/$$handler$$')
|
|
14
|
+
let res = await handler(event, context)
|
|
15
|
+
return res
|
|
16
|
+
}
|
|
17
|
+
|