alp-node 7.0.0 → 8.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 +24 -0
  2. package/README.md +7 -7
  3. package/dist/{AlpNodeApp-node18.mjs → AlpNodeApp-node20.mjs} +59 -77
  4. package/dist/AlpNodeApp-node20.mjs.map +1 -0
  5. package/dist/definitions/AlpNodeApp.d.ts +15 -16
  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-node20.mjs} +142 -158
  33. package/dist/index-node20.mjs.map +1 -0
  34. package/package.json +23 -23
  35. package/src/AlpNodeApp.ts +48 -48
  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 +5 -5
  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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "alp-node",
3
- "version": "7.0.0",
3
+ "version": "8.0.0",
4
4
  "description": "framework based on koa 2",
5
5
  "keywords": [
6
6
  "springbokjs",
@@ -22,10 +22,10 @@
22
22
  },
23
23
  "type": "module",
24
24
  "engines": {
25
- "node": ">=18.12.0"
25
+ "node": ">=20.11.0"
26
26
  },
27
27
  "sideEffects": false,
28
- "main": "./dist/index-node18.mjs",
28
+ "main": "./dist/index-node20.mjs",
29
29
  "types": "./dist/definitions/index.d.ts",
30
30
  "typesVersions": {
31
31
  ">=3.1": {
@@ -39,13 +39,13 @@
39
39
  ".": {
40
40
  "types": "./dist/definitions/index.d.ts",
41
41
  "node": {
42
- "import": "./dist/index-node18.mjs"
42
+ "import": "./dist/index-node20.mjs"
43
43
  }
44
44
  },
45
45
  "./AlpNodeApp": {
46
46
  "types": "./dist/definitions/AlpNodeApp.d.ts",
47
47
  "node": {
48
- "import": "./dist/AlpNodeApp-node18.mjs"
48
+ "import": "./dist/AlpNodeApp-node20.mjs"
49
49
  }
50
50
  }
51
51
  },
@@ -59,45 +59,45 @@
59
59
  "clean": "yarn clean:build",
60
60
  "clean:build": "pob-babel-clean-out dist",
61
61
  "lint": "yarn run lint:eslint",
62
- "lint:eslint": "yarn ../.. run eslint --report-unused-disable-directives --resolve-plugins-relative-to . --quiet packages/alp-node",
62
+ "lint:eslint": "yarn ../.. run eslint --quiet packages/alp-node",
63
63
  "watch": "yarn clean:build && rollup --config rollup.config.mjs --watch"
64
64
  },
65
65
  "pob": {
66
- "babelEnvs": [
67
- {
68
- "target": "node",
69
- "version": "18"
70
- }
71
- ],
66
+ "bundler": "rollup-babel",
72
67
  "entries": [
73
68
  "index",
74
69
  "AlpNodeApp"
70
+ ],
71
+ "envs": [
72
+ {
73
+ "target": "node",
74
+ "version": "20"
75
+ }
75
76
  ]
76
77
  },
77
78
  "prettier": "@pob/root/prettier-config",
78
79
  "peerDependencies": {
79
- "router-segments": "^9.1.0"
80
+ "router-segments": "^11.0.0"
80
81
  },
81
82
  "dependencies": {
82
- "@types/koa": "^2.13.1",
83
- "@types/node": ">=18.0.0",
84
- "deep-freeze-es6": "^3.0.2",
83
+ "@types/koa": "^3.0.0",
84
+ "@types/node": ">=20.0.0",
85
+ "deep-freeze-es6": "^4.0.1",
85
86
  "error-html": "^0.3.5",
86
87
  "intl-messageformat": "^10.0.0",
87
- "koa": "^2.13.1",
88
- "koa-compress": "^5.0.0",
88
+ "koa": "^3.0.1",
89
+ "koa-compress": "^5.1.1",
89
90
  "koa-static": "^5.0.0",
90
91
  "minimist": "^1.2.8",
91
92
  "nightingale-logger": "^15.0.0",
92
- "object-properties": "^8.1.0",
93
- "parse-json-object-as-map": "^1.2.0"
93
+ "object-properties": "^9.0.1"
94
94
  },
95
95
  "devDependencies": {
96
- "@babel/core": "7.23.7",
96
+ "@babel/core": "7.28.0",
97
97
  "@types/koa-compress": "4.0.6",
98
98
  "@types/koa-static": "4.0.4",
99
99
  "@types/minimist": "1.2.5",
100
- "pob-babel": "38.0.2",
101
- "typescript": "5.3.3"
100
+ "pob-babel": "43.7.0",
101
+ "typescript": "5.8.3"
102
102
  }
103
103
  }
package/src/AlpNodeApp.ts CHANGED
@@ -1,36 +1,39 @@
1
- import type { IncomingMessage, Server, ServerResponse } from 'node:http';
2
- import path from 'node:path';
3
- import { deprecate } from 'node:util';
4
- import Koa from 'koa';
5
- import type { ParameterizedContext, DefaultState } from 'koa';
6
- import compress from 'koa-compress';
7
- import serve from 'koa-static';
8
- import { Logger } from 'nightingale-logger';
9
- import type { Router } from 'router-segments';
10
- import type { Config } from './config';
11
- import _config from './config';
12
- import errors from './errors';
13
- import type { AlpLanguageContext } from './language';
14
- import language from './language';
15
- import _listen from './listen';
16
- import type { AlpParamsContext, AlpParamsRequest } from './params';
17
- import params from './params';
1
+ import type {
2
+ IncomingMessage,
3
+ RequestListener,
4
+ Server,
5
+ ServerResponse,
6
+ } from "node:http";
7
+ import path from "node:path";
8
+ import Koa from "koa";
9
+ import type { DefaultState, ParameterizedContext } from "koa";
10
+ import compress from "koa-compress";
11
+ import serve from "koa-static";
12
+ import { Logger } from "nightingale-logger";
13
+ import type { Router } from "router-segments";
14
+ import type { Config } from "./config";
15
+ import errors from "./errors";
16
+ import type { AlpLanguageContext } from "./language";
17
+ import language from "./language";
18
+ import _listen from "./listen";
19
+ import type { AlpParamsContext, AlpParamsRequest } from "./params/index";
20
+ import params from "./params/index";
18
21
  import type {
19
22
  AlpRouteRef,
20
23
  RouterContext as AlpRouterContext,
21
24
  UrlGenerator,
22
- } from './router';
23
- import type { TranslateBaseContext, TranslateContext } from './translate';
24
- import translate from './translate';
25
+ } from "./router";
26
+ import type { TranslateBaseContext, TranslateContext } from "./translate/index";
27
+ import translate from "./translate/index";
25
28
  import type {
26
- NodeApplication,
27
- NodeConfig,
28
29
  Context as AlpContext,
29
- ContextState,
30
30
  ContextSanitizedState,
31
- } from './types';
31
+ ContextState,
32
+ NodeApplication,
33
+ NodeConfig,
34
+ } from "./types";
32
35
 
33
- const logger = new Logger('alp');
36
+ const logger = new Logger("alp");
34
37
 
35
38
  export interface AlpNodeAppOptions {
36
39
  appDirname: string;
@@ -40,8 +43,8 @@ export interface AlpNodeAppOptions {
40
43
  publicPath?: string;
41
44
  }
42
45
 
43
- declare module 'koa' {
44
- // eslint-disable-next-line @typescript-eslint/no-empty-interface, @typescript-eslint/no-shadow
46
+ declare module "koa" {
47
+ // eslint-disable-next-line @typescript-eslint/no-empty-object-type
45
48
  interface DefaultState extends ContextState {}
46
49
 
47
50
  interface DefaultContext
@@ -58,7 +61,7 @@ declare module 'koa' {
58
61
  params?: P,
59
62
  ) => void;
60
63
  }
61
- // eslint-disable-next-line @typescript-eslint/no-empty-interface
64
+ // eslint-disable-next-line @typescript-eslint/no-empty-object-type
62
65
  interface BaseRequest extends AlpParamsRequest {}
63
66
  }
64
67
 
@@ -90,31 +93,24 @@ export class AlpNodeApp extends Koa<ContextState> implements NodeApplication {
90
93
  super();
91
94
 
92
95
  this.dirname = path.normalize(appDirname);
93
-
94
- Object.defineProperty(this, 'packageDirname', {
95
- get: deprecate(() => packageDirname, 'packageDirname'),
96
- configurable: false,
97
- enumerable: false,
98
- });
99
-
100
96
  this.certPath = certPath || `${packageDirname}/config/cert`;
101
97
  this.publicPath = publicPath || `${packageDirname}/public/`;
102
98
 
103
- this.config = _config(this, config);
99
+ this.config = config;
104
100
  this.context.config = this.config;
105
101
 
106
102
  params(this);
107
103
  language(this);
108
- translate('locales')(this);
104
+ translate("locales")(this);
109
105
 
110
106
  this.use(compress());
111
107
  }
112
108
 
113
- existsConfigSync(name: string): ReturnType<Config['existsConfigSync']> {
109
+ existsConfigSync(name: string): ReturnType<Config["existsConfigSync"]> {
114
110
  return this.config.existsConfigSync(name);
115
111
  }
116
112
 
117
- loadConfigSync(name: string): ReturnType<Config['loadConfigSync']> {
113
+ loadConfigSync(name: string): ReturnType<Config["loadConfigSync"]> {
118
114
  return this.config.loadConfigSync(name);
119
115
  }
120
116
 
@@ -123,6 +119,7 @@ export class AlpNodeApp extends Koa<ContextState> implements NodeApplication {
123
119
  res: ServerResponse,
124
120
  ): ParameterizedContext<StateT> {
125
121
  const ctx = super.createContext<StateT>(req, res);
122
+ // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
126
123
  ctx.sanitizedState = {} as ContextSanitizedState;
127
124
  return ctx;
128
125
  }
@@ -135,9 +132,8 @@ export class AlpNodeApp extends Koa<ContextState> implements NodeApplication {
135
132
  this.use(errors);
136
133
  }
137
134
 
138
- // eslint-disable-next-line @typescript-eslint/class-methods-use-this
139
135
  override listen(): never {
140
- throw new Error('Use start instead');
136
+ throw new Error("Use start instead");
141
137
  }
142
138
 
143
139
  /**
@@ -146,25 +142,29 @@ export class AlpNodeApp extends Koa<ContextState> implements NodeApplication {
146
142
  close(): void {
147
143
  if (this._server) {
148
144
  this._server.close();
149
- this.emit('close');
145
+ this.emit("close");
150
146
  }
151
147
  }
152
148
 
153
149
  async start(fn: () => Promise<void> | void): Promise<Server> {
154
150
  await fn();
155
151
  try {
156
- const server = await _listen(this.config, this.callback(), this.certPath);
152
+ const server = await _listen(
153
+ this.config,
154
+ this.callback() as RequestListener,
155
+ this.certPath,
156
+ );
157
157
  this._server = server;
158
- logger.success('started');
159
- if (process.send) process.send('ready');
158
+ logger.success("started");
159
+ if (process.send) process.send("ready");
160
160
  return server;
161
161
  } catch (error: unknown) {
162
- logger.error('start fail', { err: error });
162
+ logger.error("start fail", { err: error });
163
163
  throw error;
164
164
  }
165
165
  }
166
166
  }
167
167
 
168
- export type { Context } from 'koa';
168
+ export type { Context } from "koa";
169
169
 
170
- export { type NodeApplication } from './types';
170
+ export { type NodeApplication } from "./types";
package/src/config.ts CHANGED
@@ -1,8 +1,7 @@
1
- import { existsSync, readFileSync } from 'node:fs';
2
- import deepFreeze from 'deep-freeze-es6';
3
- import minimist from 'minimist';
4
- import parseJSON from 'parse-json-object-as-map';
5
- import type { NodeApplication, NodeConfig, PackageConfig } from './types';
1
+ import { existsSync, readFileSync } from "node:fs";
2
+ import deepFreeze from "deep-freeze-es6";
3
+ import minimist from "minimist";
4
+ import type { NodeConfig, PackageConfig } from "./types";
6
5
 
7
6
  const argv = minimist(process.argv.slice(2));
8
7
 
@@ -10,9 +9,12 @@ function _existsConfigSync(dirname: string, name: string): boolean {
10
9
  return existsSync(`${dirname}${name}.json`);
11
10
  }
12
11
 
13
- function _loadConfigSync(dirname: string, name: string): Map<string, unknown> {
14
- const content = readFileSync(`${dirname}${name}.json`, 'utf8');
15
- return parseJSON(content) as Map<string, unknown>;
12
+ function _loadConfigSync(
13
+ dirname: string,
14
+ name: string,
15
+ ): Record<string, unknown> {
16
+ const content = readFileSync(`${dirname}${name}.json`, "utf8");
17
+ return JSON.parse(content) as Record<string, unknown>;
16
18
  }
17
19
 
18
20
  export interface ConfigOptions {
@@ -24,98 +26,91 @@ export interface ConfigOptions {
24
26
  export class Config {
25
27
  packageConfig?: PackageConfig;
26
28
 
27
- private _map: Map<string, unknown>;
29
+ private _record: Record<string, unknown>;
28
30
 
29
31
  private readonly _dirname: string;
30
32
 
31
33
  constructor(dirname: string, options?: ConfigOptions) {
32
- this._map = new Map<string, unknown>();
33
- this._dirname = dirname.replace(/\/*$/, '/');
34
+ this._record = {};
35
+ this._dirname = dirname.replace(/\/*$/, "/");
34
36
  if (options) {
35
37
  this.loadSync(options);
36
38
  }
37
39
  }
38
40
 
39
41
  loadSync(options: ConfigOptions = {}): Config & NodeConfig {
40
- const env = process.env.CONFIG_ENV || process.env.NODE_ENV || 'development';
42
+ const env = process.env.CONFIG_ENV || process.env.NODE_ENV || "development";
41
43
  const { argv: argvOverrides = [], packageConfig, version } = options;
42
44
  this.packageConfig = packageConfig;
43
45
 
44
- const config = this.loadConfigSync('common') as Map<string, unknown>;
45
- for (const [key, value] of this.loadConfigSync(env)) {
46
- config.set(key, value);
46
+ const config = _loadConfigSync(this._dirname, "common");
47
+ for (const [key, value] of Object.entries(
48
+ _loadConfigSync(this._dirname, env),
49
+ )) {
50
+ config[key] = value;
47
51
  }
48
52
 
49
- if (this.existsConfigSync('local')) {
50
- for (const [key, value] of this.loadConfigSync('local')) {
51
- config.set(key, value);
53
+ if (this.existsConfigSync("local")) {
54
+ for (const [key, value] of Object.entries(
55
+ _loadConfigSync(this._dirname, "local"),
56
+ )) {
57
+ config[key] = value;
52
58
  }
53
59
  }
54
60
 
55
- if (config.has('version')) {
61
+ if (config.version) {
56
62
  throw new Error('Cannot have "version", in config.');
57
63
  }
58
64
 
59
- config.set(
60
- 'version',
61
- String(version || argv.version || packageConfig?.version),
62
- );
65
+ config.version = String(version || argv.version || packageConfig?.version);
63
66
 
64
67
  const socketPath: string | undefined = (argv.socket ||
65
- argv['socket-path'] ||
68
+ argv["socket-path"] ||
66
69
  argv.socketPath) as string | undefined;
67
70
  if (socketPath) {
68
- config.set('socketPath', socketPath);
71
+ config.socketPath = socketPath;
69
72
  } else if (argv.port) {
70
- config.set('port', argv.port);
71
- config.delete('socketPath');
73
+ config.port = argv.port;
74
+ delete config.socketPath;
72
75
  } else if (process.env.PORT) {
73
- config.set('port', Number(process.env.PORT));
74
- config.delete('socketPath');
76
+ config.port = Number(process.env.PORT);
77
+ delete config.socketPath;
75
78
  }
76
79
 
77
80
  argvOverrides.forEach((key) => {
78
- const splitted = key.split('.');
81
+ const splitted = key.split(".");
79
82
  const value =
80
83
  splitted.length > 0 &&
81
- // eslint-disable-next-line @typescript-eslint/no-unsafe-return,unicorn/no-array-reduce, @typescript-eslint/no-shadow
82
- splitted.reduce((config, partialKey) => config?.[partialKey], argv);
84
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-return,unicorn/no-array-reduce
85
+ splitted.reduce((config, partialKey) => config[partialKey], argv);
83
86
  if (value !== undefined) {
84
87
  const last = splitted.pop()!;
85
- const map =
88
+ const v =
86
89
  splitted.length === 0
87
90
  ? config
88
91
  : // eslint-disable-next-line unicorn/no-array-reduce
89
92
  splitted.reduce(
90
- // eslint-disable-next-line @typescript-eslint/no-shadow
91
93
  (config, partialKey) =>
92
- config.get(partialKey) as Map<string, unknown>,
94
+ config[partialKey] as Record<string, unknown>,
93
95
  config,
94
96
  );
95
- map.set(last, value);
97
+ v[last] = value;
96
98
  }
97
99
  });
98
100
 
99
- this._map = deepFreeze(config);
100
- return this as Config & NodeConfig;
101
+ this._record = deepFreeze(config);
102
+ return this as unknown as Config & NodeConfig;
101
103
  }
102
104
 
103
- get<T>(key: string): T {
104
- return this._map.get(key) as T;
105
+ get<T>(key: string): Readonly<T> {
106
+ return this._record[key] as T;
105
107
  }
106
108
 
107
109
  existsConfigSync(name: string): boolean {
108
110
  return _existsConfigSync(this._dirname, name);
109
111
  }
110
112
 
111
- loadConfigSync(name: string): ReadonlyMap<string, unknown> {
113
+ loadConfigSync(name: string): Readonly<Record<string, unknown>> {
112
114
  return _loadConfigSync(this._dirname, name);
113
115
  }
114
116
  }
115
-
116
- export default function getConfig(
117
- app: NodeApplication,
118
- config: Config & NodeConfig,
119
- ): Config & NodeConfig {
120
- return config;
121
- }
package/src/errors.ts CHANGED
@@ -1,11 +1,10 @@
1
- /* eslint-disable complexity */
2
- import { STATUS_CODES } from 'node:http';
3
- import ErrorHtmlRenderer from 'error-html';
4
- import { Logger } from 'nightingale-logger';
5
- import type { Context } from './AlpNodeApp';
6
- import type { HtmlError } from './types';
1
+ import { STATUS_CODES } from "node:http";
2
+ import ErrorHtmlRenderer from "error-html";
3
+ import { Logger } from "nightingale-logger";
4
+ import type { Context } from "./AlpNodeApp";
5
+ import type { HtmlError } from "./types";
7
6
 
8
- const logger = new Logger('alp:errors');
7
+ const logger = new Logger("alp:errors");
9
8
  const errorHtmlRenderer = new ErrorHtmlRenderer({
10
9
  appPath: `${process.cwd()}/`,
11
10
  });
@@ -18,19 +17,19 @@ export default async function alpNodeErrors(
18
17
  await next();
19
18
  } catch (error: unknown) {
20
19
  // eslint-disable-next-line no-ex-assign
21
- if (!error) error = new Error('Unknown error');
20
+ if (!error) error = new Error("Unknown error");
22
21
  // eslint-disable-next-line no-ex-assign
23
- if (typeof error === 'string') error = new Error(error);
22
+ if (typeof error === "string") error = new Error(error);
24
23
 
25
24
  ctx.status = (error as HtmlError).status || 500;
26
25
  // eslint-disable-next-line @typescript-eslint/no-unsafe-argument
27
26
  logger.error(error as any);
28
27
 
29
- switch (ctx.request.accepts('html', 'text', 'json')) {
30
- case 'json':
31
- ctx.type = 'application/json';
28
+ switch (ctx.request.accepts("html", "text", "json")) {
29
+ case "json":
30
+ ctx.type = "application/json";
32
31
  if (
33
- process.env.NODE_ENV !== 'production' ||
32
+ process.env.NODE_ENV !== "production" ||
34
33
  (error as HtmlError).expose
35
34
  ) {
36
35
  ctx.body = { error: (error as Error).message };
@@ -40,9 +39,9 @@ export default async function alpNodeErrors(
40
39
 
41
40
  break;
42
41
 
43
- case 'html':
44
- ctx.type = 'text/html';
45
- if (process.env.NODE_ENV !== 'production') {
42
+ case "html":
43
+ ctx.type = "text/html";
44
+ if (process.env.NODE_ENV !== "production") {
46
45
  ctx.body = errorHtmlRenderer.render(error as Error);
47
46
  } else if ((error as HtmlError).expose) {
48
47
  ctx.body = (error as Error).message;
@@ -52,11 +51,12 @@ export default async function alpNodeErrors(
52
51
 
53
52
  break;
54
53
 
55
- case 'text':
54
+ case "text":
55
+ case false:
56
56
  default:
57
- ctx.type = 'text/plain';
57
+ ctx.type = "text/plain";
58
58
  if (
59
- process.env.NODE_ENV !== 'production' ||
59
+ process.env.NODE_ENV !== "production" ||
60
60
  (error as HtmlError).expose
61
61
  ) {
62
62
  ctx.body = (error as Error).message;
package/src/index.ts CHANGED
@@ -1,9 +1,9 @@
1
- import { existsSync, readFileSync } from 'node:fs';
2
- import path from 'node:path';
3
- import { Logger } from 'nightingale-logger';
4
- import type { AlpNodeAppOptions } from './AlpNodeApp';
5
- import { AlpNodeApp } from './AlpNodeApp';
6
- import { Config } from './config';
1
+ import { existsSync, readFileSync } from "node:fs";
2
+ import path from "node:path";
3
+ import { Logger } from "nightingale-logger";
4
+ import type { AlpNodeAppOptions } from "./AlpNodeApp";
5
+ import { AlpNodeApp } from "./AlpNodeApp";
6
+ import { Config } from "./config";
7
7
 
8
8
  export type {
9
9
  BaseContext,
@@ -11,23 +11,23 @@ export type {
11
11
  NodeConfig,
12
12
  ContextState,
13
13
  ContextSanitizedState,
14
- } from './types';
15
- export type { Context } from './AlpNodeApp';
14
+ } from "./types";
15
+ export type { Context } from "./AlpNodeApp";
16
16
 
17
- const logger = new Logger('alp');
17
+ const logger = new Logger("alp");
18
18
 
19
- export const appDirname = path.resolve('build');
19
+ export const appDirname = path.resolve("build");
20
20
 
21
- const packagePath = path.resolve('package.json');
21
+ const packagePath = path.resolve("package.json");
22
22
  if (!packagePath) {
23
23
  throw new Error(`Could not find package.json: "${String(packagePath)}"`);
24
24
  }
25
25
  export const packageDirname = path.dirname(packagePath);
26
26
 
27
- logger.debug('init', { appDirname, packageDirname });
27
+ logger.debug("init", { appDirname, packageDirname });
28
28
 
29
29
  export const packageConfig: Record<string, unknown> = JSON.parse(
30
- readFileSync(packagePath, 'utf8'),
30
+ readFileSync(packagePath, "utf8"),
31
31
  ) as Record<string, unknown>;
32
32
 
33
33
  const buildedConfigPath = `${appDirname}/build/config/`;
@@ -39,7 +39,7 @@ export const config = new Config(configPath).loadSync({ packageConfig });
39
39
 
40
40
  export type AppOptions = Omit<
41
41
  AlpNodeAppOptions,
42
- 'appDirname' | 'config' | 'packageDirname'
42
+ "appDirname" | "config" | "packageDirname"
43
43
  >;
44
44
 
45
45
  export default class App extends AlpNodeApp {
@@ -53,11 +53,11 @@ export default class App extends AlpNodeApp {
53
53
  }
54
54
  }
55
55
 
56
- export { Config } from './config';
56
+ export { Config } from "./config";
57
57
 
58
58
  export {
59
59
  default as router,
60
60
  createAlpRouterBuilder,
61
61
  type AlpRouteRef,
62
62
  type AlpRouter,
63
- } from './router';
63
+ } from "./router";
package/src/language.ts CHANGED
@@ -1,6 +1,6 @@
1
- import type { Context } from 'koa';
2
- import { defineLazyProperty } from 'object-properties';
3
- import type { AlpNodeApp } from './AlpNodeApp';
1
+ import type { Context } from "koa";
2
+ import { defineLazyProperty } from "object-properties";
3
+ import type { AlpNodeApp } from "./AlpNodeApp";
4
4
 
5
5
  export interface AlpLanguageContext {
6
6
  readonly firstAcceptedLanguage: string;
@@ -8,20 +8,28 @@ export interface AlpLanguageContext {
8
8
  }
9
9
  export default function alpLanguage(app: AlpNodeApp): void {
10
10
  const config = app.context.config;
11
- const availableLanguages: string[] = config.get('availableLanguages');
11
+ const availableLanguages: string[] = config.get("availableLanguages");
12
12
  if (!availableLanguages) {
13
13
  throw new Error('Missing config "availableLanguages"');
14
14
  }
15
15
 
16
- defineLazyProperty(app.context, 'language', function (this: Context): string {
17
- return this.acceptsLanguages(availableLanguages) || availableLanguages[0];
18
- });
16
+ defineLazyProperty(
17
+ app.context,
18
+ "language",
19
+ function language(this: Context): string {
20
+ return (
21
+ this.acceptsLanguages(availableLanguages) ||
22
+ availableLanguages[0] ||
23
+ "en"
24
+ );
25
+ },
26
+ );
19
27
 
20
28
  defineLazyProperty(
21
29
  app.context,
22
- 'firstAcceptedLanguage',
23
- function (this: Context): string {
24
- return this.acceptsLanguages()[0] || availableLanguages[0];
30
+ "firstAcceptedLanguage",
31
+ function firstAcceptedLanguage(this: Context): string {
32
+ return this.acceptsLanguages()[0] || availableLanguages[0] || "en";
25
33
  },
26
34
  );
27
35
  }