alp-node 6.2.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 (66) hide show
  1. package/CHANGELOG.md +38 -0
  2. package/README.md +7 -7
  3. package/dist/AlpNodeApp-node20.mjs +367 -0
  4. package/dist/AlpNodeApp-node20.mjs.map +1 -0
  5. package/dist/definitions/AlpNodeApp.d.ts +21 -14
  6. package/dist/definitions/AlpNodeApp.d.ts.map +1 -1
  7. package/dist/definitions/config.d.ts +17 -0
  8. package/dist/definitions/config.d.ts.map +1 -0
  9. package/dist/definitions/errors.d.ts +3 -0
  10. package/dist/definitions/errors.d.ts.map +1 -0
  11. package/dist/definitions/index.d.ts +9 -7
  12. package/dist/definitions/index.d.ts.map +1 -1
  13. package/dist/definitions/language.d.ts +7 -0
  14. package/dist/definitions/language.d.ts.map +1 -0
  15. package/dist/definitions/listen.d.ts +6 -0
  16. package/dist/definitions/listen.d.ts.map +1 -0
  17. package/dist/definitions/params/ParamValid.d.ts +8 -0
  18. package/dist/definitions/params/ParamValid.d.ts.map +1 -0
  19. package/dist/definitions/params/ParamValidationResult.d.ts +9 -0
  20. package/dist/definitions/params/ParamValidationResult.d.ts.map +1 -0
  21. package/dist/definitions/params/ParamValidationResult.test.d.ts +2 -0
  22. package/dist/definitions/params/ParamValidationResult.test.d.ts.map +1 -0
  23. package/dist/definitions/params/ParamValueFromContext.d.ts +12 -0
  24. package/dist/definitions/params/ParamValueFromContext.d.ts.map +1 -0
  25. package/dist/definitions/params/ParamValueModelValidator.d.ts +4 -0
  26. package/dist/definitions/params/ParamValueModelValidator.d.ts.map +1 -0
  27. package/dist/definitions/params/ParamValueStringValidator.d.ts +5 -0
  28. package/dist/definitions/params/ParamValueStringValidator.d.ts.map +1 -0
  29. package/dist/definitions/params/ParamValueValidator.d.ts +10 -0
  30. package/dist/definitions/params/ParamValueValidator.d.ts.map +1 -0
  31. package/dist/definitions/params/index.d.ts +19 -0
  32. package/dist/definitions/params/index.d.ts.map +1 -0
  33. package/dist/definitions/router.d.ts +13 -0
  34. package/dist/definitions/router.d.ts.map +1 -0
  35. package/dist/definitions/translate/index.d.ts +11 -0
  36. package/dist/definitions/translate/index.d.ts.map +1 -0
  37. package/dist/definitions/translate/load.d.ts +4 -0
  38. package/dist/definitions/translate/load.d.ts.map +1 -0
  39. package/dist/definitions/types.d.ts +53 -0
  40. package/dist/definitions/types.d.ts.map +1 -0
  41. package/dist/index-node20.mjs +495 -0
  42. package/dist/index-node20.mjs.map +1 -0
  43. package/package.json +27 -28
  44. package/src/AlpNodeApp.ts +71 -50
  45. package/src/config.ts +116 -0
  46. package/src/errors.ts +70 -0
  47. package/src/index.ts +33 -18
  48. package/src/language.ts +35 -0
  49. package/src/listen.ts +68 -0
  50. package/src/params/ParamValid.ts +15 -0
  51. package/src/params/ParamValidationResult.test.ts +65 -0
  52. package/src/params/ParamValidationResult.ts +38 -0
  53. package/src/params/ParamValueFromContext.ts +42 -0
  54. package/src/params/ParamValueModelValidator.ts +36 -0
  55. package/src/params/ParamValueStringValidator.ts +13 -0
  56. package/src/params/ParamValueValidator.ts +23 -0
  57. package/src/params/index.ts +70 -0
  58. package/src/router.ts +64 -0
  59. package/src/translate/index.ts +45 -0
  60. package/src/translate/load.ts +31 -0
  61. package/src/types.ts +67 -0
  62. package/dist/AlpNodeApp-node18.mjs +0 -94
  63. package/dist/AlpNodeApp-node18.mjs.map +0 -1
  64. package/dist/index-node18.mjs +0 -124
  65. package/dist/index-node18.mjs.map +0 -1
  66. package/src/.eslintrc.json +0 -31
@@ -0,0 +1,65 @@
1
+ import { ParamValidationResult } from "./ParamValidationResult";
2
+
3
+ // const createContextMock = (): Context &
4
+ // Record<
5
+ // 'namedParam' | 'otherParam' | 'param' | 'paramGET' | 'paramGETorPOST',
6
+ // ReturnType<typeof jest.fn>
7
+ // > => {
8
+ // return {
9
+ // state: {} as ContextState,
10
+ // sanitizedState: {} as ContextSanitizedState,
11
+ // param: jest.fn(),
12
+ // namedParam: jest.fn(),
13
+ // otherParam: jest.fn(),
14
+ // paramGET: jest.fn(),
15
+ // paramGETorPOST: jest.fn(),
16
+ // } as unknown as Context &
17
+ // Record<
18
+ // 'namedParam' | 'otherParam' | 'param' | 'paramGET' | 'paramGETorPOST',
19
+ // ReturnType<typeof jest.fn>
20
+ // >;
21
+ // };
22
+
23
+ test("on init is valid", () => {
24
+ const paramValidator = new ParamValidationResult();
25
+ expect(paramValidator.getErrors()).toBe(undefined);
26
+ expect(paramValidator.hasErrors()).toBe(false);
27
+ expect(paramValidator.isValid()).toBe(true);
28
+ });
29
+
30
+ test("has error", () => {
31
+ const paramValidator = new ParamValidationResult();
32
+ paramValidator._error("slug", "notEmpty", "");
33
+ expect(paramValidator.hasErrors()).toBe(true);
34
+ expect(paramValidator.isValid()).toBe(false);
35
+ expect(paramValidator.getErrors()).toEqual({
36
+ slug: { error: "notEmpty", value: "" },
37
+ });
38
+ });
39
+
40
+ // test('.string() empty', () => {
41
+ // const contextMock = createContextMock();
42
+ // contextMock.param.mockReturnValue('');
43
+
44
+ // const paramValidator = new ParamValidationResult(contextMock);
45
+
46
+ // paramValidator.string('slug').notEmpty();
47
+ // expect(contextMock.param).toHaveBeenNthCalledWith(1, 'slug');
48
+ // expect(paramValidator.hasErrors()).toBe(true);
49
+ // expect(paramValidator.isValid()).toBe(false);
50
+ // expect(paramValidator.getErrors()).toEqual({
51
+ // slug: { error: 'notEmpty', value: '' },
52
+ // });
53
+ // });
54
+
55
+ // test('.string() not empty', () => {
56
+ // const contextMock = createContextMock();
57
+ // contextMock.param.mockReturnValue('testValue');
58
+ // const paramValidator = new ParamValidationResult(contextMock);
59
+
60
+ // paramValidator.string('slug').notEmpty();
61
+ // expect(contextMock.param).toHaveBeenNthCalledWith(1, 'slug');
62
+ // expect(paramValidator.hasErrors()).toBe(false);
63
+ // expect(paramValidator.isValid()).toBe(true);
64
+ // expect(paramValidator.getErrors()).toBe(undefined);
65
+ // });
@@ -0,0 +1,38 @@
1
+ export type Errors = Record<string, any>;
2
+
3
+ export class ParamValidationResult {
4
+ _errors?: Errors;
5
+
6
+ _error(name: string, key: string, value: unknown): void {
7
+ if (!this._errors) {
8
+ this._errors = {};
9
+ }
10
+
11
+ this._errors[name] = { error: key, value };
12
+ }
13
+
14
+ getErrors(): Errors | undefined {
15
+ return this._errors;
16
+ }
17
+
18
+ hasErrors(): boolean {
19
+ return this._errors !== undefined;
20
+ }
21
+
22
+ isValid(): boolean {
23
+ return this._errors === undefined;
24
+ }
25
+
26
+ // string(name: string): ParamValueStringValidator {
27
+ // return new ParamValueStringValidator(this, name, this.context.param(name));
28
+ // }
29
+ /* int(name, position) {
30
+ return new ParamValueIntValidator(this, name, this.context.param(name, position));
31
+ }
32
+ model(modelName, name) {
33
+ name = name || S.string.lcFirst(modelName);
34
+ console.log('paramvalidator model', modelName, M[modelName]);
35
+ let data = this.context.getOrPostParam(name);
36
+ return new ParamValueModelValidator(this, name, !data ? null : new M[modelName](data));
37
+ } */
38
+ }
@@ -0,0 +1,42 @@
1
+ import type { Context } from "../AlpNodeApp";
2
+ import type { ParamValidationResult } from "./ParamValidationResult";
3
+ import ParamValueStringValidator from "./ParamValueStringValidator";
4
+
5
+ export class ParamValueFromContext {
6
+ readonly validationResult: ParamValidationResult;
7
+
8
+ readonly context: Context;
9
+
10
+ constructor(context: Context, validationResult: ParamValidationResult) {
11
+ this.validationResult = validationResult;
12
+ this.context = context;
13
+ }
14
+
15
+ namedParam(name: string): ParamValueStringValidator {
16
+ return new ParamValueStringValidator(
17
+ this.validationResult,
18
+ name,
19
+ this.context.namedRouteParam(name),
20
+ );
21
+ }
22
+
23
+ otherParam(position: number): ParamValueStringValidator {
24
+ return new ParamValueStringValidator(
25
+ this.validationResult,
26
+ String(position),
27
+ this.context.otherRouteParam(position),
28
+ );
29
+ }
30
+
31
+ queryParam(name: string): ParamValueStringValidator {
32
+ return new ParamValueStringValidator(
33
+ this.validationResult,
34
+ name,
35
+ this.context.queryParam(name),
36
+ );
37
+ }
38
+
39
+ // bodyParam: <T>(name: string): ParamValueValidator<string | undefined> {
40
+
41
+ // }
42
+ }
@@ -0,0 +1,36 @@
1
+ import ParamValueValidator from "./ParamValueValidator";
2
+
3
+ export default class ParamValueModelValidator<
4
+ T,
5
+ > extends ParamValueValidator<T> {
6
+ /*
7
+ required() {
8
+ if (this.value == null) {
9
+ this._error('required');
10
+ }
11
+ return this;
12
+ }
13
+ valid(fieldsRequired) {
14
+ if (this.value == null) {
15
+ return this;
16
+ }
17
+ if (S.isString(fieldsRequired)) {
18
+ fieldsRequired = fieldsRequired.split(' ');
19
+ }
20
+ S.forEach(this.value.constructor.Fields, (name, fModel) => {
21
+ let value = this.value[name];
22
+ if (fieldsRequired) {
23
+ if(S.array.has(fieldsRequired, name) && value == null) {
24
+ this._error('required');
25
+ }
26
+ } else {
27
+ if (value == null && fModel[1] && fModel[1].required) {
28
+ this._error('required');
29
+ }
30
+ }
31
+ //TODO ...
32
+ });
33
+ return this;
34
+ }
35
+ */
36
+ }
@@ -0,0 +1,13 @@
1
+ import ParamValueValidator from "./ParamValueValidator";
2
+
3
+ export default class ParamValueStringValidator<
4
+ T extends string = string,
5
+ > extends ParamValueValidator<T | null | undefined> {
6
+ notEmpty(): ParamValueValidator<T> {
7
+ if (this.value == null || this.value.trim() === "") {
8
+ this._error("notEmpty");
9
+ }
10
+
11
+ return this as ParamValueValidator<T>;
12
+ }
13
+ }
@@ -0,0 +1,23 @@
1
+ import type { ParamValidationResult } from "./ParamValidationResult";
2
+
3
+ export default class ParamValueValidator<T> {
4
+ readonly validationResult: ParamValidationResult;
5
+
6
+ readonly name: string;
7
+
8
+ readonly value: T;
9
+
10
+ constructor(validationResult: ParamValidationResult, name: string, value: T) {
11
+ this.validationResult = validationResult;
12
+ this.name = name;
13
+ this.value = value;
14
+ }
15
+
16
+ isValid(): boolean {
17
+ return this.validationResult.isValid();
18
+ }
19
+
20
+ _error(key: string): void {
21
+ this.validationResult._error(this.name, key, this.value);
22
+ }
23
+ }
@@ -0,0 +1,70 @@
1
+ import { defineLazyProperty } from "object-properties";
2
+ import type { AlpNodeApp, Context } from "../AlpNodeApp";
3
+ import ParamValid from "./ParamValid";
4
+ import { ParamValidationResult } from "./ParamValidationResult";
5
+ import { ParamValueFromContext } from "./ParamValueFromContext";
6
+
7
+ export interface AlpParamsContext {
8
+ params: ParamValueFromContext;
9
+ validParams: ParamValueFromContext;
10
+ namedRouteParam: (name: string) => string | undefined;
11
+ otherRouteParam: (position: number) => string | undefined;
12
+ /** @deprecated use namedRouteParam */
13
+ namedParam: never;
14
+ /** @deprecated use otherRouteParam */
15
+ otherParam: never;
16
+ queryParam: (name: string) => string | undefined;
17
+ bodyParam: <T>(name: string) => T | undefined;
18
+ }
19
+
20
+ export interface AlpParamsRequest {
21
+ searchParams: URLSearchParams;
22
+ }
23
+
24
+ export default function alpParams(app: AlpNodeApp): void {
25
+ Object.assign(app.context, {
26
+ namedRouteParam(this: Context, name: string): string | undefined {
27
+ const namedParams = this.route.namedParams;
28
+ return namedParams?.get(name);
29
+ },
30
+
31
+ otherRouteParam(this: Context, position: number): string | undefined {
32
+ const otherParams = this.route.otherParams;
33
+ return otherParams?.[position - 1];
34
+ },
35
+
36
+ queryParam(this: Context, name: string): string | undefined {
37
+ const searchParams = this.request.searchParams;
38
+ return searchParams.get(name) ?? undefined;
39
+ },
40
+
41
+ bodyParam<T>(this: Context, name: string): T | undefined {
42
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-return, @typescript-eslint/no-unsafe-member-access
43
+ return (this.body as any)[name];
44
+ },
45
+ });
46
+
47
+ defineLazyProperty(
48
+ app.request,
49
+ "searchParams",
50
+ function searchParams(this: Context["request"]): URLSearchParams {
51
+ return new URLSearchParams(this.search);
52
+ },
53
+ );
54
+
55
+ defineLazyProperty(
56
+ app.context,
57
+ "params",
58
+ function params(this: Context): ParamValueFromContext {
59
+ return new ParamValueFromContext(this, new ParamValidationResult());
60
+ },
61
+ );
62
+
63
+ defineLazyProperty(
64
+ app.context,
65
+ "validParams",
66
+ function validParams(this: Context): ParamValueFromContext {
67
+ return new ParamValueFromContext(this, new ParamValid(this));
68
+ },
69
+ );
70
+ }
package/src/router.ts ADDED
@@ -0,0 +1,64 @@
1
+ import type {
2
+ LocaleType,
3
+ RouteMatch,
4
+ Router,
5
+ RouterBuilder,
6
+ } from "router-segments";
7
+ import { createRouterBuilder } from "router-segments";
8
+ import type { AlpNodeApp, Context } from "./AlpNodeApp";
9
+
10
+ export type AlpRouter<Locales extends LocaleType> = Router<
11
+ Locales,
12
+ AlpRouteRef
13
+ >;
14
+ export type AlpRouteRef = (ctx: Context) => Promise<void> | void;
15
+ type ReturnType = (app: AlpNodeApp) => AlpRouteRef;
16
+
17
+ export interface RouterContext {
18
+ route: RouteMatch<any, AlpRouteRef>;
19
+ }
20
+ export const createAlpRouterBuilder = <
21
+ Locales extends LocaleType,
22
+ >(): RouterBuilder<Locales, AlpRouteRef> =>
23
+ createRouterBuilder<Locales, AlpRouteRef>();
24
+
25
+ export type UrlGenerator = <P extends Record<string, unknown> | undefined>(
26
+ routeKey: string,
27
+ params?: P,
28
+ ) => string;
29
+
30
+ export default function alpRouter<Locales extends string>(
31
+ router: Router<Locales, AlpRouteRef>,
32
+ ): ReturnType {
33
+ return (app: AlpNodeApp) => {
34
+ app.router = router;
35
+
36
+ app.context.urlGenerator = function urlGenerator<
37
+ P extends Record<string, unknown> | undefined,
38
+ >(this: Context, routeKey: string, params?: P): string {
39
+ return router.toLocalizedPath(this.language as Locales, routeKey, params);
40
+ };
41
+
42
+ app.context.redirectTo = function redirectTo<
43
+ P extends Record<string, unknown> | undefined,
44
+ >(this: Context, to: string, params?: P): void {
45
+ this.redirect(
46
+ router.toLocalizedPath(this.language as Locales, to, params),
47
+ );
48
+ };
49
+
50
+ return async (ctx: Context): Promise<void> => {
51
+ // eslint-disable-next-line unicorn/no-array-method-this-argument
52
+ const routeMatch = router.find(ctx.request.path, ctx.language as Locales);
53
+
54
+ if (!routeMatch) {
55
+ ctx.status = 404;
56
+ throw new Error(`Route not found: ${ctx.request.path}`);
57
+ }
58
+
59
+ ctx.route = routeMatch;
60
+
61
+ await routeMatch.ref(ctx);
62
+ };
63
+ };
64
+ }
@@ -0,0 +1,45 @@
1
+ import { Logger } from "nightingale-logger";
2
+ import type { AlpNodeApp, Context } from "../AlpNodeApp";
3
+ import type { Translations } from "./load";
4
+ import load from "./load";
5
+
6
+ const logger = new Logger("alp:translate");
7
+
8
+ type Args = Record<string, any>;
9
+
10
+ export interface TranslateBaseContext {
11
+ t: (id: string, args: Args) => string;
12
+ }
13
+ export interface TranslateContext {
14
+ readonly language: string;
15
+ }
16
+
17
+ export default function alpTranslate(
18
+ dirname: string,
19
+ ): (app: AlpNodeApp) => void {
20
+ dirname = dirname.replace(/\/*$/, "/");
21
+ return (app: AlpNodeApp) => {
22
+ const appTranslations = new Map<string, Translations>();
23
+
24
+ Object.assign(app.context, {
25
+ t(this: Context, id: string, args: Args): string {
26
+ const msg = appTranslations.get(this.language)?.[id];
27
+ if (!msg) {
28
+ logger.warn("invalid msg", { language: this.language, id });
29
+ return id;
30
+ }
31
+
32
+ return msg.format(args) as string;
33
+ },
34
+ });
35
+
36
+ const config = app.config;
37
+
38
+ config.get<string[]>("availableLanguages").forEach((language) => {
39
+ const translations = app.loadConfigSync(dirname + language);
40
+ appTranslations.set(language, load(translations, language));
41
+ });
42
+
43
+ return appTranslations;
44
+ };
45
+ }
@@ -0,0 +1,31 @@
1
+ import IntlMessageFormatDefault from "intl-messageformat";
2
+
3
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
4
+ const IntlMessageFormat: typeof IntlMessageFormatDefault =
5
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
6
+ (IntlMessageFormatDefault as any).default || IntlMessageFormatDefault;
7
+
8
+ export type Translations = Readonly<Record<string, IntlMessageFormatDefault>>;
9
+
10
+ export default function load(
11
+ translations: Readonly<Record<string, unknown>>,
12
+ language: string,
13
+ ): Translations {
14
+ const result: Record<string, IntlMessageFormatDefault> = {};
15
+
16
+ (function loadMap(record: Record<string, unknown>, prefix: string) {
17
+ Object.entries(record).forEach(([key, value]) => {
18
+ if (typeof value === "object" && value !== null) {
19
+ loadMap(value as Record<string, unknown>, `${prefix}${key}.`);
20
+ return;
21
+ }
22
+
23
+ result[`${prefix}${key}`] = new IntlMessageFormat(
24
+ value as string,
25
+ language,
26
+ );
27
+ });
28
+ })(translations, "");
29
+
30
+ return result;
31
+ }
package/src/types.ts ADDED
@@ -0,0 +1,67 @@
1
+ type RawRecordConfig = Readonly<Record<string, unknown>>;
2
+
3
+ export interface Config {
4
+ get: <T>(key: string) => T;
5
+ }
6
+
7
+ export type PackageConfig = Record<string, any>;
8
+
9
+ export interface NodeConfig extends Config {
10
+ loadConfigSync: (name: string) => RawRecordConfig;
11
+ readonly packageConfig: PackageConfig;
12
+ }
13
+
14
+ // eslint-disable-next-line @typescript-eslint/no-empty-object-type
15
+ export interface ContextState {}
16
+
17
+ // eslint-disable-next-line @typescript-eslint/no-empty-object-type
18
+ export interface ContextSanitizedState {}
19
+
20
+ export interface BaseContext {
21
+ config: Config;
22
+ }
23
+
24
+ export interface Context extends BaseContext {
25
+ state: ContextState;
26
+ sanitizedState: ContextSanitizedState;
27
+ status: number;
28
+
29
+ response: any;
30
+ redirect: (url: string) => Promise<void>;
31
+ [key: string]: any;
32
+ }
33
+
34
+ export interface ApplicationInCreation {
35
+ config?: Config;
36
+ context: BaseContext;
37
+ }
38
+
39
+ export interface Application extends ApplicationInCreation {
40
+ config: Config;
41
+ }
42
+
43
+ export interface NodeApplicationInCreation extends ApplicationInCreation {
44
+ loadConfigSync: (name: string) => RawRecordConfig;
45
+ }
46
+
47
+ export interface BrowserApplicationInCreation extends ApplicationInCreation {
48
+ appVersion: string;
49
+ existsConfig: (name: string) => Promise<boolean> | boolean;
50
+ loadConfig: (name: string) => Promise<RawRecordConfig>;
51
+ createContext: () => Context;
52
+ }
53
+
54
+ export interface NodeApplication
55
+ extends Application,
56
+ NodeApplicationInCreation {
57
+ config: NodeConfig;
58
+ dirname: string;
59
+ on: (event: "close", callback: () => void) => void;
60
+ existsConfigSync: (name: string) => boolean;
61
+ loadConfigSync: (name: string) => RawRecordConfig;
62
+ }
63
+
64
+ export interface HtmlError extends Error {
65
+ status: number;
66
+ expose?: true;
67
+ }
@@ -1,94 +0,0 @@
1
- import path from 'node:path';
2
- import { deprecate } from 'node:util';
3
- import _listen from 'alp-listen';
4
- import _config from 'alp-node-config';
5
- import errors from 'alp-node-errors';
6
- import language from 'alp-node-language';
7
- import params from 'alp-params';
8
- import translate from 'alp-translate';
9
- import Koa from 'koa';
10
- import compress from 'koa-compress';
11
- import serve from 'koa-static';
12
- import { Logger } from 'nightingale-logger';
13
-
14
- const logger = new Logger('alp');
15
- class AlpNodeApp extends Koa {
16
- /**
17
- * @param {Object} [options]
18
- * @param {string} [options.certPath] directory of the ssl certificates
19
- * @param {string} [options.publicPath] directory of public files
20
- */
21
- constructor({
22
- appDirname,
23
- packageDirname,
24
- config,
25
- certPath,
26
- publicPath
27
- }) {
28
- super();
29
- this.dirname = path.normalize(appDirname);
30
- Object.defineProperty(this, 'packageDirname', {
31
- get: deprecate(() => packageDirname, 'packageDirname'),
32
- configurable: false,
33
- enumerable: false
34
- });
35
- this.certPath = certPath || `${packageDirname}/config/cert`;
36
- this.publicPath = publicPath || `${packageDirname}/public/`;
37
- this.config = _config(this, config);
38
- this.context.config = this.config;
39
- params(this);
40
- language(this);
41
- translate('locales')(this);
42
- this.use(compress());
43
- }
44
- existsConfigSync(name) {
45
- return this.config.existsConfigSync(name);
46
- }
47
- loadConfigSync(name) {
48
- return this.config.loadConfigSync(name);
49
- }
50
- createContext(req, res) {
51
- const ctx = super.createContext(req, res);
52
- ctx.sanitizedState = {};
53
- return ctx;
54
- }
55
- servePublic() {
56
- this.use(serve(this.publicPath)); // static files
57
- }
58
- catchErrors() {
59
- this.use(errors);
60
- }
61
-
62
- // eslint-disable-next-line @typescript-eslint/class-methods-use-this
63
- listen() {
64
- throw new Error('Use start instead');
65
- }
66
-
67
- /**
68
- * Close server and emit close event
69
- */
70
- close() {
71
- if (this._server) {
72
- this._server.close();
73
- this.emit('close');
74
- }
75
- }
76
- async start(fn) {
77
- await fn();
78
- try {
79
- const server = await _listen(this.config, this.callback(), this.certPath);
80
- this._server = server;
81
- logger.success('started');
82
- if (process.send) process.send('ready');
83
- return server;
84
- } catch (error) {
85
- logger.error('start fail', {
86
- err: error
87
- });
88
- throw error;
89
- }
90
- }
91
- }
92
-
93
- export { AlpNodeApp };
94
- //# sourceMappingURL=AlpNodeApp-node18.mjs.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"AlpNodeApp-node18.mjs","sources":["../src/AlpNodeApp.ts"],"sourcesContent":["import type { IncomingMessage, Server, ServerResponse } from 'node:http';\nimport path from 'node:path';\nimport { deprecate } from 'node:util';\nimport _listen from 'alp-listen';\nimport type { Config } from 'alp-node-config';\nimport _config from 'alp-node-config';\nimport errors from 'alp-node-errors';\nimport language from 'alp-node-language';\nimport params from 'alp-params';\nimport translate from 'alp-translate';\nimport type {\n NodeApplication,\n NodeConfig,\n Context as AlpContext,\n ContextState,\n ContextSanitizedState,\n ContextRequest,\n} from 'alp-types';\nimport Koa from 'koa';\nimport type { ParameterizedContext, DefaultState, BaseRequest } from 'koa';\nimport compress from 'koa-compress';\nimport serve from 'koa-static';\nimport { Logger } from 'nightingale-logger';\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-interface, @typescript-eslint/no-shadow\n interface DefaultState extends ContextState {}\n // eslint-disable-next-line @typescript-eslint/no-empty-interface\n interface DefaultContext extends AlpContext {}\n // eslint-disable-next-line @typescript-eslint/no-empty-interface\n interface BaseContext extends AlpContext {}\n // eslint-disable-next-line @typescript-eslint/no-empty-interface, @typescript-eslint/no-shadow\n interface BaseRequest extends ContextRequest {}\n}\n\nexport class AlpNodeApp extends Koa<ContextState> implements NodeApplication {\n dirname: string;\n\n certPath: string;\n\n publicPath: string;\n\n config: Config & NodeConfig;\n\n declare request: BaseRequest & ContextRequest;\n\n _server?: Server;\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\n Object.defineProperty(this, 'packageDirname', {\n get: deprecate(() => packageDirname, 'packageDirname'),\n configurable: false,\n enumerable: false,\n });\n\n this.certPath = certPath || `${packageDirname}/config/cert`;\n this.publicPath = publicPath || `${packageDirname}/public/`;\n\n this.config = _config(this, 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 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 // eslint-disable-next-line @typescript-eslint/class-methods-use-this\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(this.config, this.callback(), this.certPath);\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"],"names":["logger","Logger","AlpNodeApp","Koa","constructor","appDirname","packageDirname","config","certPath","publicPath","dirname","path","normalize","Object","defineProperty","get","deprecate","configurable","enumerable","_config","context","params","language","translate","use","compress","existsConfigSync","name","loadConfigSync","createContext","req","res","ctx","sanitizedState","servePublic","serve","catchErrors","errors","listen","Error","close","_server","emit","start","fn","server","_listen","callback","success","process","send","error","err"],"mappings":"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"}