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.
- package/CHANGELOG.md +24 -0
- package/README.md +7 -7
- package/dist/{AlpNodeApp-node18.mjs → AlpNodeApp-node20.mjs} +59 -77
- package/dist/AlpNodeApp-node20.mjs.map +1 -0
- package/dist/definitions/AlpNodeApp.d.ts +15 -16
- 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-node20.mjs} +142 -158
- package/dist/index-node20.mjs.map +1 -0
- package/package.json +23 -23
- package/src/AlpNodeApp.ts +48 -48
- 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 +5 -5
- 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
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "alp-node",
|
|
3
|
-
"version": "
|
|
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": ">=
|
|
25
|
+
"node": ">=20.11.0"
|
|
26
26
|
},
|
|
27
27
|
"sideEffects": false,
|
|
28
|
-
"main": "./dist/index-
|
|
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-
|
|
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-
|
|
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 --
|
|
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
|
-
"
|
|
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": "^
|
|
80
|
+
"router-segments": "^11.0.0"
|
|
80
81
|
},
|
|
81
82
|
"dependencies": {
|
|
82
|
-
"@types/koa": "^
|
|
83
|
-
"@types/node": ">=
|
|
84
|
-
"deep-freeze-es6": "^
|
|
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": "^
|
|
88
|
-
"koa-compress": "^5.
|
|
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": "^
|
|
93
|
-
"parse-json-object-as-map": "^1.2.0"
|
|
93
|
+
"object-properties": "^9.0.1"
|
|
94
94
|
},
|
|
95
95
|
"devDependencies": {
|
|
96
|
-
"@babel/core": "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": "
|
|
101
|
-
"typescript": "5.
|
|
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 {
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
import
|
|
8
|
-
import
|
|
9
|
-
import type {
|
|
10
|
-
import
|
|
11
|
-
import
|
|
12
|
-
import
|
|
13
|
-
import type {
|
|
14
|
-
import
|
|
15
|
-
import
|
|
16
|
-
import type {
|
|
17
|
-
import
|
|
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
|
|
23
|
-
import type { TranslateBaseContext, TranslateContext } from
|
|
24
|
-
import translate from
|
|
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
|
-
|
|
31
|
+
ContextState,
|
|
32
|
+
NodeApplication,
|
|
33
|
+
NodeConfig,
|
|
34
|
+
} from "./types";
|
|
32
35
|
|
|
33
|
-
const logger = new Logger(
|
|
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
|
|
44
|
-
// eslint-disable-next-line @typescript-eslint/no-empty-
|
|
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-
|
|
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 =
|
|
99
|
+
this.config = config;
|
|
104
100
|
this.context.config = this.config;
|
|
105
101
|
|
|
106
102
|
params(this);
|
|
107
103
|
language(this);
|
|
108
|
-
translate(
|
|
104
|
+
translate("locales")(this);
|
|
109
105
|
|
|
110
106
|
this.use(compress());
|
|
111
107
|
}
|
|
112
108
|
|
|
113
|
-
existsConfigSync(name: string): ReturnType<Config[
|
|
109
|
+
existsConfigSync(name: string): ReturnType<Config["existsConfigSync"]> {
|
|
114
110
|
return this.config.existsConfigSync(name);
|
|
115
111
|
}
|
|
116
112
|
|
|
117
|
-
loadConfigSync(name: string): ReturnType<Config[
|
|
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(
|
|
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(
|
|
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(
|
|
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(
|
|
159
|
-
if (process.send) process.send(
|
|
158
|
+
logger.success("started");
|
|
159
|
+
if (process.send) process.send("ready");
|
|
160
160
|
return server;
|
|
161
161
|
} catch (error: unknown) {
|
|
162
|
-
logger.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
|
|
168
|
+
export type { Context } from "koa";
|
|
169
169
|
|
|
170
|
-
export { type NodeApplication } from
|
|
170
|
+
export { type NodeApplication } from "./types";
|
package/src/config.ts
CHANGED
|
@@ -1,8 +1,7 @@
|
|
|
1
|
-
import { existsSync, readFileSync } from
|
|
2
|
-
import deepFreeze from
|
|
3
|
-
import minimist from
|
|
4
|
-
import
|
|
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(
|
|
14
|
-
|
|
15
|
-
|
|
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
|
|
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.
|
|
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 ||
|
|
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.
|
|
45
|
-
for (const [key, value] of
|
|
46
|
-
|
|
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(
|
|
50
|
-
for (const [key, value] of
|
|
51
|
-
|
|
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.
|
|
61
|
+
if (config.version) {
|
|
56
62
|
throw new Error('Cannot have "version", in config.');
|
|
57
63
|
}
|
|
58
64
|
|
|
59
|
-
config.
|
|
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[
|
|
68
|
+
argv["socket-path"] ||
|
|
66
69
|
argv.socketPath) as string | undefined;
|
|
67
70
|
if (socketPath) {
|
|
68
|
-
config.
|
|
71
|
+
config.socketPath = socketPath;
|
|
69
72
|
} else if (argv.port) {
|
|
70
|
-
config.
|
|
71
|
-
config.
|
|
73
|
+
config.port = argv.port;
|
|
74
|
+
delete config.socketPath;
|
|
72
75
|
} else if (process.env.PORT) {
|
|
73
|
-
config.
|
|
74
|
-
config.
|
|
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
|
|
82
|
-
splitted.reduce((config, partialKey) => config
|
|
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
|
|
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
|
|
94
|
+
config[partialKey] as Record<string, unknown>,
|
|
93
95
|
config,
|
|
94
96
|
);
|
|
95
|
-
|
|
97
|
+
v[last] = value;
|
|
96
98
|
}
|
|
97
99
|
});
|
|
98
100
|
|
|
99
|
-
this.
|
|
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.
|
|
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):
|
|
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
|
-
|
|
2
|
-
import
|
|
3
|
-
import
|
|
4
|
-
import {
|
|
5
|
-
import type {
|
|
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(
|
|
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(
|
|
20
|
+
if (!error) error = new Error("Unknown error");
|
|
22
21
|
// eslint-disable-next-line no-ex-assign
|
|
23
|
-
if (typeof 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(
|
|
30
|
-
case
|
|
31
|
-
ctx.type =
|
|
28
|
+
switch (ctx.request.accepts("html", "text", "json")) {
|
|
29
|
+
case "json":
|
|
30
|
+
ctx.type = "application/json";
|
|
32
31
|
if (
|
|
33
|
-
process.env.NODE_ENV !==
|
|
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
|
|
44
|
-
ctx.type =
|
|
45
|
-
if (process.env.NODE_ENV !==
|
|
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
|
|
54
|
+
case "text":
|
|
55
|
+
case false:
|
|
56
56
|
default:
|
|
57
|
-
ctx.type =
|
|
57
|
+
ctx.type = "text/plain";
|
|
58
58
|
if (
|
|
59
|
-
process.env.NODE_ENV !==
|
|
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
|
|
2
|
-
import path from
|
|
3
|
-
import { Logger } from
|
|
4
|
-
import type { AlpNodeAppOptions } from
|
|
5
|
-
import { AlpNodeApp } from
|
|
6
|
-
import { Config } from
|
|
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
|
|
15
|
-
export type { Context } from
|
|
14
|
+
} from "./types";
|
|
15
|
+
export type { Context } from "./AlpNodeApp";
|
|
16
16
|
|
|
17
|
-
const logger = new Logger(
|
|
17
|
+
const logger = new Logger("alp");
|
|
18
18
|
|
|
19
|
-
export const appDirname = path.resolve(
|
|
19
|
+
export const appDirname = path.resolve("build");
|
|
20
20
|
|
|
21
|
-
const packagePath = path.resolve(
|
|
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(
|
|
27
|
+
logger.debug("init", { appDirname, packageDirname });
|
|
28
28
|
|
|
29
29
|
export const packageConfig: Record<string, unknown> = JSON.parse(
|
|
30
|
-
readFileSync(packagePath,
|
|
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
|
-
|
|
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
|
|
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
|
|
63
|
+
} from "./router";
|
package/src/language.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import type { Context } from
|
|
2
|
-
import { defineLazyProperty } from
|
|
3
|
-
import type { AlpNodeApp } from
|
|
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(
|
|
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(
|
|
17
|
-
|
|
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
|
-
|
|
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
|
}
|