create-nwire 0.9.2 → 0.10.1

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 (38) hide show
  1. package/README.md +7 -8
  2. package/dist/index.d.ts +0 -1
  3. package/dist/index.js +0 -1
  4. package/package.json +1 -1
  5. package/templates/enterprise/__tests__/auto-moderate.test.ts +6 -14
  6. package/templates/enterprise/__tests__/submit-flow.test.ts +6 -14
  7. package/templates/enterprise/app/api.ts +11 -18
  8. package/templates/enterprise/app/app.ts +37 -21
  9. package/templates/enterprise/app/main.ts +40 -21
  10. package/templates/enterprise/modules/posts/routes/approve-post.ts +10 -6
  11. package/templates/enterprise/modules/posts/routes/get-post.ts +8 -4
  12. package/templates/enterprise/modules/posts/routes/list-queue.ts +12 -6
  13. package/templates/enterprise/modules/posts/routes/reject-post.ts +8 -4
  14. package/templates/enterprise/modules/posts/routes/submit-post.ts +9 -9
  15. package/templates/enterprise/package.json +7 -6
  16. package/templates/minimal/__tests__/hello.test.ts +19 -15
  17. package/templates/minimal/app/api.ts +11 -14
  18. package/templates/minimal/app/main.ts +26 -15
  19. package/templates/minimal/app/routes/hello.ts +6 -13
  20. package/templates/minimal/package.json +4 -2
  21. package/templates/service/README.md +1 -1
  22. package/templates/service/__tests__/todo-api.test.ts +21 -20
  23. package/templates/service/app/api.ts +11 -20
  24. package/templates/service/app/main.ts +31 -20
  25. package/templates/service/app/middleware/require-user.ts +10 -11
  26. package/templates/service/app/routes/complete-todo.ts +8 -11
  27. package/templates/service/app/routes/create-todo.ts +9 -10
  28. package/templates/service/app/routes/delete-todo.ts +9 -9
  29. package/templates/service/app/routes/list-todos.ts +8 -11
  30. package/templates/service/app/store/todo-store.ts +3 -3
  31. package/templates/service/package.json +7 -5
  32. package/dist/__tests__/scaffold.test.d.ts +0 -7
  33. package/dist/__tests__/scaffold.test.d.ts.map +0 -1
  34. package/dist/__tests__/scaffold.test.js +0 -113
  35. package/dist/__tests__/scaffold.test.js.map +0 -1
  36. package/dist/index.d.ts.map +0 -1
  37. package/dist/index.js.map +0 -1
  38. package/templates/enterprise/modules/posts/posts.module.ts +0 -36
@@ -1,21 +1,14 @@
1
1
  /**
2
2
  * POST /hello — Zod-validated body, typed handler return.
3
3
  *
4
- * The shape every route file follows:
4
+ * Every route file exports a `{name}Route` (the binding) and a
5
+ * `{name}Handler` (the function). `api.ts` pairs them in the `wires`
6
+ * array.
5
7
  *
6
- * - `{name}Route` — the `post(path, schema)` binding
7
- * - `{name}Handler` — the `async ({ input }) => ...` handler
8
- *
9
- * `api.ts` wires them with `.wire(helloRoute, helloHandler)`.
10
- *
11
- * The framework converts the Zod schema into OpenAPI on boot — visit
12
- * `/openapi.json` or the Scalar UI at `/docs` to see it.
13
- *
14
- * To add a route, copy this file, rename, then `.wire()` the new pair
15
- * from `api.ts`.
8
+ * Add a route: copy this file, rename, then add an entry in `api.ts`.
16
9
  */
17
10
 
18
- import { post, type HttpHandler } from "@nwire/http";
11
+ import { post } from "@nwire/wires/http";
19
12
  import { z } from "zod";
20
13
 
21
14
  const HelloBody = z.object({
@@ -24,6 +17,6 @@ const HelloBody = z.object({
24
17
 
25
18
  export const helloRoute = post("/hello", { body: HelloBody });
26
19
 
27
- export const helloHandler: HttpHandler<z.infer<typeof HelloBody>> = async ({ input }) => {
20
+ export const helloHandler = async (input: z.infer<typeof HelloBody>) => {
28
21
  return { message: `Hello, ${input.name}!` };
29
22
  };
@@ -8,8 +8,10 @@
8
8
  "test": "vitest run"
9
9
  },
10
10
  "dependencies": {
11
- "@nwire/endpoint": "^0.9.2",
12
- "@nwire/http": "^0.9.2",
11
+ "@nwire/app": "^0.10.1",
12
+ "@nwire/endpoint": "^0.10.1",
13
+ "@nwire/wires": "^0.10.1",
14
+ "@nwire/koa": "^0.10.1",
13
15
  "zod": "^4.0.0"
14
16
  },
15
17
  "devDependencies": {
@@ -63,7 +63,7 @@ curl -X POST http://localhost:3000/api/todos/<id>/complete \
63
63
  | A new error type | `app/errors/<resource>-errors.ts` — `defineError({ code, status, summary })` |
64
64
  | A new middleware | `app/middleware/<name>.ts` exports `HttpMiddleware`; `.use()` it from `api.ts` |
65
65
  | A new resource | `app/resources/<name>.ts` — `defineResource` schema + `public` field list |
66
- | Real persistence | Swap `app/store/todo-store.ts` for `@nwire/data-drizzle` or `@nwire/store-mongo` |
66
+ | Real persistence | Swap `app/store/todo-store.ts` for `@nwire/drizzle` or `@nwire/mongo` |
67
67
 
68
68
  ## Grow up
69
69
 
@@ -1,36 +1,37 @@
1
1
  /**
2
2
  * Smoke test — the four CRUD operations + the requireUser middleware.
3
3
  *
4
- * Boots the api against a real Node http server, registers a fresh
5
- * in-memory TodoStore on a container, and dispatches fetch requests
6
- * exactly the way clients will.
4
+ * Boots the app under httpKoa against an ephemeral port and dispatches
5
+ * fetch requests exactly the way clients will.
7
6
  */
8
7
 
9
8
  import { describe, it, expect, beforeAll, afterAll } from "vitest";
10
- import http from "node:http";
11
- import type { Server } from "node:http";
12
- import { createContainer } from "@nwire/container";
13
- import { TodoStore } from "../app/store/todo-store";
14
- import { api } from "../app/api";
9
+ import { endpoint } from "@nwire/endpoint";
10
+ import { httpKoa } from "@nwire/koa";
11
+ import { buildApp } from "../app/main";
12
+ import { requireUser } from "../app/middleware/require-user";
15
13
 
16
- let server: Server;
14
+ let running: Awaited<ReturnType<ReturnType<typeof endpoint>["run"]>>;
15
+ let app: ReturnType<typeof buildApp>;
17
16
  let url: string;
18
17
 
19
18
  beforeAll(async () => {
20
- const container = createContainer();
21
- container.register("todos", new TodoStore());
22
- api.provide(container);
23
-
24
- server = http.createServer(api.compile());
25
- await new Promise<void>((resolve) => server.listen(0, "127.0.0.1", resolve));
26
- const addr = server.address() as { port: number };
27
- url = `http://127.0.0.1:${addr.port}`;
19
+ app = buildApp();
20
+ const koa = httpKoa({ port: 0, prefix: "/api", middleware: [requireUser] });
21
+ running = await endpoint("todo-test", {
22
+ exitOnShutdown: false,
23
+ banner: false,
24
+ probes: { enabled: false },
25
+ })
26
+ .use(koa)
27
+ .mount(app)
28
+ .run();
29
+ url = `http://127.0.0.1:${koa.port()}`;
28
30
  });
29
31
 
30
32
  afterAll(async () => {
31
- await new Promise<void>((resolve, reject) =>
32
- server.close((err) => (err ? reject(err) : resolve())),
33
- );
33
+ await running.shutdown("test");
34
+ await app.stop();
34
35
  });
35
36
 
36
37
  async function req(
@@ -1,30 +1,21 @@
1
1
  /**
2
- * HTTP interface — the surface this app exposes.
2
+ * Wires — the surface this app exposes.
3
3
  *
4
- * One `.wire(Route, Handler)` line per route. To add a new route, drop a
5
- * file under `./routes/` exporting `{name}Route + {name}Handler`, then
6
- * `.wire()` it in here.
4
+ * Each route file under `./routes/` exports a `{name}Route` (binding) +
5
+ * `{name}Handler` (function). `wires` is the flat array `main.ts` feeds
6
+ * into `app.wire(...)`.
7
7
  *
8
- * Each route's verb + path + schema + handler live in one file under
9
- * `./routes/`. The interface stays a 1-line-per-route reducer — easy to
10
- * audit, easy to grep, no second config file.
11
- *
12
- * Cross-cutting:
13
- * - `requireUser` middleware runs before EVERY route (chained once here).
14
- * - `.provide(container)` is wired by `main.ts` with the todo store.
8
+ * Adding a route = one new file + one entry in this array.
15
9
  */
16
10
 
17
- import { httpInterface } from "@nwire/http";
18
- import { requireUser } from "./middleware/require-user";
19
-
20
11
  import { listTodosRoute, listTodosHandler } from "./routes/list-todos";
21
12
  import { createTodoRoute, createTodoHandler } from "./routes/create-todo";
22
13
  import { completeTodoRoute, completeTodoHandler } from "./routes/complete-todo";
23
14
  import { deleteTodoRoute, deleteTodoHandler } from "./routes/delete-todo";
24
15
 
25
- export const api = httpInterface({ prefix: "/api" })
26
- .use(requireUser)
27
- .wire(listTodosRoute, listTodosHandler)
28
- .wire(createTodoRoute, createTodoHandler)
29
- .wire(completeTodoRoute, completeTodoHandler)
30
- .wire(deleteTodoRoute, deleteTodoHandler);
16
+ export const wires = [
17
+ { binding: listTodosRoute, handler: listTodosHandler },
18
+ { binding: createTodoRoute, handler: createTodoHandler },
19
+ { binding: completeTodoRoute, handler: completeTodoHandler },
20
+ { binding: deleteTodoRoute, handler: deleteTodoHandler },
21
+ ] as const;
@@ -1,35 +1,46 @@
1
1
  /**
2
- * Entry point wire the store into the http interface, then run.
2
+ * Entry — boot the app under HTTP.
3
3
  *
4
- * The shape for Level 2:
5
- *
6
- * 1. Build an in-memory container, register the store on it.
7
- * 2. Hand it to the http interface via `.provide()` — route handlers
8
- * read it with `resolve<TodoStore>("todos")`.
9
- * 3. Wrap in `endpoint()` for graceful shutdown + K8s probes.
10
- *
11
- * No `createApp` here. With ONE binding and zero plugin lifecycle work,
12
- * createApp adds ceremony without value. The L4 template (and the
13
- * station-management example) show the full createApp + plugin shape
14
- * with many bindings and framework events; L2 doesn't need it.
4
+ * 1. createApp registers the TodoStore on the container via a plugin.
5
+ * 2. app.wire(...) pairs every route binding with its handler.
6
+ * 3. endpoint().use(httpKoa({middleware:[requireUser]})).mount(app).run()
7
+ * runs the HTTP adopter under graceful drain + K8s probes.
15
8
  *
16
9
  * Run: pnpm dev
17
10
  * Try: curl -X POST http://localhost:3000/api/todos \
18
11
  * -H "content-type: application/json" \
19
12
  * -H "x-user-id: alice" \
20
13
  * -d '{"text":"buy milk"}'
21
- *
22
14
  * curl -H "x-user-id: alice" http://localhost:3000/api/todos
23
15
  */
24
16
 
17
+ import { createApp, definePlugin } from "@nwire/app";
25
18
  import { endpoint } from "@nwire/endpoint";
26
- import { createContainer } from "@nwire/container";
27
- import { TodoStore } from "./store/todo-store";
28
- import { api } from "./api";
19
+ import { httpKoa } from "@nwire/koa";
29
20
 
30
- const container = createContainer();
31
- container.register("todos", new TodoStore());
21
+ import { wires } from "./api";
22
+ import { requireUser } from "./middleware/require-user";
23
+ import { TodoStore } from "./store/todo-store";
32
24
 
33
- api.provide(container);
25
+ export function buildApp() {
26
+ const app = createApp({
27
+ appName: "{{PROJECT_NAME}}",
28
+ plugins: [
29
+ definePlugin("todo-store", ({ bind }) => {
30
+ bind("todos", new TodoStore());
31
+ }),
32
+ ],
33
+ });
34
+ for (const { binding, handler } of wires) {
35
+ app.wire(binding, handler);
36
+ }
37
+ return app;
38
+ }
34
39
 
35
- await endpoint("{{PROJECT_NAME}}", { port: 3000 }).serve(api).run();
40
+ if (import.meta.url === `file://${process.argv[1]}`) {
41
+ const app = buildApp();
42
+ await endpoint("{{PROJECT_NAME}}", { port: 3000 })
43
+ .use(httpKoa({ prefix: "/api", middleware: [requireUser] }))
44
+ .mount(app)
45
+ .run();
46
+ }
@@ -2,24 +2,23 @@
2
2
  * `requireUser` — tiny auth shim that proves the middleware-chain pattern.
3
3
  *
4
4
  * A real app would use `@nwire/auth` + an IdP adapter (Logto, better-auth,
5
- * etc.) to extract `user` from a JWT in the Authorization header. For this
6
- * template we trust the `x-user-id` header so the test suite stays focused
7
- * on the framework shape, not on JWT handling.
8
- *
9
- * The middleware does two things:
5
+ * etc.) to extract `user` from a JWT. For this template we trust the
6
+ * `x-user-id` header so the test suite stays focused on the framework
7
+ * shape, not on JWT handling.
10
8
  *
9
+ * The middleware:
11
10
  * 1. Throws `NoUserId` if the header is absent — surfaces as 401 JSON.
12
- * 2. Attaches the user id to Koa state so handlers can read it without
13
- * re-parsing the request.
11
+ * 2. Attaches the user id to Koa state so handlers can read it via
12
+ * ctx.koa.state.userId.
14
13
  *
15
- * Routes chain it once via `.use(requireUser)` in `api.ts`; auth lives at
16
- * the interface seam, not inside business logic.
14
+ * Adopter-wide registration in `main.ts`:
15
+ * httpKoa({ middleware: [requireUser] })
17
16
  */
18
17
 
19
- import type { HttpMiddleware } from "@nwire/http";
18
+ import type Koa from "koa";
20
19
  import { NoUserId } from "../errors/todo-errors";
21
20
 
22
- export const requireUser: HttpMiddleware = async (ctx, next) => {
21
+ export const requireUser: Koa.Middleware = async (ctx, next) => {
23
22
  const userId = ctx.request.headers["x-user-id"];
24
23
  if (typeof userId !== "string" || userId.length === 0) {
25
24
  throw NoUserId;
@@ -2,14 +2,12 @@
2
2
  * POST /api/todos/:id/complete — mark a todo done.
3
3
  *
4
4
  * Two negative cases mapped to typed errors:
5
- *
6
5
  * - Todo doesn't exist OR belongs to another user → `TodoNotFound` (404)
7
6
  * - Todo already completed → `TodoAlreadyCompleted` (409)
8
- *
9
- * Throwing typed errors keeps the handler readable; transport translates.
10
7
  */
11
8
 
12
- import { post, type HttpHandler } from "@nwire/http";
9
+ import { post } from "@nwire/wires/http";
10
+ import type Koa from "koa";
13
11
  import { z } from "zod";
14
12
  import { TodoStore } from "../store/todo-store";
15
13
  import { project } from "../resources/todo";
@@ -19,13 +17,12 @@ const Params = z.object({ id: z.string() });
19
17
 
20
18
  export const completeTodoRoute = post("/todos/:id/complete", { params: Params });
21
19
 
22
- export const completeTodoHandler: HttpHandler<z.infer<typeof Params>> = async ({
23
- input,
24
- resolve,
25
- _raw,
26
- }) => {
27
- const store = resolve<TodoStore>("todos");
28
- const userId = _raw.state.userId as string;
20
+ export const completeTodoHandler = async (
21
+ input: z.infer<typeof Params>,
22
+ ctx: { resolve: <T>(name: string) => T; koa: Koa.ParameterizedContext },
23
+ ) => {
24
+ const store = ctx.resolve<TodoStore>("todos");
25
+ const userId = ctx.koa.state.userId as string;
29
26
 
30
27
  const existing = store.get(input.id);
31
28
  if (!existing || existing.userId !== userId) throw TodoNotFound;
@@ -2,11 +2,11 @@
2
2
  * POST /api/todos — add a new todo to the caller's list.
3
3
  *
4
4
  * Returns 201 + the new todo. The handler reads `userId` from Koa state
5
- * (set by `requireUser` middleware) and the store from the request-scoped
6
- * container.
5
+ * (set by `requireUser` middleware) and the store from the container.
7
6
  */
8
7
 
9
- import { post, type HttpHandler } from "@nwire/http";
8
+ import { post } from "@nwire/wires/http";
9
+ import type Koa from "koa";
10
10
  import { z } from "zod";
11
11
  import { TodoStore } from "../store/todo-store";
12
12
  import { project } from "../resources/todo";
@@ -15,13 +15,12 @@ const Body = z.object({ text: z.string().min(1).max(500) });
15
15
 
16
16
  export const createTodoRoute = post("/todos", { body: Body });
17
17
 
18
- export const createTodoHandler: HttpHandler<z.infer<typeof Body>> = async ({
19
- input,
20
- resolve,
21
- _raw,
22
- }) => {
23
- const store = resolve<TodoStore>("todos");
24
- const userId = _raw.state.userId as string;
18
+ export const createTodoHandler = async (
19
+ input: z.infer<typeof Body>,
20
+ ctx: { resolve: <T>(name: string) => T; koa: Koa.ParameterizedContext },
21
+ ) => {
22
+ const store = ctx.resolve<TodoStore>("todos");
23
+ const userId = ctx.koa.state.userId as string;
25
24
  const todo = store.add({ userId, text: input.text });
26
25
  return { $status: 201, body: project(todo) };
27
26
  };
@@ -6,7 +6,8 @@
6
6
  * "doesn't exist", that's an information-disclosure vector.
7
7
  */
8
8
 
9
- import { del, type HttpHandler } from "@nwire/http";
9
+ import { del } from "@nwire/wires/http";
10
+ import type Koa from "koa";
10
11
  import { z } from "zod";
11
12
  import { TodoStore } from "../store/todo-store";
12
13
  import { TodoNotFound } from "../errors/todo-errors";
@@ -15,17 +16,16 @@ const Params = z.object({ id: z.string() });
15
16
 
16
17
  export const deleteTodoRoute = del("/todos/:id", { params: Params });
17
18
 
18
- export const deleteTodoHandler: HttpHandler<z.infer<typeof Params>> = async ({
19
- input,
20
- resolve,
21
- _raw,
22
- }) => {
23
- const store = resolve<TodoStore>("todos");
24
- const userId = _raw.state.userId as string;
19
+ export const deleteTodoHandler = async (
20
+ input: z.infer<typeof Params>,
21
+ ctx: { resolve: <T>(name: string) => T; koa: Koa.ParameterizedContext },
22
+ ) => {
23
+ const store = ctx.resolve<TodoStore>("todos");
24
+ const userId = ctx.koa.state.userId as string;
25
25
 
26
26
  const existing = store.get(input.id);
27
27
  if (!existing || existing.userId !== userId) throw TodoNotFound;
28
28
 
29
29
  store.remove(input.id);
30
- return null; // → 204 No Content
30
+ return undefined; // → 204 No Content (koa.status defaults to 204 on undefined)
31
31
  };
@@ -1,11 +1,9 @@
1
1
  /**
2
2
  * GET /api/todos — list the caller's todos, optionally filtered by status.
3
- *
4
- * Returns `{ items, total }`. The store sorts so open-first by added-at;
5
- * the handler just projects the records and counts.
6
3
  */
7
4
 
8
- import { get, type HttpHandler } from "@nwire/http";
5
+ import { get } from "@nwire/wires/http";
6
+ import type Koa from "koa";
9
7
  import { z } from "zod";
10
8
  import { TodoStore } from "../store/todo-store";
11
9
  import { project } from "../resources/todo";
@@ -16,13 +14,12 @@ const Query = z.object({
16
14
 
17
15
  export const listTodosRoute = get("/todos", { query: Query });
18
16
 
19
- export const listTodosHandler: HttpHandler<z.infer<typeof Query>> = async ({
20
- input,
21
- resolve,
22
- _raw,
23
- }) => {
24
- const store = resolve<TodoStore>("todos");
25
- const userId = _raw.state.userId as string;
17
+ export const listTodosHandler = async (
18
+ input: z.infer<typeof Query>,
19
+ ctx: { resolve: <T>(name: string) => T; koa: Koa.ParameterizedContext },
20
+ ) => {
21
+ const store = ctx.resolve<TodoStore>("todos");
22
+ const userId = ctx.koa.state.userId as string;
26
23
  const list = store.listByUser(userId, input.status);
27
24
  return { items: list.map(project), total: list.length };
28
25
  };
@@ -9,8 +9,8 @@
9
9
  * store on the container under the name "todos" and tears it down
10
10
  * on graceful shutdown.
11
11
  *
12
- * In a real app you'd swap the store for `@nwire/data-drizzle` against
13
- * Postgres or `@nwire/store-mongo` against Mongo. The PLUGIN shape stays
12
+ * In a real app you'd swap the store for `@nwire/drizzle` against
13
+ * Postgres or `@nwire/mongo` against Mongo. The PLUGIN shape stays
14
14
  * the same — `provide("todos", { boot, shutdown })`. Handlers always do
15
15
  * `resolve("todos")` and get whatever the plugin booted.
16
16
  *
@@ -123,7 +123,7 @@ export const todoStorePlugin = definePlugin("todos", ({ provide }) => {
123
123
  },
124
124
  healthCheck: (store) => {
125
125
  // Trivial — proves the store is alive. A real adapter would
126
- // SELECT 1 against the DB. Lightship calls this on every /readyz.
126
+ // SELECT 1 against the DB. Lightship calls this on every /ready.
127
127
  if (store.size() < 0) throw new Error("store corrupt");
128
128
  },
129
129
  });
@@ -8,14 +8,16 @@
8
8
  "test": "vitest run"
9
9
  },
10
10
  "dependencies": {
11
- "@nwire/app": "^0.9.2",
12
- "@nwire/container": "^0.9.2",
13
- "@nwire/endpoint": "^0.9.2",
14
- "@nwire/forge": "^0.9.2",
15
- "@nwire/http": "^0.9.2",
11
+ "@nwire/app": "^0.10.1",
12
+ "@nwire/endpoint": "^0.10.1",
13
+ "@nwire/handler": "^0.10.1",
14
+ "@nwire/wires": "^0.10.1",
15
+ "@nwire/koa": "^0.10.1",
16
+ "koa": "^2.16.1",
16
17
  "zod": "^4.0.0"
17
18
  },
18
19
  "devDependencies": {
20
+ "@types/koa": "^2.15.0",
19
21
  "@types/node": "^22.19.9",
20
22
  "typescript": "^5.9.0",
21
23
  "vite-node": "^3.2.4",
@@ -1,7 +0,0 @@
1
- /**
2
- * Scaffold tests — verify each template materializes a coherent project
3
- * directory with the project name substituted and the canonical files
4
- * present. Does not install or boot the project.
5
- */
6
- export {};
7
- //# sourceMappingURL=scaffold.test.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"scaffold.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/scaffold.test.ts"],"names":[],"mappings":"AAAA;;;;GAIG"}
@@ -1,113 +0,0 @@
1
- /**
2
- * Scaffold tests — verify each template materializes a coherent project
3
- * directory with the project name substituted and the canonical files
4
- * present. Does not install or boot the project.
5
- */
6
- import { mkdtempSync, readFileSync, existsSync, rmSync } from "node:fs";
7
- import { tmpdir } from "node:os";
8
- import { join } from "node:path";
9
- import { describe, it, expect, beforeEach, afterEach } from "vitest";
10
- import { scaffold, resolveTemplateName } from "../index.js";
11
- describe("create-nwire scaffold", () => {
12
- let target;
13
- beforeEach(() => {
14
- target = mkdtempSync(join(tmpdir(), "create-nwire-test-"));
15
- rmSync(target, { recursive: true, force: true });
16
- });
17
- afterEach(() => {
18
- if (existsSync(target))
19
- rmSync(target, { recursive: true, force: true });
20
- });
21
- it("minimal — http+endpoint with folder-organized routes", () => {
22
- const { written } = scaffold({ target, template: "minimal", name: "alpha" });
23
- expect(written.length).toBeGreaterThan(0);
24
- const pkg = JSON.parse(readFileSync(join(target, "package.json"), "utf8"));
25
- expect(pkg.name).toBe("alpha");
26
- expect(pkg.dependencies["@nwire/endpoint"]).toBeDefined();
27
- expect(pkg.dependencies["@nwire/http"]).toBeDefined();
28
- expect(existsSync(join(target, "app/main.ts"))).toBe(true);
29
- expect(existsSync(join(target, "app/api.ts"))).toBe(true);
30
- expect(existsSync(join(target, "app/routes/hello.ts"))).toBe(true);
31
- expect(existsSync(join(target, "__tests__/hello.test.ts"))).toBe(true);
32
- expect(existsSync(join(target, "tsconfig.json"))).toBe(true);
33
- expect(existsSync(join(target, ".gitignore"))).toBe(true);
34
- expect(readFileSync(join(target, "app/main.ts"), "utf8")).toContain('"alpha"');
35
- });
36
- it("service — resources/errors/middleware/store/routes folders", () => {
37
- const { written } = scaffold({ target, template: "service", name: "beta-svc" });
38
- expect(written.length).toBeGreaterThan(0);
39
- const pkg = JSON.parse(readFileSync(join(target, "package.json"), "utf8"));
40
- expect(pkg.name).toBe("beta-svc");
41
- expect(pkg.dependencies["@nwire/forge"]).toBeDefined();
42
- for (const f of ["app/main.ts", "app/api.ts"]) {
43
- expect(existsSync(join(target, f))).toBe(true);
44
- }
45
- expect(existsSync(join(target, "app/resources/todo.ts"))).toBe(true);
46
- expect(existsSync(join(target, "app/errors/todo-errors.ts"))).toBe(true);
47
- expect(existsSync(join(target, "app/middleware/require-user.ts"))).toBe(true);
48
- expect(existsSync(join(target, "app/store/todo-store.ts"))).toBe(true);
49
- for (const r of ["list-todos", "create-todo", "complete-todo", "delete-todo"]) {
50
- expect(existsSync(join(target, `app/routes/${r}.ts`))).toBe(true);
51
- }
52
- expect(existsSync(join(target, "__tests__/todo-api.test.ts"))).toBe(true);
53
- });
54
- it("enterprise — modules/<bc>/{events,actions,workflows,projections,routes}", () => {
55
- const { written } = scaffold({ target, template: "enterprise", name: "gamma-app" });
56
- expect(written.length).toBeGreaterThan(0);
57
- const pkg = JSON.parse(readFileSync(join(target, "package.json"), "utf8"));
58
- expect(pkg.name).toBe("gamma-app");
59
- expect(pkg.dependencies["@nwire/app"]).toBeDefined();
60
- expect(pkg.dependencies["@nwire/forge"]).toBeDefined();
61
- for (const f of ["app/main.ts", "app/api.ts", "app/app.ts"]) {
62
- expect(existsSync(join(target, f))).toBe(true);
63
- }
64
- expect(existsSync(join(target, "modules/posts/posts.module.ts"))).toBe(true);
65
- for (const e of ["post-was-submitted", "post-was-approved", "post-was-rejected"]) {
66
- expect(existsSync(join(target, `modules/posts/events/${e}.ts`))).toBe(true);
67
- }
68
- for (const a of ["submit-post", "approve-post", "reject-post"]) {
69
- expect(existsSync(join(target, `modules/posts/actions/${a}.ts`))).toBe(true);
70
- }
71
- expect(existsSync(join(target, "modules/posts/workflows/auto-moderate.ts"))).toBe(true);
72
- expect(existsSync(join(target, "modules/posts/projections/queue-dashboard.ts"))).toBe(true);
73
- for (const r of ["submit-post", "approve-post", "reject-post", "list-queue", "get-post"]) {
74
- expect(existsSync(join(target, `modules/posts/routes/${r}.ts`))).toBe(true);
75
- }
76
- expect(existsSync(join(target, "__tests__/submit-flow.test.ts"))).toBe(true);
77
- expect(existsSync(join(target, "__tests__/auto-moderate.test.ts"))).toBe(true);
78
- });
79
- it("refuses to scaffold into a non-empty target", () => {
80
- const { written } = scaffold({ target, template: "minimal", name: "first" });
81
- expect(written.length).toBeGreaterThan(0);
82
- expect(() => scaffold({ target, template: "minimal", name: "second" })).toThrowError(/not empty/);
83
- });
84
- it("derives project name from target dir basename when --name omitted", () => {
85
- const t = join(tmpdir(), "create-nwire-derived-" + Date.now());
86
- try {
87
- scaffold({ target: t, template: "minimal" });
88
- const pkg = JSON.parse(readFileSync(join(t, "package.json"), "utf8"));
89
- expect(pkg.name).toMatch(/^create-nwire-derived-/);
90
- }
91
- finally {
92
- rmSync(t, { recursive: true, force: true });
93
- }
94
- });
95
- });
96
- describe("resolveTemplateName", () => {
97
- it("accepts canonical names", () => {
98
- expect(resolveTemplateName("minimal")).toBe("minimal");
99
- expect(resolveTemplateName("service")).toBe("service");
100
- expect(resolveTemplateName("enterprise")).toBe("enterprise");
101
- });
102
- it("accepts deprecated short aliases", () => {
103
- expect(resolveTemplateName("L1")).toBe("minimal");
104
- expect(resolveTemplateName("L2")).toBe("service");
105
- expect(resolveTemplateName("L4")).toBe("enterprise");
106
- expect(resolveTemplateName("l1")).toBe("minimal");
107
- });
108
- it("rejects unknown names", () => {
109
- expect(resolveTemplateName("foo")).toBe(null);
110
- expect(resolveTemplateName("L3")).toBe(null);
111
- });
112
- });
113
- //# sourceMappingURL=scaffold.test.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"scaffold.test.js","sourceRoot":"","sources":["../../src/__tests__/scaffold.test.ts"],"names":[],"mappings":"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"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAkBH,MAAM,MAAM,YAAY,GAAG,SAAS,GAAG,SAAS,GAAG,YAAY,CAAC;AA4BhE,UAAU,eAAe;IACvB,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,YAAY,CAAC;IACvB,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAQD,wBAAgB,QAAQ,CAAC,IAAI,EAAE,eAAe,GAAG;IAAE,OAAO,EAAE,MAAM,EAAE,CAAA;CAAE,CAiBrE;AAsDD;;;GAGG;AACH,wBAAgB,mBAAmB,CAAC,GAAG,EAAE,MAAM,GAAG,YAAY,GAAG,IAAI,CAYpE;AA8DD,wBAAsB,MAAM,IAAI,OAAO,CAAC,IAAI,CAAC,CAE5C"}
package/dist/index.js.map DELETED
@@ -1 +0,0 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}