adorn-api 1.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 (50) hide show
  1. package/README.md +249 -0
  2. package/dist/cli/generate-routes.js +101 -0
  3. package/dist/cli/generate-swagger.js +197 -0
  4. package/dist/controllers/advanced.controller.js +131 -0
  5. package/dist/controllers/user.controller.js +121 -0
  6. package/dist/entities/user.entity.js +1 -0
  7. package/dist/index.js +2 -0
  8. package/dist/lib/common.js +62 -0
  9. package/dist/lib/decorators.js +116 -0
  10. package/dist/middleware/auth.middleware.js +13 -0
  11. package/dist/routes.js +80 -0
  12. package/dist/server.js +18 -0
  13. package/dist/src/cli/generate-routes.js +105 -0
  14. package/dist/src/cli/generate-swagger.js +197 -0
  15. package/dist/src/index.js +4 -0
  16. package/dist/src/lib/common.js +62 -0
  17. package/dist/src/lib/decorators.js +116 -0
  18. package/dist/src/routes.js +80 -0
  19. package/dist/src/server.js +18 -0
  20. package/dist/tests/example-app/controllers/advanced.controller.js +130 -0
  21. package/dist/tests/example-app/controllers/controllers/advanced.controller.js +131 -0
  22. package/dist/tests/example-app/controllers/controllers/user.controller.js +121 -0
  23. package/dist/tests/example-app/controllers/user.controller.js +121 -0
  24. package/dist/tests/example-app/entities/entities/user.entity.js +1 -0
  25. package/dist/tests/example-app/entities/user.entity.js +1 -0
  26. package/dist/tests/example-app/middleware/auth.middleware.js +13 -0
  27. package/dist/tests/example-app/middleware/middleware/auth.middleware.js +13 -0
  28. package/dist/tests/example-app/routes.js +80 -0
  29. package/dist/tests/example-app/server.js +23 -0
  30. package/package.json +34 -0
  31. package/scripts/run-example.js +32 -0
  32. package/src/cli/generate-routes.ts +123 -0
  33. package/src/cli/generate-swagger.ts +216 -0
  34. package/src/index.js +20 -0
  35. package/src/index.ts +4 -0
  36. package/src/lib/common.js +68 -0
  37. package/src/lib/common.ts +35 -0
  38. package/src/lib/decorators.js +128 -0
  39. package/src/lib/decorators.ts +136 -0
  40. package/swagger.json +238 -0
  41. package/tests/e2e.test.ts +72 -0
  42. package/tests/example-app/controllers/advanced.controller.ts +52 -0
  43. package/tests/example-app/controllers/user.controller.ts +35 -0
  44. package/tests/example-app/entities/user.entity.ts +8 -0
  45. package/tests/example-app/middleware/auth.middleware.ts +16 -0
  46. package/tests/example-app/routes.ts +102 -0
  47. package/tests/example-app/server.ts +30 -0
  48. package/tests/generators.test.ts +48 -0
  49. package/tests/utils.ts +46 -0
  50. package/tsconfig.json +20 -0
@@ -0,0 +1,48 @@
1
+ import { describe, expect, it } from "vitest";
2
+ import { readFile } from "node:fs/promises";
3
+ import path from "node:path";
4
+ import { projectRoot, runTsNodeScript } from "./utils.js";
5
+
6
+ describe("adorn-api generators", () => {
7
+ it("writes swagger.json with expected routes", async () => {
8
+ await runTsNodeScript("src/cli/generate-swagger.ts");
9
+ const swaggerPath = path.join(projectRoot, "swagger.json");
10
+ const swagger = JSON.parse(await readFile(swaggerPath, "utf-8"));
11
+
12
+ expect(swagger.openapi).toBe("3.0.0");
13
+ expect(Object.keys(swagger.paths)).toEqual(
14
+ expect.arrayContaining([
15
+ "/users/{userId}",
16
+ "/users/",
17
+ "/advanced/{tenantId}/users",
18
+ "/advanced/",
19
+ ])
20
+ );
21
+
22
+ const userGet = swagger.paths["/users/{userId}"]?.get;
23
+ expect(userGet?.operationId).toBe("getUser");
24
+
25
+ const advancedGet = swagger.paths["/advanced/{tenantId}/users"]?.get;
26
+ const hasTenantId = advancedGet?.parameters?.some(
27
+ (param: { name: string; in: string }) =>
28
+ param.name === "tenantId" && param.in === "path"
29
+ );
30
+ expect(hasTenantId).toBe(true);
31
+ });
32
+
33
+ it("writes express routes from controllers", async () => {
34
+ await runTsNodeScript("src/cli/generate-routes.ts");
35
+ const routesPath = path.join(
36
+ projectRoot,
37
+ "tests",
38
+ "example-app",
39
+ "routes.ts"
40
+ );
41
+ const routes = await readFile(routesPath, "utf-8");
42
+
43
+ expect(routes).toContain("RegisterRoutes");
44
+ expect(routes).toContain("app.get('/users/:userId'");
45
+ expect(routes).toContain("app.post('/users/'");
46
+ expect(routes).toContain("new UserController()");
47
+ });
48
+ });
package/tests/utils.ts ADDED
@@ -0,0 +1,46 @@
1
+ import { spawn } from "node:child_process";
2
+ import path from "node:path";
3
+ import { fileURLToPath, pathToFileURL } from "node:url";
4
+
5
+ const __filename = fileURLToPath(import.meta.url);
6
+ const __dirname = path.dirname(__filename);
7
+
8
+ export const projectRoot = path.resolve(__dirname, "..");
9
+ const tsNodeLoader = pathToFileURL(
10
+ path.join(projectRoot, "node_modules", "ts-node", "esm.mjs")
11
+ ).toString();
12
+
13
+ export const tsNodeEnv = {
14
+ ...process.env,
15
+ TS_NODE_PROJECT: path.join(projectRoot, "tsconfig.json"),
16
+ TS_NODE_PREFER_TS_EXTS: "true",
17
+ };
18
+
19
+ export function runTsNodeScript(relativePath: string, args: string[] = []) {
20
+ return new Promise<void>((resolve, reject) => {
21
+ const scriptPath = path.join(projectRoot, relativePath);
22
+ const child = spawn(
23
+ process.execPath,
24
+ ["--loader", tsNodeLoader, scriptPath, ...args],
25
+ {
26
+ cwd: projectRoot,
27
+ env: tsNodeEnv,
28
+ stdio: ["ignore", "pipe", "pipe"],
29
+ }
30
+ );
31
+
32
+ let stderr = "";
33
+ child.stderr.on("data", (chunk) => {
34
+ stderr += chunk.toString();
35
+ });
36
+
37
+ child.on("error", reject);
38
+ child.on("exit", (code) => {
39
+ if (code === 0) {
40
+ resolve();
41
+ return;
42
+ }
43
+ reject(new Error(`Failed to run ${relativePath}\n${stderr}`));
44
+ });
45
+ });
46
+ }
package/tsconfig.json ADDED
@@ -0,0 +1,20 @@
1
+ {
2
+ "compilerOptions": {
3
+ "target": "ES2022",
4
+ "module": "NodeNext",
5
+ "moduleResolution": "NodeNext",
6
+ "strict": true,
7
+ "outDir": "./dist",
8
+ "rootDir": ".",
9
+ // "experimentalDecorators": false, <--- ENSURE THIS IS FALSE OR OMITTED
10
+ "emitDecoratorMetadata": false // Standard decorators don't use this
11
+ },
12
+ "include": [
13
+ "src/**/*",
14
+ "tests/**/*"
15
+ ],
16
+ "ts-node": {
17
+ "preferTsExts": true,
18
+ "esm": true
19
+ }
20
+ }