@tsed/cli-plugin-jest 6.6.3 → 7.0.0-alpha.10

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 (64) hide show
  1. package/lib/esm/CliPluginJestModule.js +2 -0
  2. package/lib/esm/hooks/JestGenerateHook.js +28 -47
  3. package/lib/esm/hooks/JestInitHook.js +12 -25
  4. package/lib/esm/index.js +1 -1
  5. package/lib/esm/templates/controller.integration.template.js +35 -0
  6. package/lib/esm/templates/decorator.class.spec.template.js +22 -0
  7. package/lib/esm/templates/decorator.endpoint.spec.template.js +26 -0
  8. package/lib/esm/templates/decorator.method.spec.template.js +24 -0
  9. package/lib/esm/templates/decorator.param.spec.template.js +25 -0
  10. package/lib/esm/templates/decorator.parameter.spec.template.js +23 -0
  11. package/lib/esm/templates/decorator.prop.spec.template.js +26 -0
  12. package/lib/esm/templates/decorator.property.spec.template.js +24 -0
  13. package/lib/esm/templates/generic.spec.template.js +25 -0
  14. package/lib/esm/templates/index.js +12 -0
  15. package/lib/esm/templates/jest.config.template.js +84 -0
  16. package/lib/esm/templates/server.integration.template.js +30 -0
  17. package/lib/tsconfig.esm.tsbuildinfo +1 -0
  18. package/lib/types/CliPluginJestModule.d.ts +1 -0
  19. package/lib/types/hooks/JestGenerateHook.d.ts +5 -6
  20. package/lib/types/hooks/JestInitHook.d.ts +4 -9
  21. package/lib/types/index.d.ts +1 -1
  22. package/lib/types/templates/controller.integration.template.d.ts +17 -0
  23. package/lib/types/templates/decorator.class.spec.template.d.ts +17 -0
  24. package/lib/types/templates/decorator.endpoint.spec.template.d.ts +17 -0
  25. package/lib/types/templates/decorator.method.spec.template.d.ts +17 -0
  26. package/lib/types/templates/decorator.param.spec.template.d.ts +17 -0
  27. package/lib/types/templates/decorator.parameter.spec.template.d.ts +17 -0
  28. package/lib/types/templates/decorator.prop.spec.template.d.ts +17 -0
  29. package/lib/types/templates/decorator.property.spec.template.d.ts +17 -0
  30. package/lib/types/templates/generic.spec.template.d.ts +17 -0
  31. package/lib/types/templates/index.d.ts +11 -0
  32. package/lib/types/templates/jest.config.template.d.ts +16 -0
  33. package/lib/types/templates/server.integration.template.d.ts +17 -0
  34. package/package.json +8 -5
  35. package/src/CliPluginJestModule.ts +39 -0
  36. package/src/hooks/JestGenerateHook.ts +44 -0
  37. package/src/hooks/JestInitHook.ts +22 -0
  38. package/src/index.ts +5 -0
  39. package/src/templates/controller.integration.template.ts +38 -0
  40. package/src/templates/decorator.class.spec.template.ts +25 -0
  41. package/src/templates/decorator.endpoint.spec.template.ts +28 -0
  42. package/src/templates/decorator.method.spec.template.ts +26 -0
  43. package/src/templates/decorator.param.spec.template.ts +28 -0
  44. package/src/templates/decorator.parameter.spec.template.ts +26 -0
  45. package/src/templates/decorator.prop.spec.template.ts +28 -0
  46. package/src/templates/decorator.property.spec.template.ts +27 -0
  47. package/src/templates/generic.spec.template.ts +27 -0
  48. package/src/templates/index.ts +12 -0
  49. package/{templates/init/jest.config.mjs.hbs → src/templates/jest.config.template.ts} +18 -3
  50. package/src/templates/server.integration.template.ts +32 -0
  51. package/tsconfig.esm.json +27 -0
  52. package/vitest.config.mts +21 -0
  53. package/lib/esm/utils/templateDir.js +0 -2
  54. package/lib/types/utils/templateDir.d.ts +0 -1
  55. package/templates/generate/decorator.class.spec.hbs +0 -11
  56. package/templates/generate/decorator.endpoint.spec.hbs +0 -15
  57. package/templates/generate/decorator.method.spec.hbs +0 -13
  58. package/templates/generate/decorator.param.spec.hbs +0 -14
  59. package/templates/generate/decorator.parameter.spec.hbs +0 -12
  60. package/templates/generate/decorator.prop.spec.hbs +0 -15
  61. package/templates/generate/decorator.property.spec.hbs +0 -13
  62. package/templates/generate/generic.integration.hbs +0 -20
  63. package/templates/generate/generic.spec.hbs +0 -14
  64. package/templates/generate/server.integration.hbs +0 -20
@@ -1,4 +1,6 @@
1
1
  import { __decorate, __metadata } from "tslib";
2
+ // Import templates to register them with the DI container
3
+ import "./templates/index.js";
2
4
  import { RuntimesModule } from "@tsed/cli";
3
5
  import { inject, Module, OnAdd, ProjectPackageJson } from "@tsed/cli-core";
4
6
  import { JestGenerateHook } from "./hooks/JestGenerateHook.js";
@@ -1,60 +1,41 @@
1
- import { __decorate, __metadata } from "tslib";
2
- import { SrcRendererService } from "@tsed/cli";
3
- import { inject, Injectable, OnExec } from "@tsed/cli-core";
4
- import { normalizePath } from "@tsed/normalize-path";
5
- import { TEMPLATE_DIR } from "../utils/templateDir.js";
6
- let JestGenerateHook = class JestGenerateHook {
1
+ import { CliProjectService, render } from "@tsed/cli";
2
+ import { inject } from "@tsed/cli-core";
3
+ import { injectable } from "@tsed/di";
4
+ export class JestGenerateHook {
7
5
  constructor() {
8
- this.srcRenderService = inject(SrcRendererService);
6
+ this.projectService = inject(CliProjectService);
9
7
  }
10
- onGenerateExec(ctx) {
11
- const { symbolPath } = ctx;
12
- const { specTemplate, integrationTemplate, relativeSrcPath } = this.mapOptions(ctx);
8
+ $alterGenerateTasks(tasks, data) {
9
+ const { symbolPath } = data;
13
10
  return [
11
+ ...tasks,
14
12
  {
15
- title: `Generate ${ctx.type} spec file to '${symbolPath}.spec.ts'`,
13
+ title: `Generate ${data.type} spec file to '${symbolPath}.spec.ts'`,
16
14
  enabled() {
17
- return !(ctx.type === "server" || ctx.type.includes(":dataSource") || ctx.type.includes(":connection"));
15
+ return !(data.type === "server" || data.type.includes(":dataSource") || data.type.includes(":connection"));
18
16
  },
19
- task: () => this.srcRenderService.render(specTemplate, { ...ctx, relativeSrcPath }, {
20
- output: `${symbolPath}.spec.ts`,
21
- templateDir: TEMPLATE_DIR
22
- })
17
+ task: () => {
18
+ let specTemplateType = [data.type, data.templateType, "spec"].filter(Boolean).join(".");
19
+ specTemplateType = this.projectService.templates.get(specTemplateType) ? specTemplateType : "generic.spec";
20
+ render(specTemplateType, {
21
+ ...data,
22
+ symbolPath: data.symbolPath + ".spec"
23
+ });
24
+ }
23
25
  },
24
26
  {
25
- title: `Generate ${ctx.type} integration file '${symbolPath}.integration.spec.ts'`,
27
+ title: `Generate ${data.type} integration file '${symbolPath}.integration.spec.ts'`,
26
28
  enabled() {
27
- return ["controller", "server"].includes(ctx.type);
29
+ return ["controller", "server"].includes(data.type);
28
30
  },
29
- task: () => this.srcRenderService.render(integrationTemplate, { ...ctx, relativeSrcPath }, {
30
- output: `${symbolPath}.integration.spec.ts`,
31
- templateDir: TEMPLATE_DIR
32
- })
31
+ task: () => {
32
+ render(data.type + ".integration", {
33
+ ...data,
34
+ symbolPath: data.symbolPath + ".integration.spec"
35
+ });
36
+ }
33
37
  }
34
38
  ];
35
39
  }
36
- mapOptions(options) {
37
- const type = [options.type, options.templateType].filter(Boolean).join(".");
38
- const specTemplate = this.srcRenderService.templateExists(`generate/${type}.spec.hbs`, { templateDir: TEMPLATE_DIR })
39
- ? `generate/${type}.spec.hbs`
40
- : "generate/generic.spec.hbs";
41
- const integrationTemplate = this.srcRenderService.templateExists(`generate/${type}.integration.hbs`, { templateDir: TEMPLATE_DIR })
42
- ? `generate/${type}.integration.hbs`
43
- : "generate/generic.integration.hbs";
44
- return {
45
- specTemplate,
46
- integrationTemplate,
47
- relativeSrcPath: normalizePath(this.srcRenderService.relativeFrom(`${options.symbolPath}.integration.spec.ts`))
48
- };
49
- }
50
- };
51
- __decorate([
52
- OnExec("generate"),
53
- __metadata("design:type", Function),
54
- __metadata("design:paramtypes", [Object]),
55
- __metadata("design:returntype", Array)
56
- ], JestGenerateHook.prototype, "onGenerateExec", null);
57
- JestGenerateHook = __decorate([
58
- Injectable()
59
- ], JestGenerateHook);
60
- export { JestGenerateHook };
40
+ }
41
+ injectable(JestGenerateHook);
@@ -1,32 +1,19 @@
1
- import { __decorate, __metadata } from "tslib";
2
- import { RootRendererService } from "@tsed/cli";
3
- import { inject, Injectable, OnExec, ProjectPackageJson } from "@tsed/cli-core";
4
- import { TEMPLATE_DIR } from "../utils/templateDir.js";
5
- let JestInitHook = class JestInitHook {
6
- constructor() {
7
- this.packageJson = inject(ProjectPackageJson);
8
- this.rootRenderer = inject(RootRendererService);
9
- }
10
- onInitExec() {
1
+ import { render } from "@tsed/cli";
2
+ import { injectable } from "@tsed/di";
3
+ export class JestInitHook {
4
+ $alterInitSubTasks(tasks, data) {
11
5
  return [
6
+ ...tasks,
12
7
  {
13
- title: "Generate files for jest",
14
- task: (ctx) => {
15
- return this.rootRenderer.renderAll(["jest.config.ts.hbs"], ctx, {
16
- templateDir: `${TEMPLATE_DIR}/init`
8
+ title: "Create jest configuration",
9
+ enabled: () => !!data.jest,
10
+ task: () => {
11
+ render("jest.config", {
12
+ symbolName: "jest.config"
17
13
  });
18
14
  }
19
15
  }
20
16
  ];
21
17
  }
22
- };
23
- __decorate([
24
- OnExec("init"),
25
- __metadata("design:type", Function),
26
- __metadata("design:paramtypes", []),
27
- __metadata("design:returntype", void 0)
28
- ], JestInitHook.prototype, "onInitExec", null);
29
- JestInitHook = __decorate([
30
- Injectable()
31
- ], JestInitHook);
32
- export { JestInitHook };
18
+ }
19
+ injectable(JestInitHook);
package/lib/esm/index.js CHANGED
@@ -1,3 +1,3 @@
1
1
  import { CliPluginJestModule } from "./CliPluginJestModule.js";
2
- export * from "./utils/templateDir.js";
2
+ export * from "./templates/index.js";
3
3
  export default CliPluginJestModule;
@@ -0,0 +1,35 @@
1
+ import { CliProjectService, defineTemplate } from "@tsed/cli";
2
+ import { inject } from "@tsed/cli-core";
3
+ export default defineTemplate({
4
+ id: "controller.integration",
5
+ label: "Generic Integration Test",
6
+ fileName: "{{symbolName}}.spec",
7
+ outputDir: "{{srcDir}}",
8
+ hidden: true,
9
+ render(symbolName, data) {
10
+ const projectService = inject(CliProjectService);
11
+ const relativePath = projectService.getRelativePath(`${data.symbolPath}.integration.spec.ts`);
12
+ const serverName = projectService.getServerFileName();
13
+ return `import { PlatformTest } from "@tsed/platform-http/testing";
14
+ import SuperTest from "supertest";
15
+ import { ${symbolName} } from "./${data.symbolPathBasename}.js";
16
+ import { Server } from "${relativePath}/${serverName}.js";
17
+
18
+ describe("${symbolName}", () => {
19
+ beforeAll(PlatformTest.bootstrap(Server, {
20
+ mount: {
21
+ "/": [${symbolName}]
22
+ }
23
+ }));
24
+ afterAll(PlatformTest.reset);
25
+
26
+ it("should call GET ${data.route}", async () => {
27
+ const request = SuperTest(PlatformTest.callback());
28
+ const response = await request.get("${data.route}").expect(200);
29
+
30
+ expect(response.text).toEqual("hello");
31
+ });
32
+ });
33
+ `;
34
+ }
35
+ });
@@ -0,0 +1,22 @@
1
+ import { defineTemplate } from "@tsed/cli";
2
+ export default defineTemplate({
3
+ id: "decorator.class.spec",
4
+ label: "Class Decorator Test",
5
+ fileName: "{{symbolName}}.spec",
6
+ outputDir: "{{srcDir}}",
7
+ hidden: true,
8
+ render(symbolName, data) {
9
+ return `import { ${symbolName} } from "./${data.symbolPathBasename}.js";
10
+
11
+ describe("${symbolName}", () => {
12
+ it("should do something", () => {
13
+ @${symbolName}({})
14
+ class Test {
15
+ }
16
+
17
+ expect(typeof ${symbolName}).toBe("function")
18
+ });
19
+ });
20
+ `;
21
+ }
22
+ });
@@ -0,0 +1,26 @@
1
+ import { defineTemplate } from "@tsed/cli";
2
+ export default defineTemplate({
3
+ id: "decorator.endpoint.spec",
4
+ label: "Endpoint Decorator Test",
5
+ fileName: "{{symbolName}}.spec",
6
+ outputDir: "{{srcDir}}",
7
+ hidden: true,
8
+ render(symbolName, data) {
9
+ return `import { Store } from "@tsed/core";
10
+ import { ${symbolName} } from "./${data.symbolPathBasename}.js";
11
+
12
+ describe("${symbolName}", () => {
13
+ it("should store options", () => {
14
+ class Test {
15
+ @${symbolName}({options: "options"})
16
+ method(param: string) {}
17
+ }
18
+
19
+ const store = Store.fromMethod(Test, "method");
20
+
21
+ expect(store.get(${symbolName})).toEqual({options: "options"});
22
+ });
23
+ });
24
+ `;
25
+ }
26
+ });
@@ -0,0 +1,24 @@
1
+ import { defineTemplate } from "@tsed/cli";
2
+ export default defineTemplate({
3
+ id: "decorator.method.spec",
4
+ label: "Method Decorator Test",
5
+ fileName: "{{symbolName}}.spec",
6
+ outputDir: "{{srcDir}}",
7
+ hidden: true,
8
+ render(symbolName, data) {
9
+ return `import { ${symbolName} } from "./${data.symbolPathBasename}.js";
10
+
11
+ describe("${symbolName}", () => {
12
+ it("should do something", () => {
13
+ class Test {
14
+ @${symbolName}({})
15
+ method(){}
16
+ }
17
+
18
+ expect(typeof ${symbolName}).toBe("function")
19
+ expect(typeof ${symbolName}()).toBe("function")
20
+ });
21
+ });
22
+ `;
23
+ }
24
+ });
@@ -0,0 +1,25 @@
1
+ import { defineTemplate } from "@tsed/cli";
2
+ export default defineTemplate({
3
+ id: "decorator.param.spec",
4
+ label: "Parameter Decorator Test",
5
+ fileName: "{{symbolName}}.spec",
6
+ outputDir: "{{srcDir}}",
7
+ hidden: true,
8
+ render(symbolName, data) {
9
+ return `import { Store } from "@tsed/core";
10
+ import { ${symbolName} } from "./${data.symbolPathBasename}.js";
11
+
12
+ describe("${symbolName}", () => {
13
+ it("should store options", () => {
14
+ class Test {
15
+ method(@${symbolName}({options: "options"}) param: string){}
16
+ }
17
+
18
+ const store = Store.from(Test, "method", 0)
19
+
20
+ expect(store.get(${symbolName})).toEqual({options: "options"});
21
+ });
22
+ });
23
+ `;
24
+ }
25
+ });
@@ -0,0 +1,23 @@
1
+ import { defineTemplate } from "@tsed/cli";
2
+ export default defineTemplate({
3
+ id: "decorator.parameter.spec",
4
+ label: "Parameters Decorator Test",
5
+ fileName: "{{symbolName}}.spec",
6
+ outputDir: "{{srcDir}}",
7
+ hidden: true,
8
+ render(symbolName, data) {
9
+ return `import { ${symbolName} } from "./${data.symbolPathBasename}.js";
10
+
11
+ describe("${symbolName}", () => {
12
+ it("should do something", () => {
13
+ class Test {
14
+ method(@${symbolName}({}) param: string){}
15
+ }
16
+
17
+ expect(typeof ${symbolName}).toBe("function")
18
+ expect(typeof ${symbolName}()).toBe("function")
19
+ });
20
+ });
21
+ `;
22
+ }
23
+ });
@@ -0,0 +1,26 @@
1
+ import { defineTemplate } from "@tsed/cli";
2
+ export default defineTemplate({
3
+ id: "decorator.prop.spec",
4
+ label: "Property Decorator with @Property Test",
5
+ fileName: "{{symbolName}}.spec",
6
+ outputDir: "{{srcDir}}",
7
+ hidden: true,
8
+ render(symbolName, data) {
9
+ return `import { Store } from "@tsed/core";
10
+ import { ${symbolName} } from "./${data.symbolPathBasename}.js";
11
+
12
+ describe("${symbolName}", () => {
13
+ it("should store options", () => {
14
+ class Test {
15
+ @${symbolName}({options: "options"})
16
+ property: string;
17
+ }
18
+
19
+ const store = Store.from(Test, "property");
20
+
21
+ expect(store.get(${symbolName})).toEqual({options: "options"});
22
+ });
23
+ });
24
+ `;
25
+ }
26
+ });
@@ -0,0 +1,24 @@
1
+ import { defineTemplate } from "@tsed/cli";
2
+ export default defineTemplate({
3
+ id: "decorator.property.spec",
4
+ label: "Property Decorator Test",
5
+ fileName: "{{symbolName}}.spec",
6
+ outputDir: "{{srcDir}}",
7
+ hidden: true,
8
+ render(symbolName, data) {
9
+ return `import { ${symbolName} } from "./${data.symbolPathBasename}.js";
10
+
11
+ describe("${symbolName}", () => {
12
+ it("should do something", () => {
13
+ class Test {
14
+ @${symbolName}({})
15
+ property: string;
16
+ }
17
+
18
+ expect(typeof ${symbolName}).toBe("function")
19
+ expect(typeof ${symbolName}()).toBe("function")
20
+ });
21
+ });
22
+ `;
23
+ }
24
+ });
@@ -0,0 +1,25 @@
1
+ import { defineTemplate } from "@tsed/cli";
2
+ export default defineTemplate({
3
+ id: "generic.spec",
4
+ label: "Generic Spec",
5
+ fileName: "{{symbolName}}.spec",
6
+ outputDir: "{{srcDir}}",
7
+ hidden: true,
8
+ render(symbolName, data) {
9
+ return `import { PlatformTest, inject } from "@tsed/platform-http/testing";
10
+ import { ${symbolName} } from "./${data.symbolPathBasename}.js";
11
+
12
+ describe("${symbolName}", () => {
13
+ beforeEach(PlatformTest.create);
14
+ afterEach(PlatformTest.reset);
15
+
16
+ it("should do something", () => {
17
+ const instance = inject(${symbolName});
18
+ // const instance = PlatformTest.invoke<${symbolName}>(${symbolName}); // get fresh instance
19
+
20
+ expect(instance).toBeInstanceOf(${symbolName});
21
+ });
22
+ });
23
+ `;
24
+ }
25
+ });
@@ -0,0 +1,12 @@
1
+ // Import all templates to register them with the DI container
2
+ import "./decorator.class.spec.template.js";
3
+ import "./decorator.endpoint.spec.template.js";
4
+ import "./decorator.method.spec.template.js";
5
+ import "./decorator.param.spec.template.js";
6
+ import "./decorator.parameter.spec.template.js";
7
+ import "./decorator.prop.spec.template.js";
8
+ import "./decorator.property.spec.template.js";
9
+ import "./controller.integration.template.js";
10
+ import "./generic.spec.template.js";
11
+ import "./jest.config.template.js";
12
+ import "./server.integration.template.js";
@@ -0,0 +1,84 @@
1
+ import { defineTemplate } from "@tsed/cli";
2
+ export default defineTemplate({
3
+ id: "jest.config",
4
+ label: "Jest Config",
5
+ fileName: "jest.config",
6
+ ext: "mjs",
7
+ outputDir: ".",
8
+ hidden: true,
9
+ preserveCase: true,
10
+ render() {
11
+ return `// For a detailed explanation regarding each configuration property, visit:
12
+ // https://jestjs.io/docs/en/configuration.html
13
+
14
+ /** @type {import('jest').Config} */
15
+ export default {
16
+ // Automatically clear mock calls and instances between every test
17
+ clearMocks: true,
18
+
19
+ // Indicates whether the coverage information should be collected while executing the test
20
+ collectCoverage: true,
21
+
22
+ // An array of glob patterns indicating a set of files for which coverage information should be collected
23
+ // collectCoverageFrom: undefined,
24
+
25
+ // The directory where Jest should output its coverage files
26
+ coverageDirectory: "coverage",
27
+
28
+ // An array of regexp pattern strings used to skip coverage collection
29
+ coveragePathIgnorePatterns: ["index.ts", "/node_modules/"],
30
+
31
+ // An object that configures minimum threshold enforcement for coverage results
32
+ coverageThreshold: {
33
+ global: {
34
+ branches: 70,
35
+ functions: 70,
36
+ lines: 70,
37
+ statements: 70
38
+ }
39
+ },
40
+
41
+ // An array of file extensions your modules use
42
+ moduleFileExtensions: ["js", "json", "jsx", "ts", "tsx", "node"],
43
+ extensionsToTreatAsEsm: [".ts", ".tsx"],
44
+ // The test environment that will be used for testing
45
+ testEnvironment: "node",
46
+
47
+ // The glob patterns Jest uses to detect test files
48
+ testMatch: ["**/src/**/__tests__/**/*.[jt]s?(x)", "**/src/**/?(*.)+(spec|test).[tj]s?(x)"],
49
+ // A map from regular expressions to paths to transformers
50
+ transform: {
51
+ "^.+\\\\.(j|t)sx?$": [
52
+ "@swc/jest",
53
+ {
54
+ jsc: {
55
+ parser: {
56
+ syntax: "typescript",
57
+ tsx: true,
58
+ decorators: true,
59
+ dynamicImport: true,
60
+ importMeta: true,
61
+ preserveAllComments: true
62
+ },
63
+ target: "esnext",
64
+ transform: {
65
+ useDefineForClassFields: false,
66
+ legacyDecorator: true,
67
+ decoratorMetadata: true
68
+ }
69
+ },
70
+ module: {
71
+ type: "es6"
72
+ }
73
+ }
74
+ ]
75
+ },
76
+ moduleNameMapper: {
77
+ "^(\\\\.{1,2}/.*)\\\\.js$": "$1"
78
+ },
79
+ testPathIgnorePatterns: ["/node_modules/", "/dist/"],
80
+ transformIgnorePatterns: ["/node_modules/(?!(module-name|another-module)/)"]
81
+ };
82
+ `;
83
+ }
84
+ });
@@ -0,0 +1,30 @@
1
+ import { defineTemplate } from "@tsed/cli";
2
+ export default defineTemplate({
3
+ id: "server.integration",
4
+ label: "Server Integration Test",
5
+ outputDir: "{{srcDir}}",
6
+ hidden: true,
7
+ render(symbolName, data) {
8
+ return `import { PlatformTest } from "@tsed/platform-http/testing";
9
+ import SuperTest from "supertest";
10
+ import { ${symbolName} } from "./${data.symbolPathBasename}.js";
11
+
12
+ describe("${symbolName}", () => {
13
+ beforeAll(PlatformTest.bootstrap(${symbolName}));
14
+ afterAll(PlatformTest.reset);
15
+
16
+ it("should call GET ${data.route}", async () => {
17
+ const request = SuperTest(PlatformTest.callback());
18
+ const response = await request.get("${data.route}").expect(404);
19
+
20
+ expect(response.body).toEqual({
21
+ errors: [],
22
+ message: 'Resource "/rest" not found',
23
+ name: "NOT_FOUND",
24
+ status: 404,
25
+ });
26
+ });
27
+ });
28
+ `;
29
+ }
30
+ });