alp-node 7.0.0 → 9.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 +39 -0
- package/README.md +7 -7
- package/dist/{AlpNodeApp-node18.mjs → AlpNodeApp-node.mjs} +136 -134
- package/dist/AlpNodeApp-node.mjs.map +1 -0
- package/dist/definitions/AlpNodeApp.d.ts +16 -17
- package/dist/definitions/AlpNodeApp.d.ts.map +1 -1
- package/dist/definitions/config.d.ts +4 -5
- package/dist/definitions/config.d.ts.map +1 -1
- package/dist/definitions/errors.d.ts +1 -2
- package/dist/definitions/errors.d.ts.map +1 -1
- package/dist/definitions/index.d.ts +8 -8
- package/dist/definitions/language.d.ts +1 -1
- package/dist/definitions/language.d.ts.map +1 -1
- package/dist/definitions/listen.d.ts +2 -3
- package/dist/definitions/listen.d.ts.map +1 -1
- package/dist/definitions/params/ParamValid.d.ts +2 -3
- package/dist/definitions/params/ParamValid.d.ts.map +1 -1
- package/dist/definitions/params/ParamValueFromContext.d.ts +3 -4
- package/dist/definitions/params/ParamValueFromContext.d.ts.map +1 -1
- package/dist/definitions/params/ParamValueModelValidator.d.ts +1 -1
- package/dist/definitions/params/ParamValueStringValidator.d.ts +1 -1
- package/dist/definitions/params/ParamValueValidator.d.ts +1 -1
- package/dist/definitions/params/index.d.ts +8 -4
- package/dist/definitions/params/index.d.ts.map +1 -1
- package/dist/definitions/router.d.ts +3 -4
- package/dist/definitions/router.d.ts.map +1 -1
- package/dist/definitions/translate/index.d.ts +1 -1
- package/dist/definitions/translate/load.d.ts +3 -3
- package/dist/definitions/translate/load.d.ts.map +1 -1
- package/dist/definitions/types.d.ts +6 -6
- package/dist/definitions/types.d.ts.map +1 -1
- package/dist/{index-node18.mjs → index-node.mjs} +233 -225
- package/dist/index-node.mjs.map +1 -0
- package/package.json +26 -25
- package/src/AlpNodeApp.ts +52 -49
- package/src/config.ts +43 -48
- package/src/errors.ts +19 -19
- package/src/index.ts +16 -16
- package/src/language.ts +18 -10
- package/src/listen.ts +16 -16
- package/src/params/ParamValid.ts +3 -3
- package/src/params/ParamValidationResult.test.ts +14 -11
- package/src/params/ParamValueFromContext.ts +5 -5
- package/src/params/ParamValueModelValidator.ts +1 -1
- package/src/params/ParamValueStringValidator.ts +3 -3
- package/src/params/ParamValueValidator.ts +1 -1
- package/src/params/index.ts +17 -13
- package/src/router.ts +7 -7
- package/src/translate/index.ts +9 -9
- package/src/translate/load.ts +13 -12
- package/src/types.ts +8 -8
- package/dist/AlpNodeApp-node18.mjs.map +0 -1
- package/dist/index-node18.mjs.map +0 -1
- package/src/.eslintrc.json +0 -31
|
@@ -1,101 +1,19 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { unlinkSync, chmodSync, readFileSync, existsSync } from 'node:fs';
|
|
2
2
|
import path from 'node:path';
|
|
3
3
|
import { Logger } from 'nightingale-logger';
|
|
4
|
-
import { deprecate } from 'node:util';
|
|
5
4
|
import Koa from 'koa';
|
|
6
5
|
import compress from 'koa-compress';
|
|
7
6
|
import serve from 'koa-static';
|
|
8
|
-
import deepFreeze from 'deep-freeze-es6';
|
|
9
|
-
import minimist from 'minimist';
|
|
10
|
-
import parseJSON from 'parse-json-object-as-map';
|
|
11
7
|
import { STATUS_CODES, createServer as createServer$2 } from 'node:http';
|
|
12
8
|
import ErrorHtmlRenderer from 'error-html';
|
|
13
9
|
import { defineLazyProperty } from 'object-properties';
|
|
14
10
|
import { createServer as createServer$1 } from 'node:https';
|
|
15
11
|
import IntlMessageFormatDefault from 'intl-messageformat';
|
|
12
|
+
import deepFreeze from 'deep-freeze-es6';
|
|
13
|
+
import minimist from 'minimist';
|
|
16
14
|
import { createRouterBuilder } from 'router-segments';
|
|
17
15
|
|
|
18
|
-
const
|
|
19
|
-
function _existsConfigSync(dirname, name) {
|
|
20
|
-
return existsSync(`${dirname}${name}.json`);
|
|
21
|
-
}
|
|
22
|
-
function _loadConfigSync(dirname, name) {
|
|
23
|
-
const content = readFileSync(`${dirname}${name}.json`, 'utf8');
|
|
24
|
-
return parseJSON(content);
|
|
25
|
-
}
|
|
26
|
-
class Config {
|
|
27
|
-
constructor(dirname, options) {
|
|
28
|
-
this._map = new Map();
|
|
29
|
-
this._dirname = dirname.replace(/\/*$/, '/');
|
|
30
|
-
if (options) {
|
|
31
|
-
this.loadSync(options);
|
|
32
|
-
}
|
|
33
|
-
}
|
|
34
|
-
loadSync(options = {}) {
|
|
35
|
-
const env = process.env.CONFIG_ENV || process.env.NODE_ENV || 'development';
|
|
36
|
-
const {
|
|
37
|
-
argv: argvOverrides = [],
|
|
38
|
-
packageConfig,
|
|
39
|
-
version
|
|
40
|
-
} = options;
|
|
41
|
-
this.packageConfig = packageConfig;
|
|
42
|
-
const config = this.loadConfigSync('common');
|
|
43
|
-
for (const [key, value] of this.loadConfigSync(env)) {
|
|
44
|
-
config.set(key, value);
|
|
45
|
-
}
|
|
46
|
-
if (this.existsConfigSync('local')) {
|
|
47
|
-
for (const [key, value] of this.loadConfigSync('local')) {
|
|
48
|
-
config.set(key, value);
|
|
49
|
-
}
|
|
50
|
-
}
|
|
51
|
-
if (config.has('version')) {
|
|
52
|
-
throw new Error('Cannot have "version", in config.');
|
|
53
|
-
}
|
|
54
|
-
config.set('version', String(version || argv.version || packageConfig?.version));
|
|
55
|
-
const socketPath = argv.socket || argv['socket-path'] || argv.socketPath;
|
|
56
|
-
if (socketPath) {
|
|
57
|
-
config.set('socketPath', socketPath);
|
|
58
|
-
} else if (argv.port) {
|
|
59
|
-
config.set('port', argv.port);
|
|
60
|
-
config.delete('socketPath');
|
|
61
|
-
} else if (process.env.PORT) {
|
|
62
|
-
config.set('port', Number(process.env.PORT));
|
|
63
|
-
config.delete('socketPath');
|
|
64
|
-
}
|
|
65
|
-
argvOverrides.forEach(key => {
|
|
66
|
-
const splitted = key.split('.');
|
|
67
|
-
const value = splitted.length > 0 &&
|
|
68
|
-
// eslint-disable-next-line @typescript-eslint/no-unsafe-return,unicorn/no-array-reduce, @typescript-eslint/no-shadow
|
|
69
|
-
splitted.reduce((config, partialKey) => config?.[partialKey], argv);
|
|
70
|
-
if (value !== undefined) {
|
|
71
|
-
const last = splitted.pop();
|
|
72
|
-
const map = splitted.length === 0 ? config :
|
|
73
|
-
// eslint-disable-next-line unicorn/no-array-reduce
|
|
74
|
-
splitted.reduce(
|
|
75
|
-
// eslint-disable-next-line @typescript-eslint/no-shadow
|
|
76
|
-
(config, partialKey) => config.get(partialKey), config);
|
|
77
|
-
map.set(last, value);
|
|
78
|
-
}
|
|
79
|
-
});
|
|
80
|
-
this._map = deepFreeze(config);
|
|
81
|
-
return this;
|
|
82
|
-
}
|
|
83
|
-
get(key) {
|
|
84
|
-
return this._map.get(key);
|
|
85
|
-
}
|
|
86
|
-
existsConfigSync(name) {
|
|
87
|
-
return _existsConfigSync(this._dirname, name);
|
|
88
|
-
}
|
|
89
|
-
loadConfigSync(name) {
|
|
90
|
-
return _loadConfigSync(this._dirname, name);
|
|
91
|
-
}
|
|
92
|
-
}
|
|
93
|
-
function getConfig(app, config) {
|
|
94
|
-
return config;
|
|
95
|
-
}
|
|
96
|
-
|
|
97
|
-
/* eslint-disable complexity */
|
|
98
|
-
const logger$4 = new Logger('alp:errors');
|
|
16
|
+
const logger$4 = new Logger("alp:errors");
|
|
99
17
|
const errorHtmlRenderer = new ErrorHtmlRenderer({
|
|
100
18
|
appPath: `${process.cwd()}/`
|
|
101
19
|
});
|
|
@@ -103,29 +21,22 @@ async function alpNodeErrors(ctx, next) {
|
|
|
103
21
|
try {
|
|
104
22
|
await next();
|
|
105
23
|
} catch (error) {
|
|
106
|
-
|
|
107
|
-
if (
|
|
108
|
-
// eslint-disable-next-line no-ex-assign
|
|
109
|
-
if (typeof error === 'string') error = new Error(error);
|
|
24
|
+
if (!error) error = new Error("Unknown error");
|
|
25
|
+
if (typeof error === "string") error = new Error(error);
|
|
110
26
|
ctx.status = error.status || 500;
|
|
111
|
-
// eslint-disable-next-line @typescript-eslint/no-unsafe-argument
|
|
112
27
|
logger$4.error(error);
|
|
113
|
-
switch (ctx.request.accepts(
|
|
114
|
-
case
|
|
115
|
-
ctx.type =
|
|
116
|
-
if (process.env.NODE_ENV !==
|
|
117
|
-
ctx.body = {
|
|
118
|
-
error: error.message
|
|
119
|
-
};
|
|
28
|
+
switch (ctx.request.accepts("html", "text", "json")) {
|
|
29
|
+
case "json":
|
|
30
|
+
ctx.type = "application/json";
|
|
31
|
+
if (process.env.NODE_ENV !== "production" || error.expose) {
|
|
32
|
+
ctx.body = { error: error.message };
|
|
120
33
|
} else {
|
|
121
|
-
ctx.body = {
|
|
122
|
-
error: STATUS_CODES[ctx.status]
|
|
123
|
-
};
|
|
34
|
+
ctx.body = { error: STATUS_CODES[ctx.status] };
|
|
124
35
|
}
|
|
125
36
|
break;
|
|
126
|
-
case
|
|
127
|
-
ctx.type =
|
|
128
|
-
if (process.env.NODE_ENV !==
|
|
37
|
+
case "html":
|
|
38
|
+
ctx.type = "text/html";
|
|
39
|
+
if (process.env.NODE_ENV !== "production") {
|
|
129
40
|
ctx.body = errorHtmlRenderer.render(error);
|
|
130
41
|
} else if (error.expose) {
|
|
131
42
|
ctx.body = error.message;
|
|
@@ -133,10 +44,11 @@ async function alpNodeErrors(ctx, next) {
|
|
|
133
44
|
throw error;
|
|
134
45
|
}
|
|
135
46
|
break;
|
|
136
|
-
case
|
|
47
|
+
case "text":
|
|
48
|
+
case false:
|
|
137
49
|
default:
|
|
138
|
-
ctx.type =
|
|
139
|
-
if (process.env.NODE_ENV !==
|
|
50
|
+
ctx.type = "text/plain";
|
|
51
|
+
if (process.env.NODE_ENV !== "production" || error.expose) {
|
|
140
52
|
ctx.body = error.message;
|
|
141
53
|
} else {
|
|
142
54
|
throw error;
|
|
@@ -148,22 +60,28 @@ async function alpNodeErrors(ctx, next) {
|
|
|
148
60
|
|
|
149
61
|
function alpLanguage(app) {
|
|
150
62
|
const config = app.context.config;
|
|
151
|
-
const availableLanguages = config.get(
|
|
63
|
+
const availableLanguages = config.get("availableLanguages");
|
|
152
64
|
if (!availableLanguages) {
|
|
153
65
|
throw new Error('Missing config "availableLanguages"');
|
|
154
66
|
}
|
|
155
|
-
defineLazyProperty(
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
67
|
+
defineLazyProperty(
|
|
68
|
+
app.context,
|
|
69
|
+
"language",
|
|
70
|
+
function language() {
|
|
71
|
+
return this.acceptsLanguages(availableLanguages) || availableLanguages[0] || "en";
|
|
72
|
+
}
|
|
73
|
+
);
|
|
74
|
+
defineLazyProperty(
|
|
75
|
+
app.context,
|
|
76
|
+
"firstAcceptedLanguage",
|
|
77
|
+
function firstAcceptedLanguage() {
|
|
78
|
+
return this.acceptsLanguages()[0] || availableLanguages[0] || "en";
|
|
79
|
+
}
|
|
80
|
+
);
|
|
161
81
|
}
|
|
162
82
|
|
|
163
|
-
const logger$3 = new Logger(
|
|
164
|
-
const createServer = (callback, socketPath, tls, dirname =
|
|
165
|
-
// eslint-disable-next-line @typescript-eslint/max-params
|
|
166
|
-
) => {
|
|
83
|
+
const logger$3 = new Logger("alp:listen");
|
|
84
|
+
const createServer = (callback, socketPath, tls, dirname = "") => {
|
|
167
85
|
const createHttpServer = !socketPath && tls ? createServer$1 : createServer$2;
|
|
168
86
|
if (!tls) {
|
|
169
87
|
return createHttpServer(callback);
|
|
@@ -175,35 +93,28 @@ const createServer = (callback, socketPath, tls, dirname = ''
|
|
|
175
93
|
return createHttpServer(options, callback);
|
|
176
94
|
};
|
|
177
95
|
function alpListen(config, callback, dirname) {
|
|
178
|
-
return new Promise(resolve => {
|
|
179
|
-
const socketPath = config.get(
|
|
180
|
-
const port = config.get(
|
|
181
|
-
const hostname = config.get(
|
|
182
|
-
const tls = config.get(
|
|
183
|
-
logger$3.info(
|
|
184
|
-
socketPath
|
|
185
|
-
} : {
|
|
186
|
-
port
|
|
187
|
-
});
|
|
96
|
+
return new Promise((resolve) => {
|
|
97
|
+
const socketPath = config.get("socketPath");
|
|
98
|
+
const port = config.get("port");
|
|
99
|
+
const hostname = config.get("hostname");
|
|
100
|
+
const tls = config.get("tls");
|
|
101
|
+
logger$3.info("Creating server", socketPath ? { socketPath } : { port });
|
|
188
102
|
const server = createServer(callback, socketPath, tls, dirname);
|
|
189
103
|
if (socketPath) {
|
|
190
104
|
try {
|
|
191
105
|
unlinkSync(socketPath);
|
|
192
|
-
} catch {
|
|
106
|
+
} catch {
|
|
107
|
+
}
|
|
193
108
|
server.listen(socketPath, () => {
|
|
194
109
|
if (socketPath) {
|
|
195
|
-
chmodSync(socketPath,
|
|
110
|
+
chmodSync(socketPath, "777");
|
|
196
111
|
}
|
|
197
|
-
logger$3.info(
|
|
198
|
-
socketPath
|
|
199
|
-
});
|
|
112
|
+
logger$3.info("Server listening", { socketPath });
|
|
200
113
|
resolve(server);
|
|
201
114
|
});
|
|
202
115
|
} else {
|
|
203
116
|
server.listen(port, hostname, () => {
|
|
204
|
-
logger$3.info(
|
|
205
|
-
port
|
|
206
|
-
});
|
|
117
|
+
logger$3.info("Server listening", { port });
|
|
207
118
|
resolve(server);
|
|
208
119
|
});
|
|
209
120
|
}
|
|
@@ -211,25 +122,22 @@ function alpListen(config, callback, dirname) {
|
|
|
211
122
|
}
|
|
212
123
|
|
|
213
124
|
class ParamValidationResult {
|
|
125
|
+
_errors;
|
|
214
126
|
_error(name, key, value) {
|
|
215
127
|
if (!this._errors) {
|
|
216
128
|
this._errors = {};
|
|
217
129
|
}
|
|
218
|
-
this._errors[name] = {
|
|
219
|
-
error: key,
|
|
220
|
-
value
|
|
221
|
-
};
|
|
130
|
+
this._errors[name] = { error: key, value };
|
|
222
131
|
}
|
|
223
132
|
getErrors() {
|
|
224
133
|
return this._errors;
|
|
225
134
|
}
|
|
226
135
|
hasErrors() {
|
|
227
|
-
return this._errors !==
|
|
136
|
+
return this._errors !== void 0;
|
|
228
137
|
}
|
|
229
138
|
isValid() {
|
|
230
|
-
return this._errors ===
|
|
139
|
+
return this._errors === void 0;
|
|
231
140
|
}
|
|
232
|
-
|
|
233
141
|
// string(name: string): ParamValueStringValidator {
|
|
234
142
|
// return new ParamValueStringValidator(this, name, this.context.param(name));
|
|
235
143
|
// }
|
|
@@ -245,18 +153,20 @@ class ParamValidationResult {
|
|
|
245
153
|
}
|
|
246
154
|
|
|
247
155
|
class ParamValid extends ParamValidationResult {
|
|
156
|
+
context;
|
|
248
157
|
constructor(context) {
|
|
249
158
|
super();
|
|
250
159
|
this.context = context;
|
|
251
160
|
}
|
|
252
161
|
_error() {
|
|
253
|
-
this.context.throw(400,
|
|
254
|
-
validator: this
|
|
255
|
-
});
|
|
162
|
+
this.context.throw(400, "Invalid params", { validator: this });
|
|
256
163
|
}
|
|
257
164
|
}
|
|
258
165
|
|
|
259
166
|
class ParamValueValidator {
|
|
167
|
+
validationResult;
|
|
168
|
+
name;
|
|
169
|
+
value;
|
|
260
170
|
constructor(validationResult, name, value) {
|
|
261
171
|
this.validationResult = validationResult;
|
|
262
172
|
this.name = name;
|
|
@@ -272,30 +182,42 @@ class ParamValueValidator {
|
|
|
272
182
|
|
|
273
183
|
class ParamValueStringValidator extends ParamValueValidator {
|
|
274
184
|
notEmpty() {
|
|
275
|
-
if (this.value == null || this.value.trim() ===
|
|
276
|
-
this._error(
|
|
185
|
+
if (this.value == null || this.value.trim() === "") {
|
|
186
|
+
this._error("notEmpty");
|
|
277
187
|
}
|
|
278
188
|
return this;
|
|
279
189
|
}
|
|
280
190
|
}
|
|
281
191
|
|
|
282
192
|
class ParamValueFromContext {
|
|
193
|
+
validationResult;
|
|
194
|
+
context;
|
|
283
195
|
constructor(context, validationResult) {
|
|
284
196
|
this.validationResult = validationResult;
|
|
285
197
|
this.context = context;
|
|
286
198
|
}
|
|
287
199
|
namedParam(name) {
|
|
288
|
-
return new ParamValueStringValidator(
|
|
200
|
+
return new ParamValueStringValidator(
|
|
201
|
+
this.validationResult,
|
|
202
|
+
name,
|
|
203
|
+
this.context.namedRouteParam(name)
|
|
204
|
+
);
|
|
289
205
|
}
|
|
290
206
|
otherParam(position) {
|
|
291
|
-
return new ParamValueStringValidator(
|
|
207
|
+
return new ParamValueStringValidator(
|
|
208
|
+
this.validationResult,
|
|
209
|
+
String(position),
|
|
210
|
+
this.context.otherRouteParam(position)
|
|
211
|
+
);
|
|
292
212
|
}
|
|
293
213
|
queryParam(name) {
|
|
294
|
-
return new ParamValueStringValidator(
|
|
214
|
+
return new ParamValueStringValidator(
|
|
215
|
+
this.validationResult,
|
|
216
|
+
name,
|
|
217
|
+
this.context.queryParam(name)
|
|
218
|
+
);
|
|
295
219
|
}
|
|
296
|
-
|
|
297
220
|
// bodyParam: <T>(name: string): ParamValueValidator<string | undefined> {
|
|
298
|
-
|
|
299
221
|
// }
|
|
300
222
|
}
|
|
301
223
|
|
|
@@ -311,65 +233,73 @@ function alpParams(app) {
|
|
|
311
233
|
},
|
|
312
234
|
queryParam(name) {
|
|
313
235
|
const searchParams = this.request.searchParams;
|
|
314
|
-
return searchParams.get(name) ??
|
|
236
|
+
return searchParams.get(name) ?? void 0;
|
|
315
237
|
},
|
|
316
238
|
bodyParam(name) {
|
|
317
|
-
// eslint-disable-next-line @typescript-eslint/no-unsafe-return, @typescript-eslint/no-unsafe-member-access
|
|
318
239
|
return this.body[name];
|
|
319
240
|
}
|
|
320
241
|
});
|
|
321
|
-
defineLazyProperty(
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
242
|
+
defineLazyProperty(
|
|
243
|
+
app.request,
|
|
244
|
+
"searchParams",
|
|
245
|
+
function searchParams() {
|
|
246
|
+
return new URLSearchParams(this.search);
|
|
247
|
+
}
|
|
248
|
+
);
|
|
249
|
+
defineLazyProperty(
|
|
250
|
+
app.context,
|
|
251
|
+
"params",
|
|
252
|
+
function params() {
|
|
253
|
+
return new ParamValueFromContext(this, new ParamValidationResult());
|
|
254
|
+
}
|
|
255
|
+
);
|
|
256
|
+
defineLazyProperty(
|
|
257
|
+
app.context,
|
|
258
|
+
"validParams",
|
|
259
|
+
function validParams() {
|
|
260
|
+
return new ParamValueFromContext(this, new ParamValid(this));
|
|
261
|
+
}
|
|
262
|
+
);
|
|
330
263
|
}
|
|
331
264
|
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
265
|
+
const IntlMessageFormat = (
|
|
266
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
|
|
267
|
+
IntlMessageFormatDefault.default || IntlMessageFormatDefault
|
|
268
|
+
);
|
|
336
269
|
function load(translations, language) {
|
|
337
|
-
const result =
|
|
338
|
-
(function loadMap(
|
|
339
|
-
|
|
340
|
-
if (typeof value ===
|
|
341
|
-
// eslint-disable-next-line @typescript-eslint/no-unsafe-argument
|
|
270
|
+
const result = {};
|
|
271
|
+
(function loadMap(record, prefix) {
|
|
272
|
+
Object.entries(record).forEach(([key, value]) => {
|
|
273
|
+
if (typeof value === "object" && value !== null) {
|
|
342
274
|
loadMap(value, `${prefix}${key}.`);
|
|
343
275
|
return;
|
|
344
276
|
}
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
277
|
+
result[`${prefix}${key}`] = new IntlMessageFormat(
|
|
278
|
+
value,
|
|
279
|
+
language
|
|
280
|
+
);
|
|
348
281
|
});
|
|
349
|
-
})(translations,
|
|
282
|
+
})(translations, "");
|
|
350
283
|
return result;
|
|
351
284
|
}
|
|
352
285
|
|
|
353
|
-
const logger$2 = new Logger(
|
|
286
|
+
const logger$2 = new Logger("alp:translate");
|
|
354
287
|
function alpTranslate(dirname) {
|
|
355
|
-
dirname = dirname.replace(/\/*$/,
|
|
356
|
-
return app => {
|
|
357
|
-
const appTranslations = new Map();
|
|
288
|
+
dirname = dirname.replace(/\/*$/, "/");
|
|
289
|
+
return (app) => {
|
|
290
|
+
const appTranslations = /* @__PURE__ */ new Map();
|
|
358
291
|
Object.assign(app.context, {
|
|
359
292
|
t(id, args) {
|
|
360
|
-
const msg = appTranslations.get(this.language)
|
|
293
|
+
const msg = appTranslations.get(this.language)?.[id];
|
|
361
294
|
if (!msg) {
|
|
362
|
-
logger$2.warn(
|
|
363
|
-
language: this.language,
|
|
364
|
-
id
|
|
365
|
-
});
|
|
295
|
+
logger$2.warn("invalid msg", { language: this.language, id });
|
|
366
296
|
return id;
|
|
367
297
|
}
|
|
368
298
|
return msg.format(args);
|
|
369
299
|
}
|
|
370
300
|
});
|
|
371
301
|
const config = app.config;
|
|
372
|
-
config.get(
|
|
302
|
+
config.get("availableLanguages").forEach((language) => {
|
|
373
303
|
const translations = app.loadConfigSync(dirname + language);
|
|
374
304
|
appTranslations.set(language, load(translations, language));
|
|
375
305
|
});
|
|
@@ -377,8 +307,14 @@ function alpTranslate(dirname) {
|
|
|
377
307
|
};
|
|
378
308
|
}
|
|
379
309
|
|
|
380
|
-
const logger$1 = new Logger(
|
|
310
|
+
const logger$1 = new Logger("alp");
|
|
381
311
|
class AlpNodeApp extends Koa {
|
|
312
|
+
dirname;
|
|
313
|
+
certPath;
|
|
314
|
+
publicPath;
|
|
315
|
+
config;
|
|
316
|
+
_server;
|
|
317
|
+
router;
|
|
382
318
|
/**
|
|
383
319
|
* @param {Object} [options]
|
|
384
320
|
* @param {string} [options.certPath] directory of the ssl certificates
|
|
@@ -393,18 +329,13 @@ class AlpNodeApp extends Koa {
|
|
|
393
329
|
}) {
|
|
394
330
|
super();
|
|
395
331
|
this.dirname = path.normalize(appDirname);
|
|
396
|
-
Object.defineProperty(this, 'packageDirname', {
|
|
397
|
-
get: deprecate(() => packageDirname, 'packageDirname'),
|
|
398
|
-
configurable: false,
|
|
399
|
-
enumerable: false
|
|
400
|
-
});
|
|
401
332
|
this.certPath = certPath || `${packageDirname}/config/cert`;
|
|
402
333
|
this.publicPath = publicPath || `${packageDirname}/public/`;
|
|
403
|
-
this.config =
|
|
334
|
+
this.config = config;
|
|
404
335
|
this.context.config = this.config;
|
|
405
336
|
alpParams(this);
|
|
406
337
|
alpLanguage(this);
|
|
407
|
-
alpTranslate(
|
|
338
|
+
alpTranslate("locales")(this);
|
|
408
339
|
this.use(compress());
|
|
409
340
|
}
|
|
410
341
|
existsConfigSync(name) {
|
|
@@ -419,55 +350,135 @@ class AlpNodeApp extends Koa {
|
|
|
419
350
|
return ctx;
|
|
420
351
|
}
|
|
421
352
|
servePublic() {
|
|
422
|
-
this.use(serve(this.publicPath));
|
|
353
|
+
this.use(serve(this.publicPath));
|
|
423
354
|
}
|
|
424
355
|
catchErrors() {
|
|
425
356
|
this.use(alpNodeErrors);
|
|
426
357
|
}
|
|
427
|
-
|
|
428
|
-
// eslint-disable-next-line @typescript-eslint/class-methods-use-this
|
|
429
358
|
listen() {
|
|
430
|
-
throw new Error(
|
|
359
|
+
throw new Error("Use start instead");
|
|
431
360
|
}
|
|
432
|
-
|
|
433
361
|
/**
|
|
434
362
|
* Close server and emit close event
|
|
435
363
|
*/
|
|
436
364
|
close() {
|
|
437
365
|
if (this._server) {
|
|
438
366
|
this._server.close();
|
|
439
|
-
this.emit(
|
|
367
|
+
this.emit("close");
|
|
440
368
|
}
|
|
441
369
|
}
|
|
442
370
|
async start(fn) {
|
|
443
371
|
await fn();
|
|
444
372
|
try {
|
|
445
|
-
const server = await alpListen(
|
|
373
|
+
const server = await alpListen(
|
|
374
|
+
this.config,
|
|
375
|
+
this.callback(),
|
|
376
|
+
this.certPath
|
|
377
|
+
);
|
|
446
378
|
this._server = server;
|
|
447
|
-
logger$1.success(
|
|
448
|
-
if (process.send) process.send(
|
|
379
|
+
logger$1.success("started");
|
|
380
|
+
if (process.send) process.send("ready");
|
|
449
381
|
return server;
|
|
450
382
|
} catch (error) {
|
|
451
|
-
logger$1.error(
|
|
452
|
-
err: error
|
|
453
|
-
});
|
|
383
|
+
logger$1.error("start fail", { err: error });
|
|
454
384
|
throw error;
|
|
455
385
|
}
|
|
456
386
|
}
|
|
457
387
|
}
|
|
458
388
|
|
|
389
|
+
const argv = minimist(process.argv.slice(2));
|
|
390
|
+
function _existsConfigSync(dirname, name) {
|
|
391
|
+
return existsSync(`${dirname}${name}.json`);
|
|
392
|
+
}
|
|
393
|
+
function _loadConfigSync(dirname, name) {
|
|
394
|
+
const content = readFileSync(`${dirname}${name}.json`, "utf8");
|
|
395
|
+
return JSON.parse(content);
|
|
396
|
+
}
|
|
397
|
+
class Config {
|
|
398
|
+
packageConfig;
|
|
399
|
+
_record;
|
|
400
|
+
_dirname;
|
|
401
|
+
constructor(dirname, options) {
|
|
402
|
+
this._record = {};
|
|
403
|
+
this._dirname = dirname.replace(/\/*$/, "/");
|
|
404
|
+
if (options) {
|
|
405
|
+
this.loadSync(options);
|
|
406
|
+
}
|
|
407
|
+
}
|
|
408
|
+
loadSync(options = {}) {
|
|
409
|
+
const env = process.env.CONFIG_ENV || process.env.NODE_ENV || "development";
|
|
410
|
+
const { argv: argvOverrides = [], packageConfig, version } = options;
|
|
411
|
+
this.packageConfig = packageConfig;
|
|
412
|
+
const config = _loadConfigSync(this._dirname, "common");
|
|
413
|
+
for (const [key, value] of Object.entries(
|
|
414
|
+
_loadConfigSync(this._dirname, env)
|
|
415
|
+
)) {
|
|
416
|
+
config[key] = value;
|
|
417
|
+
}
|
|
418
|
+
if (this.existsConfigSync("local")) {
|
|
419
|
+
for (const [key, value] of Object.entries(
|
|
420
|
+
_loadConfigSync(this._dirname, "local")
|
|
421
|
+
)) {
|
|
422
|
+
config[key] = value;
|
|
423
|
+
}
|
|
424
|
+
}
|
|
425
|
+
if (config.version) {
|
|
426
|
+
throw new Error('Cannot have "version", in config.');
|
|
427
|
+
}
|
|
428
|
+
config.version = String(version || argv.version || packageConfig?.version);
|
|
429
|
+
const socketPath = argv.socket || argv["socket-path"] || argv.socketPath;
|
|
430
|
+
if (socketPath) {
|
|
431
|
+
config.socketPath = socketPath;
|
|
432
|
+
} else if (argv.port) {
|
|
433
|
+
config.port = argv.port;
|
|
434
|
+
delete config.socketPath;
|
|
435
|
+
} else if (process.env.PORT) {
|
|
436
|
+
config.port = Number(process.env.PORT);
|
|
437
|
+
delete config.socketPath;
|
|
438
|
+
}
|
|
439
|
+
argvOverrides.forEach((key) => {
|
|
440
|
+
const splitted = key.split(".");
|
|
441
|
+
const value = splitted.length > 0 && // eslint-disable-next-line @typescript-eslint/no-unsafe-return,unicorn/no-array-reduce
|
|
442
|
+
splitted.reduce((config2, partialKey) => config2[partialKey], argv);
|
|
443
|
+
if (value !== void 0) {
|
|
444
|
+
const last = splitted.pop();
|
|
445
|
+
const v = splitted.length === 0 ? config : (
|
|
446
|
+
// eslint-disable-next-line unicorn/no-array-reduce
|
|
447
|
+
splitted.reduce(
|
|
448
|
+
(config2, partialKey) => config2[partialKey],
|
|
449
|
+
config
|
|
450
|
+
)
|
|
451
|
+
);
|
|
452
|
+
v[last] = value;
|
|
453
|
+
}
|
|
454
|
+
});
|
|
455
|
+
this._record = deepFreeze(config);
|
|
456
|
+
return this;
|
|
457
|
+
}
|
|
458
|
+
get(key) {
|
|
459
|
+
return this._record[key];
|
|
460
|
+
}
|
|
461
|
+
existsConfigSync(name) {
|
|
462
|
+
return _existsConfigSync(this._dirname, name);
|
|
463
|
+
}
|
|
464
|
+
loadConfigSync(name) {
|
|
465
|
+
return _loadConfigSync(this._dirname, name);
|
|
466
|
+
}
|
|
467
|
+
}
|
|
468
|
+
|
|
459
469
|
const createAlpRouterBuilder = () => createRouterBuilder();
|
|
460
470
|
function alpRouter(router) {
|
|
461
|
-
return app => {
|
|
471
|
+
return (app) => {
|
|
462
472
|
app.router = router;
|
|
463
|
-
app.context.urlGenerator = function (routeKey, params) {
|
|
473
|
+
app.context.urlGenerator = function urlGenerator(routeKey, params) {
|
|
464
474
|
return router.toLocalizedPath(this.language, routeKey, params);
|
|
465
475
|
};
|
|
466
|
-
app.context.redirectTo = function (to, params) {
|
|
467
|
-
this.redirect(
|
|
476
|
+
app.context.redirectTo = function redirectTo(to, params) {
|
|
477
|
+
this.redirect(
|
|
478
|
+
router.toLocalizedPath(this.language, to, params)
|
|
479
|
+
);
|
|
468
480
|
};
|
|
469
|
-
return async ctx => {
|
|
470
|
-
// eslint-disable-next-line unicorn/no-array-method-this-argument
|
|
481
|
+
return async (ctx) => {
|
|
471
482
|
const routeMatch = router.find(ctx.request.path, ctx.language);
|
|
472
483
|
if (!routeMatch) {
|
|
473
484
|
ctx.status = 404;
|
|
@@ -479,23 +490,20 @@ function alpRouter(router) {
|
|
|
479
490
|
};
|
|
480
491
|
}
|
|
481
492
|
|
|
482
|
-
const logger = new Logger(
|
|
483
|
-
const appDirname = path.resolve(
|
|
484
|
-
const packagePath = path.resolve(
|
|
493
|
+
const logger = new Logger("alp");
|
|
494
|
+
const appDirname = path.resolve("build");
|
|
495
|
+
const packagePath = path.resolve("package.json");
|
|
485
496
|
if (!packagePath) {
|
|
486
497
|
throw new Error(`Could not find package.json: "${String(packagePath)}"`);
|
|
487
498
|
}
|
|
488
499
|
const packageDirname = path.dirname(packagePath);
|
|
489
|
-
logger.debug(
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
const packageConfig = JSON.parse(readFileSync(packagePath, 'utf8'));
|
|
500
|
+
logger.debug("init", { appDirname, packageDirname });
|
|
501
|
+
const packageConfig = JSON.parse(
|
|
502
|
+
readFileSync(packagePath, "utf8")
|
|
503
|
+
);
|
|
494
504
|
const buildedConfigPath = `${appDirname}/build/config/`;
|
|
495
505
|
const configPath = existsSync(buildedConfigPath) ? buildedConfigPath : `${appDirname}/config/`;
|
|
496
|
-
const config = new Config(configPath).loadSync({
|
|
497
|
-
packageConfig
|
|
498
|
-
});
|
|
506
|
+
const config = new Config(configPath).loadSync({ packageConfig });
|
|
499
507
|
class App extends AlpNodeApp {
|
|
500
508
|
constructor(options) {
|
|
501
509
|
super({
|
|
@@ -508,4 +516,4 @@ class App extends AlpNodeApp {
|
|
|
508
516
|
}
|
|
509
517
|
|
|
510
518
|
export { Config, appDirname, config, createAlpRouterBuilder, App as default, packageConfig, packageDirname, alpRouter as router };
|
|
511
|
-
//# sourceMappingURL=index-
|
|
519
|
+
//# sourceMappingURL=index-node.mjs.map
|