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.
Files changed (54) hide show
  1. package/CHANGELOG.md +39 -0
  2. package/README.md +7 -7
  3. package/dist/{AlpNodeApp-node18.mjs → AlpNodeApp-node.mjs} +136 -134
  4. package/dist/AlpNodeApp-node.mjs.map +1 -0
  5. package/dist/definitions/AlpNodeApp.d.ts +16 -17
  6. package/dist/definitions/AlpNodeApp.d.ts.map +1 -1
  7. package/dist/definitions/config.d.ts +4 -5
  8. package/dist/definitions/config.d.ts.map +1 -1
  9. package/dist/definitions/errors.d.ts +1 -2
  10. package/dist/definitions/errors.d.ts.map +1 -1
  11. package/dist/definitions/index.d.ts +8 -8
  12. package/dist/definitions/language.d.ts +1 -1
  13. package/dist/definitions/language.d.ts.map +1 -1
  14. package/dist/definitions/listen.d.ts +2 -3
  15. package/dist/definitions/listen.d.ts.map +1 -1
  16. package/dist/definitions/params/ParamValid.d.ts +2 -3
  17. package/dist/definitions/params/ParamValid.d.ts.map +1 -1
  18. package/dist/definitions/params/ParamValueFromContext.d.ts +3 -4
  19. package/dist/definitions/params/ParamValueFromContext.d.ts.map +1 -1
  20. package/dist/definitions/params/ParamValueModelValidator.d.ts +1 -1
  21. package/dist/definitions/params/ParamValueStringValidator.d.ts +1 -1
  22. package/dist/definitions/params/ParamValueValidator.d.ts +1 -1
  23. package/dist/definitions/params/index.d.ts +8 -4
  24. package/dist/definitions/params/index.d.ts.map +1 -1
  25. package/dist/definitions/router.d.ts +3 -4
  26. package/dist/definitions/router.d.ts.map +1 -1
  27. package/dist/definitions/translate/index.d.ts +1 -1
  28. package/dist/definitions/translate/load.d.ts +3 -3
  29. package/dist/definitions/translate/load.d.ts.map +1 -1
  30. package/dist/definitions/types.d.ts +6 -6
  31. package/dist/definitions/types.d.ts.map +1 -1
  32. package/dist/{index-node18.mjs → index-node.mjs} +233 -225
  33. package/dist/index-node.mjs.map +1 -0
  34. package/package.json +26 -25
  35. package/src/AlpNodeApp.ts +52 -49
  36. package/src/config.ts +43 -48
  37. package/src/errors.ts +19 -19
  38. package/src/index.ts +16 -16
  39. package/src/language.ts +18 -10
  40. package/src/listen.ts +16 -16
  41. package/src/params/ParamValid.ts +3 -3
  42. package/src/params/ParamValidationResult.test.ts +14 -11
  43. package/src/params/ParamValueFromContext.ts +5 -5
  44. package/src/params/ParamValueModelValidator.ts +1 -1
  45. package/src/params/ParamValueStringValidator.ts +3 -3
  46. package/src/params/ParamValueValidator.ts +1 -1
  47. package/src/params/index.ts +17 -13
  48. package/src/router.ts +7 -7
  49. package/src/translate/index.ts +9 -9
  50. package/src/translate/load.ts +13 -12
  51. package/src/types.ts +8 -8
  52. package/dist/AlpNodeApp-node18.mjs.map +0 -1
  53. package/dist/index-node18.mjs.map +0 -1
  54. package/src/.eslintrc.json +0 -31
package/CHANGELOG.md CHANGED
@@ -3,6 +3,45 @@
3
3
  All notable changes to this project will be documented in this file.
4
4
  See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
5
5
 
6
+ ## [9.0.0](https://github.com/christophehurpeau/alp/compare/alp-node@8.0.0...alp-node@9.0.0) (2025-10-27)
7
+
8
+ ### ⚠ BREAKING CHANGES
9
+
10
+ * drop node 20 and build using esbuild
11
+
12
+ ### Features
13
+
14
+ * drop node 20 and build using esbuild ([812c4c1](https://github.com/christophehurpeau/alp/commit/812c4c1b0ad19984e389af4382a8d1e60643e4f1))
15
+ * update nightingale packages to version 16 across multiple packages ([2f59b01](https://github.com/christophehurpeau/alp/commit/2f59b01c9c407da7c59c608a12d716058fff9c70))
16
+
17
+ ### Bug Fixes
18
+
19
+ * clarify typings ([862b7e2](https://github.com/christophehurpeau/alp/commit/862b7e2ffe2dca85535c33bfd8a2d858c066fcbc))
20
+
21
+ ## [8.0.0](https://github.com/christophehurpeau/alp/compare/alp-node@7.0.0...alp-node@8.0.0) (2025-08-02)
22
+
23
+ ### ⚠ BREAKING CHANGES
24
+
25
+ * update dependencies and drop node 20
26
+ * update dev dependencies, replace parse-json-object-as-map with native JSON.parse, update koa
27
+ * remove deprecated packageDirname
28
+ * namedRouteParam and otherRouteParam
29
+ * update koa
30
+ * update router-segments
31
+
32
+ ### Features
33
+
34
+ * remove deprecated packageDirname ([82f6f16](https://github.com/christophehurpeau/alp/commit/82f6f163d40bdfe40df181a1d009072cd1eb3c82))
35
+ * update dependencies and drop node 20 ([fc5b322](https://github.com/christophehurpeau/alp/commit/fc5b322e076e9a3c7c4a235d16734b89fd85e211))
36
+ * update dev dependencies, replace parse-json-object-as-map with native JSON.parse, update koa ([5ae7723](https://github.com/christophehurpeau/alp/commit/5ae77238cafc573fe72c5eb63b103802b8b2e537))
37
+ * update koa ([e678114](https://github.com/christophehurpeau/alp/commit/e67811429d951287de715c3dffdbee7b798f3358))
38
+ * update router-segments ([07ff52b](https://github.com/christophehurpeau/alp/commit/07ff52b3f851204256509056d0a4b25e1f630e5b))
39
+
40
+ ### Bug Fixes
41
+
42
+ * namedRouteParam and otherRouteParam ([73e9e2a](https://github.com/christophehurpeau/alp/commit/73e9e2aaf00fe956628efd1380f8e44329562c41))
43
+ * properly call callback ([89cedd4](https://github.com/christophehurpeau/alp/commit/89cedd44a2edb99e9fcc050172f9ac75e1747e20))
44
+
6
45
  ## [7.0.0](https://github.com/christophehurpeau/alp/compare/alp-node@6.2.0...alp-node@7.0.0) (2024-01-06)
7
46
 
8
47
 
package/README.md CHANGED
@@ -1,16 +1,16 @@
1
- <h3 align="center">
1
+ <h1 align="center">
2
2
  alp-node
3
- </h3>
3
+ </h1>
4
4
 
5
5
  <p align="center">
6
6
  framework based on koa 2
7
7
  </p>
8
8
 
9
9
  <p align="center">
10
- <a href="https://npmjs.org/package/alp-node"><img src="https://img.shields.io/npm/v/alp-node.svg?style=flat-square"></a>
11
- <a href="https://npmjs.org/package/alp-node"><img src="https://img.shields.io/npm/dw/alp-node.svg?style=flat-square"></a>
12
- <a href="https://npmjs.org/package/alp-node"><img src="https://img.shields.io/node/v/alp-node.svg?style=flat-square"></a>
13
- <a href="https://npmjs.org/package/alp-node"><img src="https://img.shields.io/npm/types/alp-node.svg?style=flat-square"></a>
10
+ <a href="https://npmjs.org/package/alp-node"><img src="https://img.shields.io/npm/v/alp-node.svg?style=flat-square" alt="npm version"></a>
11
+ <a href="https://npmjs.org/package/alp-node"><img src="https://img.shields.io/npm/dw/alp-node.svg?style=flat-square" alt="npm downloads"></a>
12
+ <a href="https://npmjs.org/package/alp-node"><img src="https://img.shields.io/node/v/alp-node.svg?style=flat-square" alt="node version"></a>
13
+ <a href="https://npmjs.org/package/alp-node"><img src="https://img.shields.io/npm/types/alp-node.svg?style=flat-square" alt="types"></a>
14
14
  </p>
15
15
 
16
16
  ## Install
@@ -22,7 +22,7 @@ npm install --save alp-node
22
22
  ## Usage
23
23
 
24
24
  ```js
25
- import Alp from 'alp-node';
25
+ import Alp from "alp-node";
26
26
 
27
27
  const app = new Alp();
28
28
  app.servePublic();
@@ -1,26 +1,16 @@
1
1
  import path from 'node:path';
2
- import { deprecate } from 'node:util';
3
2
  import Koa from 'koa';
4
3
  import compress from 'koa-compress';
5
4
  import serve from 'koa-static';
6
5
  import { Logger } from 'nightingale-logger';
7
- import { unlinkSync, chmodSync, readFileSync } from 'node:fs';
8
- import 'deep-freeze-es6';
9
- import minimist from 'minimist';
10
- import 'parse-json-object-as-map';
11
6
  import { STATUS_CODES, createServer as createServer$2 } from 'node:http';
12
7
  import ErrorHtmlRenderer from 'error-html';
13
8
  import { defineLazyProperty } from 'object-properties';
9
+ import { unlinkSync, chmodSync, readFileSync } from 'node:fs';
14
10
  import { createServer as createServer$1 } from 'node:https';
15
11
  import IntlMessageFormatDefault from 'intl-messageformat';
16
12
 
17
- minimist(process.argv.slice(2));
18
- function getConfig(app, config) {
19
- return config;
20
- }
21
-
22
- /* eslint-disable complexity */
23
- const logger$3 = new Logger('alp:errors');
13
+ const logger$3 = new Logger("alp:errors");
24
14
  const errorHtmlRenderer = new ErrorHtmlRenderer({
25
15
  appPath: `${process.cwd()}/`
26
16
  });
@@ -28,29 +18,22 @@ async function alpNodeErrors(ctx, next) {
28
18
  try {
29
19
  await next();
30
20
  } catch (error) {
31
- // eslint-disable-next-line no-ex-assign
32
- if (!error) error = new Error('Unknown error');
33
- // eslint-disable-next-line no-ex-assign
34
- if (typeof error === 'string') error = new Error(error);
21
+ if (!error) error = new Error("Unknown error");
22
+ if (typeof error === "string") error = new Error(error);
35
23
  ctx.status = error.status || 500;
36
- // eslint-disable-next-line @typescript-eslint/no-unsafe-argument
37
24
  logger$3.error(error);
38
- switch (ctx.request.accepts('html', 'text', 'json')) {
39
- case 'json':
40
- ctx.type = 'application/json';
41
- if (process.env.NODE_ENV !== 'production' || error.expose) {
42
- ctx.body = {
43
- error: error.message
44
- };
25
+ switch (ctx.request.accepts("html", "text", "json")) {
26
+ case "json":
27
+ ctx.type = "application/json";
28
+ if (process.env.NODE_ENV !== "production" || error.expose) {
29
+ ctx.body = { error: error.message };
45
30
  } else {
46
- ctx.body = {
47
- error: STATUS_CODES[ctx.status]
48
- };
31
+ ctx.body = { error: STATUS_CODES[ctx.status] };
49
32
  }
50
33
  break;
51
- case 'html':
52
- ctx.type = 'text/html';
53
- if (process.env.NODE_ENV !== 'production') {
34
+ case "html":
35
+ ctx.type = "text/html";
36
+ if (process.env.NODE_ENV !== "production") {
54
37
  ctx.body = errorHtmlRenderer.render(error);
55
38
  } else if (error.expose) {
56
39
  ctx.body = error.message;
@@ -58,10 +41,11 @@ async function alpNodeErrors(ctx, next) {
58
41
  throw error;
59
42
  }
60
43
  break;
61
- case 'text':
44
+ case "text":
45
+ case false:
62
46
  default:
63
- ctx.type = 'text/plain';
64
- if (process.env.NODE_ENV !== 'production' || error.expose) {
47
+ ctx.type = "text/plain";
48
+ if (process.env.NODE_ENV !== "production" || error.expose) {
65
49
  ctx.body = error.message;
66
50
  } else {
67
51
  throw error;
@@ -73,22 +57,28 @@ async function alpNodeErrors(ctx, next) {
73
57
 
74
58
  function alpLanguage(app) {
75
59
  const config = app.context.config;
76
- const availableLanguages = config.get('availableLanguages');
60
+ const availableLanguages = config.get("availableLanguages");
77
61
  if (!availableLanguages) {
78
62
  throw new Error('Missing config "availableLanguages"');
79
63
  }
80
- defineLazyProperty(app.context, 'language', function () {
81
- return this.acceptsLanguages(availableLanguages) || availableLanguages[0];
82
- });
83
- defineLazyProperty(app.context, 'firstAcceptedLanguage', function () {
84
- return this.acceptsLanguages()[0] || availableLanguages[0];
85
- });
64
+ defineLazyProperty(
65
+ app.context,
66
+ "language",
67
+ function language() {
68
+ return this.acceptsLanguages(availableLanguages) || availableLanguages[0] || "en";
69
+ }
70
+ );
71
+ defineLazyProperty(
72
+ app.context,
73
+ "firstAcceptedLanguage",
74
+ function firstAcceptedLanguage() {
75
+ return this.acceptsLanguages()[0] || availableLanguages[0] || "en";
76
+ }
77
+ );
86
78
  }
87
79
 
88
- const logger$2 = new Logger('alp:listen');
89
- const createServer = (callback, socketPath, tls, dirname = ''
90
- // eslint-disable-next-line @typescript-eslint/max-params
91
- ) => {
80
+ const logger$2 = new Logger("alp:listen");
81
+ const createServer = (callback, socketPath, tls, dirname = "") => {
92
82
  const createHttpServer = !socketPath && tls ? createServer$1 : createServer$2;
93
83
  if (!tls) {
94
84
  return createHttpServer(callback);
@@ -100,35 +90,28 @@ const createServer = (callback, socketPath, tls, dirname = ''
100
90
  return createHttpServer(options, callback);
101
91
  };
102
92
  function alpListen(config, callback, dirname) {
103
- return new Promise(resolve => {
104
- const socketPath = config.get('socketPath');
105
- const port = config.get('port');
106
- const hostname = config.get('hostname');
107
- const tls = config.get('tls');
108
- logger$2.info('Creating server', socketPath ? {
109
- socketPath
110
- } : {
111
- port
112
- });
93
+ return new Promise((resolve) => {
94
+ const socketPath = config.get("socketPath");
95
+ const port = config.get("port");
96
+ const hostname = config.get("hostname");
97
+ const tls = config.get("tls");
98
+ logger$2.info("Creating server", socketPath ? { socketPath } : { port });
113
99
  const server = createServer(callback, socketPath, tls, dirname);
114
100
  if (socketPath) {
115
101
  try {
116
102
  unlinkSync(socketPath);
117
- } catch {}
103
+ } catch {
104
+ }
118
105
  server.listen(socketPath, () => {
119
106
  if (socketPath) {
120
- chmodSync(socketPath, '777');
107
+ chmodSync(socketPath, "777");
121
108
  }
122
- logger$2.info('Server listening', {
123
- socketPath
124
- });
109
+ logger$2.info("Server listening", { socketPath });
125
110
  resolve(server);
126
111
  });
127
112
  } else {
128
113
  server.listen(port, hostname, () => {
129
- logger$2.info('Server listening', {
130
- port
131
- });
114
+ logger$2.info("Server listening", { port });
132
115
  resolve(server);
133
116
  });
134
117
  }
@@ -136,25 +119,22 @@ function alpListen(config, callback, dirname) {
136
119
  }
137
120
 
138
121
  class ParamValidationResult {
122
+ _errors;
139
123
  _error(name, key, value) {
140
124
  if (!this._errors) {
141
125
  this._errors = {};
142
126
  }
143
- this._errors[name] = {
144
- error: key,
145
- value
146
- };
127
+ this._errors[name] = { error: key, value };
147
128
  }
148
129
  getErrors() {
149
130
  return this._errors;
150
131
  }
151
132
  hasErrors() {
152
- return this._errors !== undefined;
133
+ return this._errors !== void 0;
153
134
  }
154
135
  isValid() {
155
- return this._errors === undefined;
136
+ return this._errors === void 0;
156
137
  }
157
-
158
138
  // string(name: string): ParamValueStringValidator {
159
139
  // return new ParamValueStringValidator(this, name, this.context.param(name));
160
140
  // }
@@ -170,18 +150,20 @@ class ParamValidationResult {
170
150
  }
171
151
 
172
152
  class ParamValid extends ParamValidationResult {
153
+ context;
173
154
  constructor(context) {
174
155
  super();
175
156
  this.context = context;
176
157
  }
177
158
  _error() {
178
- this.context.throw(400, 'Invalid params', {
179
- validator: this
180
- });
159
+ this.context.throw(400, "Invalid params", { validator: this });
181
160
  }
182
161
  }
183
162
 
184
163
  class ParamValueValidator {
164
+ validationResult;
165
+ name;
166
+ value;
185
167
  constructor(validationResult, name, value) {
186
168
  this.validationResult = validationResult;
187
169
  this.name = name;
@@ -197,30 +179,42 @@ class ParamValueValidator {
197
179
 
198
180
  class ParamValueStringValidator extends ParamValueValidator {
199
181
  notEmpty() {
200
- if (this.value == null || this.value.trim() === '') {
201
- this._error('notEmpty');
182
+ if (this.value == null || this.value.trim() === "") {
183
+ this._error("notEmpty");
202
184
  }
203
185
  return this;
204
186
  }
205
187
  }
206
188
 
207
189
  class ParamValueFromContext {
190
+ validationResult;
191
+ context;
208
192
  constructor(context, validationResult) {
209
193
  this.validationResult = validationResult;
210
194
  this.context = context;
211
195
  }
212
196
  namedParam(name) {
213
- return new ParamValueStringValidator(this.validationResult, name, this.context.namedParam(name));
197
+ return new ParamValueStringValidator(
198
+ this.validationResult,
199
+ name,
200
+ this.context.namedRouteParam(name)
201
+ );
214
202
  }
215
203
  otherParam(position) {
216
- return new ParamValueStringValidator(this.validationResult, String(position), this.context.otherParam(position));
204
+ return new ParamValueStringValidator(
205
+ this.validationResult,
206
+ String(position),
207
+ this.context.otherRouteParam(position)
208
+ );
217
209
  }
218
210
  queryParam(name) {
219
- return new ParamValueStringValidator(this.validationResult, name, this.context.queryParam(name));
211
+ return new ParamValueStringValidator(
212
+ this.validationResult,
213
+ name,
214
+ this.context.queryParam(name)
215
+ );
220
216
  }
221
-
222
217
  // bodyParam: <T>(name: string): ParamValueValidator<string | undefined> {
223
-
224
218
  // }
225
219
  }
226
220
 
@@ -236,65 +230,73 @@ function alpParams(app) {
236
230
  },
237
231
  queryParam(name) {
238
232
  const searchParams = this.request.searchParams;
239
- return searchParams.get(name) ?? undefined;
233
+ return searchParams.get(name) ?? void 0;
240
234
  },
241
235
  bodyParam(name) {
242
- // eslint-disable-next-line @typescript-eslint/no-unsafe-return, @typescript-eslint/no-unsafe-member-access
243
236
  return this.body[name];
244
237
  }
245
238
  });
246
- defineLazyProperty(app.request, 'searchParams', function () {
247
- return new URLSearchParams(this.search);
248
- });
249
- defineLazyProperty(app.context, 'params', function () {
250
- return new ParamValueFromContext(this, new ParamValidationResult());
251
- });
252
- defineLazyProperty(app.context, 'validParams', function () {
253
- return new ParamValueFromContext(this, new ParamValid(this));
254
- });
239
+ defineLazyProperty(
240
+ app.request,
241
+ "searchParams",
242
+ function searchParams() {
243
+ return new URLSearchParams(this.search);
244
+ }
245
+ );
246
+ defineLazyProperty(
247
+ app.context,
248
+ "params",
249
+ function params() {
250
+ return new ParamValueFromContext(this, new ParamValidationResult());
251
+ }
252
+ );
253
+ defineLazyProperty(
254
+ app.context,
255
+ "validParams",
256
+ function validParams() {
257
+ return new ParamValueFromContext(this, new ParamValid(this));
258
+ }
259
+ );
255
260
  }
256
261
 
257
- // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
258
- const IntlMessageFormat =
259
- // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
260
- IntlMessageFormatDefault.default || IntlMessageFormatDefault;
262
+ const IntlMessageFormat = (
263
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
264
+ IntlMessageFormatDefault.default || IntlMessageFormatDefault
265
+ );
261
266
  function load(translations, language) {
262
- const result = new Map();
263
- (function loadMap(map, prefix) {
264
- map.forEach((value, key) => {
265
- if (typeof value === 'object') {
266
- // eslint-disable-next-line @typescript-eslint/no-unsafe-argument
267
+ const result = {};
268
+ (function loadMap(record, prefix) {
269
+ Object.entries(record).forEach(([key, value]) => {
270
+ if (typeof value === "object" && value !== null) {
267
271
  loadMap(value, `${prefix}${key}.`);
268
272
  return;
269
273
  }
270
-
271
- // eslint-disable-next-line @typescript-eslint/no-unsafe-argument
272
- result.set(`${prefix}${key}`, new IntlMessageFormat(value, language));
274
+ result[`${prefix}${key}`] = new IntlMessageFormat(
275
+ value,
276
+ language
277
+ );
273
278
  });
274
- })(translations, '');
279
+ })(translations, "");
275
280
  return result;
276
281
  }
277
282
 
278
- const logger$1 = new Logger('alp:translate');
283
+ const logger$1 = new Logger("alp:translate");
279
284
  function alpTranslate(dirname) {
280
- dirname = dirname.replace(/\/*$/, '/');
281
- return app => {
282
- const appTranslations = new Map();
285
+ dirname = dirname.replace(/\/*$/, "/");
286
+ return (app) => {
287
+ const appTranslations = /* @__PURE__ */ new Map();
283
288
  Object.assign(app.context, {
284
289
  t(id, args) {
285
- const msg = appTranslations.get(this.language).get(id);
290
+ const msg = appTranslations.get(this.language)?.[id];
286
291
  if (!msg) {
287
- logger$1.warn('invalid msg', {
288
- language: this.language,
289
- id
290
- });
292
+ logger$1.warn("invalid msg", { language: this.language, id });
291
293
  return id;
292
294
  }
293
295
  return msg.format(args);
294
296
  }
295
297
  });
296
298
  const config = app.config;
297
- config.get('availableLanguages').forEach(language => {
299
+ config.get("availableLanguages").forEach((language) => {
298
300
  const translations = app.loadConfigSync(dirname + language);
299
301
  appTranslations.set(language, load(translations, language));
300
302
  });
@@ -302,8 +304,14 @@ function alpTranslate(dirname) {
302
304
  };
303
305
  }
304
306
 
305
- const logger = new Logger('alp');
307
+ const logger = new Logger("alp");
306
308
  class AlpNodeApp extends Koa {
309
+ dirname;
310
+ certPath;
311
+ publicPath;
312
+ config;
313
+ _server;
314
+ router;
307
315
  /**
308
316
  * @param {Object} [options]
309
317
  * @param {string} [options.certPath] directory of the ssl certificates
@@ -318,18 +326,13 @@ class AlpNodeApp extends Koa {
318
326
  }) {
319
327
  super();
320
328
  this.dirname = path.normalize(appDirname);
321
- Object.defineProperty(this, 'packageDirname', {
322
- get: deprecate(() => packageDirname, 'packageDirname'),
323
- configurable: false,
324
- enumerable: false
325
- });
326
329
  this.certPath = certPath || `${packageDirname}/config/cert`;
327
330
  this.publicPath = publicPath || `${packageDirname}/public/`;
328
- this.config = getConfig(this, config);
331
+ this.config = config;
329
332
  this.context.config = this.config;
330
333
  alpParams(this);
331
334
  alpLanguage(this);
332
- alpTranslate('locales')(this);
335
+ alpTranslate("locales")(this);
333
336
  this.use(compress());
334
337
  }
335
338
  existsConfigSync(name) {
@@ -344,42 +347,41 @@ class AlpNodeApp extends Koa {
344
347
  return ctx;
345
348
  }
346
349
  servePublic() {
347
- this.use(serve(this.publicPath)); // static files
350
+ this.use(serve(this.publicPath));
348
351
  }
349
352
  catchErrors() {
350
353
  this.use(alpNodeErrors);
351
354
  }
352
-
353
- // eslint-disable-next-line @typescript-eslint/class-methods-use-this
354
355
  listen() {
355
- throw new Error('Use start instead');
356
+ throw new Error("Use start instead");
356
357
  }
357
-
358
358
  /**
359
359
  * Close server and emit close event
360
360
  */
361
361
  close() {
362
362
  if (this._server) {
363
363
  this._server.close();
364
- this.emit('close');
364
+ this.emit("close");
365
365
  }
366
366
  }
367
367
  async start(fn) {
368
368
  await fn();
369
369
  try {
370
- const server = await alpListen(this.config, this.callback(), this.certPath);
370
+ const server = await alpListen(
371
+ this.config,
372
+ this.callback(),
373
+ this.certPath
374
+ );
371
375
  this._server = server;
372
- logger.success('started');
373
- if (process.send) process.send('ready');
376
+ logger.success("started");
377
+ if (process.send) process.send("ready");
374
378
  return server;
375
379
  } catch (error) {
376
- logger.error('start fail', {
377
- err: error
378
- });
380
+ logger.error("start fail", { err: error });
379
381
  throw error;
380
382
  }
381
383
  }
382
384
  }
383
385
 
384
386
  export { AlpNodeApp };
385
- //# sourceMappingURL=AlpNodeApp-node18.mjs.map
387
+ //# sourceMappingURL=AlpNodeApp-node.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"AlpNodeApp-node.mjs","sources":["../src/errors.ts","../src/language.ts","../src/listen.ts","../src/params/ParamValidationResult.ts","../src/params/ParamValid.ts","../src/params/ParamValueValidator.ts","../src/params/ParamValueStringValidator.ts","../src/params/ParamValueFromContext.ts","../src/params/index.ts","../src/translate/load.ts","../src/translate/index.ts","../src/AlpNodeApp.ts"],"sourcesContent":["import { STATUS_CODES } from \"node:http\";\nimport ErrorHtmlRenderer from \"error-html\";\nimport { Logger } from \"nightingale-logger\";\nimport type { Context } from \"./AlpNodeApp\";\nimport type { HtmlError } from \"./types\";\n\nconst logger = new Logger(\"alp:errors\");\nconst errorHtmlRenderer = new ErrorHtmlRenderer({\n appPath: `${process.cwd()}/`,\n});\n\nexport default async function alpNodeErrors(\n ctx: Context,\n next: () => Promise<void> | void,\n): Promise<void> {\n try {\n await next();\n } catch (error: unknown) {\n // eslint-disable-next-line no-ex-assign\n if (!error) error = new Error(\"Unknown error\");\n // eslint-disable-next-line no-ex-assign\n if (typeof error === \"string\") error = new Error(error);\n\n ctx.status = (error as HtmlError).status || 500;\n // eslint-disable-next-line @typescript-eslint/no-unsafe-argument\n logger.error(error as any);\n\n switch (ctx.request.accepts(\"html\", \"text\", \"json\")) {\n case \"json\":\n ctx.type = \"application/json\";\n if (\n process.env.NODE_ENV !== \"production\" ||\n (error as HtmlError).expose\n ) {\n ctx.body = { error: (error as Error).message };\n } else {\n ctx.body = { error: STATUS_CODES[ctx.status] };\n }\n\n break;\n\n case \"html\":\n ctx.type = \"text/html\";\n if (process.env.NODE_ENV !== \"production\") {\n ctx.body = errorHtmlRenderer.render(error as Error);\n } else if ((error as HtmlError).expose) {\n ctx.body = (error as Error).message;\n } else {\n throw error;\n }\n\n break;\n\n case \"text\":\n case false:\n default:\n ctx.type = \"text/plain\";\n if (\n process.env.NODE_ENV !== \"production\" ||\n (error as HtmlError).expose\n ) {\n ctx.body = (error as Error).message;\n } else {\n throw error;\n }\n\n break;\n }\n }\n}\n","import type { Context } from \"koa\";\nimport { defineLazyProperty } from \"object-properties\";\nimport type { AlpNodeApp } from \"./AlpNodeApp\";\n\nexport interface AlpLanguageContext {\n readonly firstAcceptedLanguage: string;\n readonly language: string;\n}\nexport default function alpLanguage(app: AlpNodeApp): void {\n const config = app.context.config;\n const availableLanguages: string[] = config.get(\"availableLanguages\");\n if (!availableLanguages) {\n throw new Error('Missing config \"availableLanguages\"');\n }\n\n defineLazyProperty(\n app.context,\n \"language\",\n function language(this: Context): string {\n return (\n this.acceptsLanguages(availableLanguages) ||\n availableLanguages[0] ||\n \"en\"\n );\n },\n );\n\n defineLazyProperty(\n app.context,\n \"firstAcceptedLanguage\",\n function firstAcceptedLanguage(this: Context): string {\n return this.acceptsLanguages()[0] || availableLanguages[0] || \"en\";\n },\n );\n}\n","import { chmodSync, readFileSync, unlinkSync } from \"node:fs\";\nimport { createServer as createServerHttp } from \"node:http\";\nimport type { IncomingMessage, Server, ServerResponse } from \"node:http\";\nimport { createServer as createServerHttps } from \"node:https\";\nimport { Logger } from \"nightingale-logger\";\nimport type { Config } from \"./config\";\n\nconst logger = new Logger(\"alp:listen\");\n\ntype RequestListener = (req: IncomingMessage, res: ServerResponse) => void;\n\nconst createServer = (\n callback: RequestListener,\n socketPath?: string,\n tls?: boolean,\n dirname = \"\",\n // eslint-disable-next-line @typescript-eslint/max-params\n): Server => {\n const createHttpServer =\n !socketPath && tls ? createServerHttps : createServerHttp;\n\n if (!tls) {\n return (createHttpServer as typeof createServerHttps)(callback);\n }\n\n const options = {\n key: readFileSync(`${dirname}/server.key`),\n cert: readFileSync(`${dirname}/server.crt`),\n };\n\n return (createHttpServer as typeof createServerHttps)(options, callback);\n};\n\nexport default function alpListen(\n config: Config,\n callback: RequestListener,\n dirname?: string,\n): Promise<Server> {\n return new Promise((resolve) => {\n const socketPath = config.get<string>(\"socketPath\");\n const port = config.get<number>(\"port\");\n const hostname = config.get<string>(\"hostname\");\n const tls = config.get<boolean>(\"tls\");\n\n logger.info(\"Creating server\", socketPath ? { socketPath } : { port });\n const server = createServer(callback, socketPath, tls, dirname);\n\n if (socketPath) {\n try {\n unlinkSync(socketPath);\n } catch {}\n\n server.listen(socketPath, () => {\n if (socketPath) {\n chmodSync(socketPath, \"777\");\n }\n\n logger.info(\"Server listening\", { socketPath });\n resolve(server);\n });\n } else {\n server.listen(port, hostname, () => {\n logger.info(\"Server listening\", { port });\n resolve(server);\n });\n }\n });\n}\n","export type Errors = Record<string, any>;\n\nexport class ParamValidationResult {\n _errors?: Errors;\n\n _error(name: string, key: string, value: unknown): void {\n if (!this._errors) {\n this._errors = {};\n }\n\n this._errors[name] = { error: key, value };\n }\n\n getErrors(): Errors | undefined {\n return this._errors;\n }\n\n hasErrors(): boolean {\n return this._errors !== undefined;\n }\n\n isValid(): boolean {\n return this._errors === undefined;\n }\n\n // string(name: string): ParamValueStringValidator {\n // return new ParamValueStringValidator(this, name, this.context.param(name));\n // }\n /* int(name, position) {\n return new ParamValueIntValidator(this, name, this.context.param(name, position));\n }\n model(modelName, name) {\n name = name || S.string.lcFirst(modelName);\n console.log('paramvalidator model', modelName, M[modelName]);\n let data = this.context.getOrPostParam(name);\n return new ParamValueModelValidator(this, name, !data ? null : new M[modelName](data));\n } */\n}\n","import type { Context } from \"../AlpNodeApp\";\nimport { ParamValidationResult } from \"./ParamValidationResult\";\n\nexport default class ParamValid extends ParamValidationResult {\n context: Context;\n\n constructor(context: Context) {\n super();\n this.context = context;\n }\n\n override _error(): void {\n this.context.throw(400, \"Invalid params\", { validator: this });\n }\n}\n","import type { ParamValidationResult } from \"./ParamValidationResult\";\n\nexport default class ParamValueValidator<T> {\n readonly validationResult: ParamValidationResult;\n\n readonly name: string;\n\n readonly value: T;\n\n constructor(validationResult: ParamValidationResult, name: string, value: T) {\n this.validationResult = validationResult;\n this.name = name;\n this.value = value;\n }\n\n isValid(): boolean {\n return this.validationResult.isValid();\n }\n\n _error(key: string): void {\n this.validationResult._error(this.name, key, this.value);\n }\n}\n","import ParamValueValidator from \"./ParamValueValidator\";\n\nexport default class ParamValueStringValidator<\n T extends string = string,\n> extends ParamValueValidator<T | null | undefined> {\n notEmpty(): ParamValueValidator<T> {\n if (this.value == null || this.value.trim() === \"\") {\n this._error(\"notEmpty\");\n }\n\n return this as ParamValueValidator<T>;\n }\n}\n","import type { Context } from \"../AlpNodeApp\";\nimport type { ParamValidationResult } from \"./ParamValidationResult\";\nimport ParamValueStringValidator from \"./ParamValueStringValidator\";\n\nexport class ParamValueFromContext {\n readonly validationResult: ParamValidationResult;\n\n readonly context: Context;\n\n constructor(context: Context, validationResult: ParamValidationResult) {\n this.validationResult = validationResult;\n this.context = context;\n }\n\n namedParam(name: string): ParamValueStringValidator {\n return new ParamValueStringValidator(\n this.validationResult,\n name,\n this.context.namedRouteParam(name),\n );\n }\n\n otherParam(position: number): ParamValueStringValidator {\n return new ParamValueStringValidator(\n this.validationResult,\n String(position),\n this.context.otherRouteParam(position),\n );\n }\n\n queryParam(name: string): ParamValueStringValidator {\n return new ParamValueStringValidator(\n this.validationResult,\n name,\n this.context.queryParam(name),\n );\n }\n\n // bodyParam: <T>(name: string): ParamValueValidator<string | undefined> {\n\n // }\n}\n","import { defineLazyProperty } from \"object-properties\";\nimport type { AlpNodeApp, Context } from \"../AlpNodeApp\";\nimport ParamValid from \"./ParamValid\";\nimport { ParamValidationResult } from \"./ParamValidationResult\";\nimport { ParamValueFromContext } from \"./ParamValueFromContext\";\n\nexport interface AlpParamsContext {\n params: ParamValueFromContext;\n validParams: ParamValueFromContext;\n namedRouteParam: (name: string) => string | undefined;\n otherRouteParam: (position: number) => string | undefined;\n /** @deprecated use namedRouteParam */\n namedParam: never;\n /** @deprecated use otherRouteParam */\n otherParam: never;\n queryParam: (name: string) => string | undefined;\n bodyParam: <T>(name: string) => T | undefined;\n}\n\nexport interface AlpParamsRequest {\n searchParams: URLSearchParams;\n}\n\nexport default function alpParams(app: AlpNodeApp): void {\n Object.assign(app.context, {\n namedRouteParam(this: Context, name: string): string | undefined {\n const namedParams = this.route.namedParams;\n return namedParams?.get(name);\n },\n\n otherRouteParam(this: Context, position: number): string | undefined {\n const otherParams = this.route.otherParams;\n return otherParams?.[position - 1];\n },\n\n queryParam(this: Context, name: string): string | undefined {\n const searchParams = this.request.searchParams;\n return searchParams.get(name) ?? undefined;\n },\n\n bodyParam<T>(this: Context, name: string): T | undefined {\n // eslint-disable-next-line @typescript-eslint/no-unsafe-return, @typescript-eslint/no-unsafe-member-access\n return (this.body as any)[name];\n },\n });\n\n defineLazyProperty(\n app.request,\n \"searchParams\",\n function searchParams(this: Context[\"request\"]): URLSearchParams {\n return new URLSearchParams(this.search);\n },\n );\n\n defineLazyProperty(\n app.context,\n \"params\",\n function params(this: Context): ParamValueFromContext {\n return new ParamValueFromContext(this, new ParamValidationResult());\n },\n );\n\n defineLazyProperty(\n app.context,\n \"validParams\",\n function validParams(this: Context): ParamValueFromContext {\n return new ParamValueFromContext(this, new ParamValid(this));\n },\n );\n}\n","import IntlMessageFormatDefault from \"intl-messageformat\";\n\n// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment\nconst IntlMessageFormat: typeof IntlMessageFormatDefault =\n // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access\n (IntlMessageFormatDefault as any).default || IntlMessageFormatDefault;\n\nexport type Translations = Readonly<Record<string, IntlMessageFormatDefault>>;\n\nexport default function load(\n translations: Readonly<Record<string, unknown>>,\n language: string,\n): Translations {\n const result: Record<string, IntlMessageFormatDefault> = {};\n\n (function loadMap(record: Record<string, unknown>, prefix: string) {\n Object.entries(record).forEach(([key, value]) => {\n if (typeof value === \"object\" && value !== null) {\n loadMap(value as Record<string, unknown>, `${prefix}${key}.`);\n return;\n }\n\n result[`${prefix}${key}`] = new IntlMessageFormat(\n value as string,\n language,\n );\n });\n })(translations, \"\");\n\n return result;\n}\n","import { Logger } from \"nightingale-logger\";\nimport type { AlpNodeApp, Context } from \"../AlpNodeApp\";\nimport type { Translations } from \"./load\";\nimport load from \"./load\";\n\nconst logger = new Logger(\"alp:translate\");\n\ntype Args = Record<string, any>;\n\nexport interface TranslateBaseContext {\n t: (id: string, args: Args) => string;\n}\nexport interface TranslateContext {\n readonly language: string;\n}\n\nexport default function alpTranslate(\n dirname: string,\n): (app: AlpNodeApp) => void {\n dirname = dirname.replace(/\\/*$/, \"/\");\n return (app: AlpNodeApp) => {\n const appTranslations = new Map<string, Translations>();\n\n Object.assign(app.context, {\n t(this: Context, id: string, args: Args): string {\n const msg = appTranslations.get(this.language)?.[id];\n if (!msg) {\n logger.warn(\"invalid msg\", { language: this.language, id });\n return id;\n }\n\n return msg.format(args) as string;\n },\n });\n\n const config = app.config;\n\n config.get<string[]>(\"availableLanguages\").forEach((language) => {\n const translations = app.loadConfigSync(dirname + language);\n appTranslations.set(language, load(translations, language));\n });\n\n return appTranslations;\n };\n}\n","import type {\n IncomingMessage,\n RequestListener,\n Server,\n ServerResponse,\n} from \"node:http\";\nimport path from \"node:path\";\nimport Koa from \"koa\";\nimport type { DefaultContext, DefaultState, ParameterizedContext } from \"koa\";\nimport compress from \"koa-compress\";\nimport serve from \"koa-static\";\nimport { Logger } from \"nightingale-logger\";\nimport type { Router } from \"router-segments\";\nimport type { Config } from \"./config\";\nimport errors from \"./errors\";\nimport type { AlpLanguageContext } from \"./language\";\nimport language from \"./language\";\nimport _listen from \"./listen\";\nimport type { AlpParamsContext, AlpParamsRequest } from \"./params/index\";\nimport params from \"./params/index\";\nimport type {\n AlpRouteRef,\n RouterContext as AlpRouterContext,\n UrlGenerator,\n} from \"./router\";\nimport type { TranslateBaseContext, TranslateContext } from \"./translate/index\";\nimport translate from \"./translate/index\";\nimport type {\n Context as AlpContext,\n ContextSanitizedState,\n ContextState,\n NodeApplication,\n NodeConfig,\n} from \"./types\";\n\nconst logger = new Logger(\"alp\");\n\nexport interface AlpNodeAppOptions {\n appDirname: string;\n packageDirname: string;\n config: Config & NodeConfig;\n certPath?: string;\n publicPath?: string;\n}\n\ndeclare module \"koa\" {\n // eslint-disable-next-line @typescript-eslint/no-empty-object-type\n interface DefaultState extends ContextState {}\n\n interface DefaultContext\n extends AlpContext,\n AlpParamsContext,\n AlpRouterContext,\n AlpLanguageContext,\n TranslateContext {}\n\n interface BaseContext extends AlpContext, TranslateBaseContext {\n urlGenerator: UrlGenerator;\n redirectTo: <P extends Record<string, unknown>>(\n to: string,\n params?: P,\n ) => void;\n }\n // eslint-disable-next-line @typescript-eslint/no-empty-object-type\n interface BaseRequest extends AlpParamsRequest {}\n}\n\nexport class AlpNodeApp\n extends Koa<DefaultState, DefaultContext>\n implements NodeApplication\n{\n dirname: string;\n\n certPath: string;\n\n publicPath: string;\n\n config: Config & NodeConfig;\n\n _server?: Server;\n\n router?: Router<any, AlpRouteRef>;\n\n /**\n * @param {Object} [options]\n * @param {string} [options.certPath] directory of the ssl certificates\n * @param {string} [options.publicPath] directory of public files\n */\n constructor({\n appDirname,\n packageDirname,\n config,\n certPath,\n publicPath,\n }: AlpNodeAppOptions) {\n super();\n\n this.dirname = path.normalize(appDirname);\n this.certPath = certPath || `${packageDirname}/config/cert`;\n this.publicPath = publicPath || `${packageDirname}/public/`;\n\n this.config = config;\n this.context.config = this.config;\n\n params(this);\n language(this);\n translate(\"locales\")(this);\n\n this.use(compress());\n }\n\n existsConfigSync(name: string): ReturnType<Config[\"existsConfigSync\"]> {\n return this.config.existsConfigSync(name);\n }\n\n loadConfigSync(name: string): ReturnType<Config[\"loadConfigSync\"]> {\n return this.config.loadConfigSync(name);\n }\n\n override createContext<StateT = DefaultState>(\n req: IncomingMessage,\n res: ServerResponse,\n ): ParameterizedContext<StateT> {\n const ctx = super.createContext<StateT>(req, res);\n // eslint-disable-next-line @typescript-eslint/consistent-type-assertions\n ctx.sanitizedState = {} as ContextSanitizedState;\n return ctx;\n }\n\n servePublic(): void {\n this.use(serve(this.publicPath)); // static files\n }\n\n catchErrors(): void {\n this.use(errors);\n }\n\n override listen(): never {\n throw new Error(\"Use start instead\");\n }\n\n /**\n * Close server and emit close event\n */\n close(): void {\n if (this._server) {\n this._server.close();\n this.emit(\"close\");\n }\n }\n\n async start(fn: () => Promise<void> | void): Promise<Server> {\n await fn();\n try {\n const server = await _listen(\n this.config,\n this.callback() as RequestListener,\n this.certPath,\n );\n this._server = server;\n logger.success(\"started\");\n if (process.send) process.send(\"ready\");\n return server;\n } catch (error: unknown) {\n logger.error(\"start fail\", { err: error });\n throw error;\n }\n }\n}\n\nexport type { Context } from \"koa\";\n\nexport { type NodeApplication } from \"./types\";\n"],"names":["logger","createServerHttps","createServerHttp","params","language","translate","errors","_listen"],"mappings":"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"}