@x12i/made-easy-api 0.0.0-stage → 0.1.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/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 x12i
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md CHANGED
@@ -1,3 +1,38 @@
1
- # Temporary Holding Version
1
+ # @x12i/made-easy-api
2
2
 
3
- This version is a temporary placeholder for this package. An operational version to replace this has been submitted for review and is awaiting a staged release.
3
+ A dependency-light `node:http` handler that exposes `@x12i/made-easy-service` as an HTTP API, with a generated OpenAPI 3.1 document.
4
+
5
+ ```bash
6
+ npm install @x12i/made-easy-api @x12i/made-easy-service
7
+ ```
8
+
9
+ ```ts
10
+ import { createServer } from 'node:http';
11
+ import { MadeEasyService } from '@x12i/made-easy-service';
12
+ import { bearerTokens, createApiHandler } from '@x12i/made-easy-api';
13
+
14
+ const service = new MadeEasyService();
15
+ const authenticate = bearerTokens([{ token: process.env.TOKEN!, principal: { tenantId: 'acme', callerId: 'alice', roles: ['author'] } }]);
16
+ createServer(createApiHandler({ service, authenticate, corsOrigins: ['https://studio.example'] })).listen(8787);
17
+ ```
18
+
19
+ Tokens are compared by SHA-256 with `timingSafeEqual`. Query-string tokens are not accepted.
20
+
21
+ ## Routes (under `/v1`)
22
+
23
+ | Method and path | Purpose |
24
+ | --- | --- |
25
+ | `GET /guide-recipes`, `GET /guide-recipes/{recipeId}` | Discover recipes |
26
+ | `POST /guides`, `GET /guides`, `GET /guides/{guideId}` | Create and list guides |
27
+ | `GET|PUT /guides/{guideId}/files` | Read and save files (optimistic `expectedRevision`) |
28
+ | `POST /guides/validate`, `POST /guides/preview` | Validate and render without storing |
29
+ | `POST /guide-build-jobs`, `POST /guide-draft-jobs` | Start jobs (`Idempotency-Key` supported) |
30
+ | `GET /guide-jobs`, `GET /guide-jobs/{jobId}`, `DELETE /guide-jobs/{jobId}` | List, read, cancel |
31
+ | `GET /guide-jobs/{jobId}/artifacts/{artifactId}` | Download an artifact (HTML is CSP-sandboxed) |
32
+ | `POST /guides/{guideId}/approvals`, `POST /guides/{guideId}/releases` | Approve a revision, publish a release |
33
+ | `GET /guides/{guideId}/releases/{releaseId}/manifest`, `.../artifacts/{artifactId}` | Read a published release |
34
+ | `GET /openapi.json`, `GET /healthz` | OpenAPI document and liveness |
35
+
36
+ Errors are `{ "error": { "code", "message", "diagnostics"? } }` with stable codes. `ROUTES` is exported, and the OpenAPI document is generated from it, so the two cannot drift.
37
+
38
+ MIT © x12i · [Repository](https://github.com/x12i/made-easy)
package/dist/auth.d.ts ADDED
@@ -0,0 +1,15 @@
1
+ import type { IncomingMessage } from 'node:http';
2
+ import type { Principal } from '@x12i/made-easy-service';
3
+ /** Resolve a request to a Principal, or return undefined to answer 401. */
4
+ export type Authenticator = (req: IncomingMessage) => Principal | undefined | Promise<Principal | undefined>;
5
+ export interface TokenEntry {
6
+ /** The bearer token. Compared by SHA-256 digest in constant time; never logged. */
7
+ token: string;
8
+ principal: Principal;
9
+ }
10
+ export declare function bearerFromRequest(req: IncomingMessage): string | undefined;
11
+ /** Static bearer tokens, each bound to one tenant and role set. */
12
+ export declare function bearerTokens(entries: TokenEntry[]): Authenticator;
13
+ /** Everyone is the same principal. Only for loopback development; the server refuses it on public interfaces. */
14
+ export declare function singleUser(principal: Principal): Authenticator;
15
+ //# sourceMappingURL=auth.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"auth.d.ts","sourceRoot":"","sources":["../src/auth.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,WAAW,CAAC;AACjD,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yBAAyB,CAAC;AAEzD,2EAA2E;AAC3E,MAAM,MAAM,aAAa,GAAG,CAAC,GAAG,EAAE,eAAe,KAAK,SAAS,GAAG,SAAS,GAAG,OAAO,CAAC,SAAS,GAAG,SAAS,CAAC,CAAC;AAE7G,MAAM,WAAW,UAAU;IACzB,mFAAmF;IACnF,KAAK,EAAE,MAAM,CAAC;IACd,SAAS,EAAE,SAAS,CAAC;CACtB;AAID,wBAAgB,iBAAiB,CAAC,GAAG,EAAE,eAAe,GAAG,MAAM,GAAG,SAAS,CAK1E;AAED,mEAAmE;AACnE,wBAAgB,YAAY,CAAC,OAAO,EAAE,UAAU,EAAE,GAAG,aAAa,CAUjE;AAED,iHAAiH;AACjH,wBAAgB,UAAU,CAAC,SAAS,EAAE,SAAS,GAAG,aAAa,CAE9D"}
package/dist/auth.js ADDED
@@ -0,0 +1,29 @@
1
+ import { createHash, timingSafeEqual } from 'node:crypto';
2
+ const digest = (s) => createHash('sha256').update(s).digest();
3
+ export function bearerFromRequest(req) {
4
+ const h = req.headers.authorization;
5
+ if (!h)
6
+ return undefined;
7
+ const m = /^Bearer\s+(\S+)$/i.exec(h);
8
+ return m?.[1];
9
+ }
10
+ /** Static bearer tokens, each bound to one tenant and role set. */
11
+ export function bearerTokens(entries) {
12
+ const table = entries.map((e) => ({ hash: digest(e.token), principal: e.principal }));
13
+ return (req) => {
14
+ const token = bearerFromRequest(req);
15
+ if (!token)
16
+ return undefined;
17
+ const h = digest(token);
18
+ let found;
19
+ for (const row of table)
20
+ if (timingSafeEqual(row.hash, h))
21
+ found = row.principal;
22
+ return found;
23
+ };
24
+ }
25
+ /** Everyone is the same principal. Only for loopback development; the server refuses it on public interfaces. */
26
+ export function singleUser(principal) {
27
+ return () => principal;
28
+ }
29
+ //# sourceMappingURL=auth.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"auth.js","sourceRoot":"","sources":["../src/auth.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAa1D,MAAM,MAAM,GAAG,CAAC,CAAS,EAAE,EAAE,CAAC,UAAU,CAAC,QAAQ,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC;AAEtE,MAAM,UAAU,iBAAiB,CAAC,GAAoB;IACpD,MAAM,CAAC,GAAG,GAAG,CAAC,OAAO,CAAC,aAAa,CAAC;IACpC,IAAI,CAAC,CAAC;QAAE,OAAO,SAAS,CAAC;IACzB,MAAM,CAAC,GAAG,mBAAmB,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IACtC,OAAO,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC;AAChB,CAAC;AAED,mEAAmE;AACnE,MAAM,UAAU,YAAY,CAAC,OAAqB;IAChD,MAAM,KAAK,GAAG,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,EAAE,IAAI,EAAE,MAAM,CAAC,CAAC,CAAC,KAAK,CAAC,EAAE,SAAS,EAAE,CAAC,CAAC,SAAS,EAAE,CAAC,CAAC,CAAC;IACtF,OAAO,CAAC,GAAG,EAAE,EAAE;QACb,MAAM,KAAK,GAAG,iBAAiB,CAAC,GAAG,CAAC,CAAC;QACrC,IAAI,CAAC,KAAK;YAAE,OAAO,SAAS,CAAC;QAC7B,MAAM,CAAC,GAAG,MAAM,CAAC,KAAK,CAAC,CAAC;QACxB,IAAI,KAA4B,CAAC;QACjC,KAAK,MAAM,GAAG,IAAI,KAAK;YAAE,IAAI,eAAe,CAAC,GAAG,CAAC,IAAI,EAAE,CAAC,CAAC;gBAAE,KAAK,GAAG,GAAG,CAAC,SAAS,CAAC;QACjF,OAAO,KAAK,CAAC;IACf,CAAC,CAAC;AACJ,CAAC;AAED,iHAAiH;AACjH,MAAM,UAAU,UAAU,CAAC,SAAoB;IAC7C,OAAO,GAAG,EAAE,CAAC,SAAS,CAAC;AACzB,CAAC"}
@@ -0,0 +1,19 @@
1
+ import { type IncomingMessage, type Server, type ServerResponse } from 'node:http';
2
+ import { type MadeEasyService } from '@x12i/made-easy-service';
3
+ import type { Authenticator } from './auth.js';
4
+ export interface ApiOptions {
5
+ service: MadeEasyService;
6
+ authenticate: Authenticator;
7
+ /** Path prefix for versioned routes. Default "/v1". */
8
+ base?: string;
9
+ /** Largest accepted JSON body in bytes. Default 40 MiB (bundles may carry ZIP or image data). */
10
+ maxBodyBytes?: number;
11
+ /** Allowed browser origins for CORS (exact match). Omit to disable CORS. */
12
+ corsOrigins?: string[];
13
+ /** Serve a static handler for non-API GET requests (the Studio uses this). Return false if not handled. */
14
+ fallback?: (req: IncomingMessage, res: ServerResponse) => Promise<boolean> | boolean;
15
+ }
16
+ /** The request handler. Mount it on any node:http server. */
17
+ export declare function createApiHandler(options: ApiOptions): (req: IncomingMessage, res: ServerResponse) => Promise<void>;
18
+ export declare function createApiServer(options: ApiOptions): Server;
19
+ //# sourceMappingURL=handler.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"handler.d.ts","sourceRoot":"","sources":["../src/handler.ts"],"names":[],"mappings":"AAAA,OAAO,EAAgB,KAAK,eAAe,EAAE,KAAK,MAAM,EAAE,KAAK,cAAc,EAAE,MAAM,WAAW,CAAC;AAEjG,OAAO,EAAgB,KAAK,eAAe,EAAE,MAAM,yBAAyB,CAAC;AAC7E,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,WAAW,CAAC;AAI/C,MAAM,WAAW,UAAU;IACzB,OAAO,EAAE,eAAe,CAAC;IACzB,YAAY,EAAE,aAAa,CAAC;IAC5B,uDAAuD;IACvD,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,iGAAiG;IACjG,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,4EAA4E;IAC5E,WAAW,CAAC,EAAE,MAAM,EAAE,CAAC;IACvB,2GAA2G;IAC3G,QAAQ,CAAC,EAAE,CAAC,GAAG,EAAE,eAAe,EAAE,GAAG,EAAE,cAAc,KAAK,OAAO,CAAC,OAAO,CAAC,GAAG,OAAO,CAAC;CACtF;AA0CD,6DAA6D;AAC7D,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,UAAU,GAAG,CAAC,GAAG,EAAE,eAAe,EAAE,GAAG,EAAE,cAAc,KAAK,OAAO,CAAC,IAAI,CAAC,CAqHlH;AAED,wBAAgB,eAAe,CAAC,OAAO,EAAE,UAAU,GAAG,MAAM,CAG3D"}
@@ -0,0 +1,166 @@
1
+ import { createServer } from 'node:http';
2
+ import { MadeEasyError } from '@x12i/made-easy';
3
+ import { ServiceError } from '@x12i/made-easy-service';
4
+ import { buildOpenApi } from './openapi.js';
5
+ import { ROUTES } from './routes.js';
6
+ function compile(route, base) {
7
+ const keys = [];
8
+ const full = route.public ? route.path : `${base}${route.path}`;
9
+ const re = new RegExp(`^${full.replace(/:([A-Za-z]+)/g, (_m, k) => (keys.push(k), '([^/]+)'))}/?$`);
10
+ return { route, re, keys };
11
+ }
12
+ function send(res, status, json, extra = {}) {
13
+ const body = JSON.stringify(json);
14
+ res.writeHead(status, {
15
+ 'content-type': 'application/json; charset=utf-8',
16
+ 'content-length': Buffer.byteLength(body),
17
+ 'cache-control': 'no-store',
18
+ 'x-content-type-options': 'nosniff',
19
+ ...extra,
20
+ });
21
+ res.end(body);
22
+ }
23
+ class BodyTooLarge extends Error {
24
+ }
25
+ async function readBody(req, limit) {
26
+ const declared = Number(req.headers['content-length'] ?? 0);
27
+ if (declared > limit)
28
+ throw new BodyTooLarge();
29
+ const chunks = [];
30
+ let size = 0;
31
+ for await (const chunk of req) {
32
+ size += chunk.length;
33
+ if (size > limit)
34
+ throw new BodyTooLarge();
35
+ chunks.push(chunk);
36
+ }
37
+ return Buffer.concat(chunks);
38
+ }
39
+ /** The request handler. Mount it on any node:http server. */
40
+ export function createApiHandler(options) {
41
+ const base = options.base ?? '/v1';
42
+ const limit = options.maxBodyBytes ?? 40 * 1024 * 1024;
43
+ const compiled = ROUTES.map((r) => compile(r, base));
44
+ const openapi = buildOpenApi({ base });
45
+ return async (req, res) => {
46
+ const url = new URL(req.url ?? '/', 'http://localhost');
47
+ const origin = req.headers.origin;
48
+ const cors = {};
49
+ if (origin && options.corsOrigins?.includes(origin)) {
50
+ cors['access-control-allow-origin'] = origin;
51
+ cors.vary = 'Origin';
52
+ cors['access-control-allow-headers'] = 'authorization, content-type, idempotency-key';
53
+ cors['access-control-allow-methods'] = 'GET, POST, PUT, DELETE, OPTIONS';
54
+ }
55
+ try {
56
+ if (req.method === 'OPTIONS') {
57
+ res.writeHead(204, cors);
58
+ res.end();
59
+ return;
60
+ }
61
+ if (url.pathname === `${base}/openapi.json` && req.method === 'GET')
62
+ return send(res, 200, openapi, cors);
63
+ let match;
64
+ let pathMatched = false;
65
+ for (const c of compiled) {
66
+ const m = c.re.exec(url.pathname);
67
+ if (!m)
68
+ continue;
69
+ pathMatched = true;
70
+ if (c.route.method !== req.method)
71
+ continue;
72
+ const params = {};
73
+ c.keys.forEach((k, i) => (params[k] = decodeURIComponent(m[i + 1])));
74
+ match = { c, params };
75
+ break;
76
+ }
77
+ if (!match) {
78
+ if (!pathMatched && req.method === 'GET' && options.fallback && !url.pathname.startsWith(`${base}/`)) {
79
+ if (await options.fallback(req, res))
80
+ return;
81
+ }
82
+ return send(res, pathMatched ? 405 : 404, { error: { code: pathMatched ? 'METHOD_NOT_ALLOWED' : 'NOT_FOUND', message: pathMatched ? 'Method not allowed.' : 'No such route.' } }, cors);
83
+ }
84
+ const { route } = match.c;
85
+ let principal;
86
+ if (!route.public) {
87
+ principal = await options.authenticate(req);
88
+ if (!principal)
89
+ return send(res, 401, { error: { code: 'UNAUTHENTICATED', message: 'A valid bearer token is required.' } }, { ...cors, 'www-authenticate': 'Bearer' });
90
+ }
91
+ let body;
92
+ if (req.method === 'POST' || req.method === 'PUT') {
93
+ const raw = await readBody(req, limit);
94
+ if (raw.length) {
95
+ const type = String(req.headers['content-type'] ?? '');
96
+ if (!type.toLowerCase().startsWith('application/json')) {
97
+ return send(res, 415, { error: { code: 'UNSUPPORTED_MEDIA_TYPE', message: 'Send application/json.' } }, cors);
98
+ }
99
+ try {
100
+ body = JSON.parse(raw.toString('utf8'));
101
+ }
102
+ catch {
103
+ return send(res, 400, { error: { code: 'INVALID_JSON', message: 'The request body is not valid JSON.' } }, cors);
104
+ }
105
+ }
106
+ else if (route.bodySchema) {
107
+ return send(res, 400, { error: { code: 'INVALID_REQUEST', message: 'A JSON body is required.' } }, cors);
108
+ }
109
+ }
110
+ if (route.parse) {
111
+ const parsed = route.parse(body);
112
+ if (!parsed.success) {
113
+ const message = parsed.error.issues.map((i) => `${i.path.map(String).join('.') || '(body)'}: ${i.message}`).join('; ');
114
+ return send(res, 400, { error: { code: 'INVALID_REQUEST', message } }, cors);
115
+ }
116
+ body = parsed.data;
117
+ }
118
+ const idem = req.headers['idempotency-key'];
119
+ const result = await route.handler({
120
+ service: options.service,
121
+ principal: principal,
122
+ params: match.params,
123
+ query: url.searchParams,
124
+ body,
125
+ headers: { idempotencyKey: typeof idem === 'string' ? idem : undefined },
126
+ base,
127
+ });
128
+ if ('bytes' in result) {
129
+ const html = result.mediaType === 'text/html';
130
+ res.writeHead(result.status, {
131
+ 'content-type': result.mediaType,
132
+ 'content-length': result.bytes.length,
133
+ 'content-disposition': `attachment; filename="${result.filename.replace(/[^A-Za-z0-9._-]/g, '_')}"`,
134
+ 'cache-control': 'private, max-age=0',
135
+ 'x-content-type-options': 'nosniff',
136
+ ...(html ? { 'content-security-policy': "sandbox; default-src 'none'; style-src 'unsafe-inline'; img-src data:" } : {}),
137
+ ...cors,
138
+ });
139
+ res.end(Buffer.from(result.bytes));
140
+ return;
141
+ }
142
+ return send(res, result.status, result.json, { ...cors, ...(result.headers ?? {}) });
143
+ }
144
+ catch (e) {
145
+ if (e instanceof BodyTooLarge)
146
+ return send(res, 413, { error: { code: 'BODY_TOO_LARGE', message: 'The request body is too large.' } }, cors);
147
+ if (e instanceof ServiceError) {
148
+ return send(res, e.status, { error: { code: e.code, message: e.message, ...(e.diagnostics ? { diagnostics: e.diagnostics } : {}) } }, cors);
149
+ }
150
+ if (e instanceof MadeEasyError) {
151
+ return send(res, 422, { error: { code: e.code, message: e.message, diagnostics: e.diagnostics } }, cors);
152
+ }
153
+ if (e.name === 'ZodError') {
154
+ return send(res, 400, { error: { code: 'INVALID_REQUEST', message: e.message } }, cors);
155
+ }
156
+ // Never leak internals; the message is generic and details stay in the server log.
157
+ process.stderr.write(`[made-easy-api] ${e.stack ?? e}\n`);
158
+ return send(res, 500, { error: { code: 'INTERNAL_ERROR', message: 'The server could not complete the request.' } }, cors);
159
+ }
160
+ };
161
+ }
162
+ export function createApiServer(options) {
163
+ const handler = createApiHandler(options);
164
+ return createServer((req, res) => void handler(req, res));
165
+ }
166
+ //# sourceMappingURL=handler.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"handler.js","sourceRoot":"","sources":["../src/handler.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,5 @@
1
+ export { createApiHandler, createApiServer, type ApiOptions } from './handler.js';
2
+ export { bearerTokens, bearerFromRequest, singleUser, type Authenticator, type TokenEntry } from './auth.js';
3
+ export { buildOpenApi } from './openapi.js';
4
+ export { ROUTES, jobView, type Route, type RouteContext, type RouteResult } from './routes.js';
5
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,eAAe,EAAE,KAAK,UAAU,EAAE,MAAM,cAAc,CAAC;AAClF,OAAO,EAAE,YAAY,EAAE,iBAAiB,EAAE,UAAU,EAAE,KAAK,aAAa,EAAE,KAAK,UAAU,EAAE,MAAM,WAAW,CAAC;AAC7G,OAAO,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AAC5C,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,KAAK,KAAK,EAAE,KAAK,YAAY,EAAE,KAAK,WAAW,EAAE,MAAM,aAAa,CAAC"}
package/dist/index.js ADDED
@@ -0,0 +1,5 @@
1
+ export { createApiHandler, createApiServer } from './handler.js';
2
+ export { bearerTokens, bearerFromRequest, singleUser } from './auth.js';
3
+ export { buildOpenApi } from './openapi.js';
4
+ export { ROUTES, jobView } from './routes.js';
5
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,eAAe,EAAmB,MAAM,cAAc,CAAC;AAClF,OAAO,EAAE,YAAY,EAAE,iBAAiB,EAAE,UAAU,EAAuC,MAAM,WAAW,CAAC;AAC7G,OAAO,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AAC5C,OAAO,EAAE,MAAM,EAAE,OAAO,EAAmD,MAAM,aAAa,CAAC"}
@@ -0,0 +1,9 @@
1
+ type Json = Record<string, unknown>;
2
+ /** Generate the OpenAPI 3.1 document from the route table, so docs and behaviour cannot drift. */
3
+ export declare function buildOpenApi(options?: {
4
+ base?: string;
5
+ title?: string;
6
+ serverUrl?: string;
7
+ }): Json;
8
+ export {};
9
+ //# sourceMappingURL=openapi.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"openapi.d.ts","sourceRoot":"","sources":["../src/openapi.ts"],"names":[],"mappings":"AAGA,KAAK,IAAI,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;AAOpC,kGAAkG;AAClG,wBAAgB,YAAY,CAAC,OAAO,GAAE;IAAE,IAAI,CAAC,EAAE,MAAM,CAAC;IAAC,KAAK,CAAC,EAAE,MAAM,CAAC;IAAC,SAAS,CAAC,EAAE,MAAM,CAAA;CAAO,GAAG,IAAI,CAqCtG"}
@@ -0,0 +1,48 @@
1
+ import { VERSION, getJsonSchemas } from '@x12i/made-easy';
2
+ import { ROUTES } from './routes.js';
3
+ function clean(schema) {
4
+ const { $id: _id, $schema: _s, title: _t, ...rest } = schema;
5
+ return rest;
6
+ }
7
+ /** Generate the OpenAPI 3.1 document from the route table, so docs and behaviour cannot drift. */
8
+ export function buildOpenApi(options = {}) {
9
+ const base = options.base ?? '/v1';
10
+ const schemas = {};
11
+ for (const [name, schema] of Object.entries(getJsonSchemas())) {
12
+ if (name.startsWith('blocks/'))
13
+ continue;
14
+ schemas[name.replace(/\.v1$/, '')] = clean(schema);
15
+ }
16
+ const paths = {};
17
+ for (const r of ROUTES) {
18
+ const p = (r.public ? r.path : `${base}${r.path}`).replace(/:([A-Za-z]+)/g, '{$1}');
19
+ const params = [...r.path.matchAll(/:([A-Za-z]+)/g)].map((m) => ({ name: m[1], in: 'path', required: true, schema: { type: 'string' } }));
20
+ if (r.idempotent)
21
+ params.push({ name: 'Idempotency-Key', in: 'header', required: false, schema: { type: 'string', maxLength: 200 } });
22
+ const op = {
23
+ operationId: r.operationId,
24
+ summary: r.summary,
25
+ ...(params.length ? { parameters: params } : {}),
26
+ ...(r.bodySchema ? { requestBody: { required: true, content: { 'application/json': { schema: { $ref: `#/components/schemas/${r.bodySchema.replace(/\.v1$/, '')}` } } } } } : {}),
27
+ ...(r.role ? { 'x-required-role': r.role } : {}),
28
+ ...(r.public ? { security: [] } : {}),
29
+ responses: {
30
+ [String(r.successStatus ?? 200)]: { description: 'Success' },
31
+ '400': { description: 'Invalid request', content: { 'application/json': { schema: { $ref: '#/components/schemas/problem' } } } },
32
+ ...(r.public ? {} : { '401': { description: 'Missing or invalid bearer token' }, '403': { description: 'The caller lacks the required role' } }),
33
+ '404': { description: 'Not found (also returned for resources of other tenants)' },
34
+ '409': { description: 'Conflict: revision mismatch, idempotency conflict, approval or release preconditions' },
35
+ },
36
+ };
37
+ (paths[p] ??= {})[r.method.toLowerCase()] = op;
38
+ }
39
+ return {
40
+ openapi: '3.1.0',
41
+ info: { title: options.title ?? 'Made Easy API', version: VERSION, description: 'Create, validate, preview, build, approve and release two-track guides. Builds are jobs; all content is tenant-scoped.' },
42
+ ...(options.serverUrl ? { servers: [{ url: options.serverUrl }] } : {}),
43
+ security: [{ bearer: [] }],
44
+ paths,
45
+ components: { securitySchemes: { bearer: { type: 'http', scheme: 'bearer' } }, schemas },
46
+ };
47
+ }
48
+ //# sourceMappingURL=openapi.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"openapi.js","sourceRoot":"","sources":["../src/openapi.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,86 @@
1
+ import { MadeEasyService, type JobRecord, type Principal } from '@x12i/made-easy-service';
2
+ export interface RouteContext {
3
+ service: MadeEasyService;
4
+ principal: Principal;
5
+ params: Record<string, string>;
6
+ query: URLSearchParams;
7
+ body: unknown;
8
+ headers: {
9
+ idempotencyKey?: string;
10
+ };
11
+ /** Absolute-path prefix used when building links (for example "/v1"). */
12
+ base: string;
13
+ }
14
+ export type RouteResult = {
15
+ status: number;
16
+ json: unknown;
17
+ headers?: Record<string, string>;
18
+ } | {
19
+ status: number;
20
+ bytes: Uint8Array;
21
+ mediaType: string;
22
+ filename: string;
23
+ };
24
+ export interface Route {
25
+ method: 'GET' | 'POST' | 'PUT' | 'DELETE';
26
+ path: string;
27
+ operationId: string;
28
+ summary: string;
29
+ /** Role needed, for documentation. Enforcement lives in the service. */
30
+ role?: 'author' | 'reviewer' | 'publisher';
31
+ /** Name of the JSON schema (from @x12i/made-easy getJsonSchemas) describing the body. */
32
+ bodySchema?: string;
33
+ parse?: (body: unknown) => {
34
+ success: true;
35
+ data: unknown;
36
+ } | {
37
+ success: false;
38
+ error: {
39
+ issues: {
40
+ path: PropertyKey[];
41
+ message: string;
42
+ }[];
43
+ };
44
+ };
45
+ handler(ctx: RouteContext): Promise<RouteResult>;
46
+ successStatus?: number;
47
+ /** Idempotency-Key header supported. */
48
+ idempotent?: boolean;
49
+ public?: boolean;
50
+ }
51
+ /** Add links to a job. The artifact URL is relative to the API, never a filesystem path. */
52
+ export declare function jobView(base: string, job: JobRecord): {
53
+ statusUrl: string;
54
+ artifacts: {
55
+ id: string;
56
+ url: string;
57
+ path: string;
58
+ mediaType: string;
59
+ size: number;
60
+ sha256: string;
61
+ }[];
62
+ id: string;
63
+ kind: import("@x12i/made-easy").JobKind;
64
+ status: import("@x12i/made-easy").JobStatus;
65
+ guideId?: string;
66
+ revision?: string;
67
+ createdAt: string;
68
+ updatedAt: string;
69
+ cancelRequested?: boolean;
70
+ result?: unknown;
71
+ error?: {
72
+ code: string;
73
+ message: string;
74
+ };
75
+ build?: {
76
+ mode: string;
77
+ audience: string;
78
+ visibility: string;
79
+ complete: boolean;
80
+ ok: boolean;
81
+ revision?: string;
82
+ referenceRevision?: string;
83
+ };
84
+ };
85
+ export declare const ROUTES: Route[];
86
+ //# sourceMappingURL=routes.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"routes.d.ts","sourceRoot":"","sources":["../src/routes.ts"],"names":[],"mappings":"AASA,OAAO,EAAE,eAAe,EAAgB,KAAK,SAAS,EAAE,KAAK,SAAS,EAAE,MAAM,yBAAyB,CAAC;AAExG,MAAM,WAAW,YAAY;IAC3B,OAAO,EAAE,eAAe,CAAC;IACzB,SAAS,EAAE,SAAS,CAAC;IACrB,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC/B,KAAK,EAAE,eAAe,CAAC;IACvB,IAAI,EAAE,OAAO,CAAC;IACd,OAAO,EAAE;QAAE,cAAc,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;IACrC,yEAAyE;IACzE,IAAI,EAAE,MAAM,CAAC;CACd;AAED,MAAM,MAAM,WAAW,GACnB;IAAE,MAAM,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,OAAO,CAAC;IAAC,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;CAAE,GACnE;IAAE,MAAM,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,UAAU,CAAC;IAAC,SAAS,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAA;CAAE,CAAC;AAE/E,MAAM,WAAW,KAAK;IACpB,MAAM,EAAE,KAAK,GAAG,MAAM,GAAG,KAAK,GAAG,QAAQ,CAAC;IAC1C,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,OAAO,EAAE,MAAM,CAAC;IAChB,wEAAwE;IACxE,IAAI,CAAC,EAAE,QAAQ,GAAG,UAAU,GAAG,WAAW,CAAC;IAC3C,yFAAyF;IACzF,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,KAAK,CAAC,EAAE,CAAC,IAAI,EAAE,OAAO,KAAK;QAAE,OAAO,EAAE,IAAI,CAAC;QAAC,IAAI,EAAE,OAAO,CAAA;KAAE,GAAG;QAAE,OAAO,EAAE,KAAK,CAAC;QAAC,KAAK,EAAE;YAAE,MAAM,EAAE;gBAAE,IAAI,EAAE,WAAW,EAAE,CAAC;gBAAC,OAAO,EAAE,MAAM,CAAA;aAAE,EAAE,CAAA;SAAE,CAAA;KAAE,CAAC;IAChJ,OAAO,CAAC,GAAG,EAAE,YAAY,GAAG,OAAO,CAAC,WAAW,CAAC,CAAC;IACjD,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,wCAAwC;IACxC,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,MAAM,CAAC,EAAE,OAAO,CAAC;CAClB;AAUD,4FAA4F;AAC5F,wBAAgB,OAAO,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,EAAE,SAAS;;;;;;;;;;;;;;;;;;;;;;;;;;;;;gBAKqC,CAAC;yBAAmC,CAAC;;EAE7H;AAED,eAAO,MAAM,MAAM,EAAE,KAAK,EAoPzB,CAAC"}
package/dist/routes.js ADDED
@@ -0,0 +1,267 @@
1
+ import { BuildRequestSchema, CreateGuideRequestSchema, DraftRequestSchema, PreviewRequestSchema, ValidateRequestSchema, artifactIdForPath, } from '@x12i/made-easy';
2
+ import { ServiceError } from '@x12i/made-easy-service';
3
+ const invalid = (message) => new ServiceError(400, 'INVALID_REQUEST', message);
4
+ function str(body, key) {
5
+ const v = body?.[key];
6
+ if (typeof v !== 'string' || !v)
7
+ throw invalid(`"${key}" is required.`);
8
+ return v;
9
+ }
10
+ /** Add links to a job. The artifact URL is relative to the API, never a filesystem path. */
11
+ export function jobView(base, job) {
12
+ const { tenantId: _t, callerId: _c, request: _r, fence: _f, leaseExpiresAt: _l, ...rest } = job;
13
+ return {
14
+ ...rest,
15
+ statusUrl: `${base}/guide-jobs/${job.id}`,
16
+ artifacts: job.artifacts.map((a) => ({ ...a, id: a.id || artifactIdForPath(a.path), url: `${base}/guide-jobs/${job.id}/artifacts/${encodeURIComponent(a.id || artifactIdForPath(a.path))}` })),
17
+ };
18
+ }
19
+ export const ROUTES = [
20
+ {
21
+ method: 'GET',
22
+ path: '/healthz',
23
+ operationId: 'health',
24
+ summary: 'Liveness probe',
25
+ public: true,
26
+ handler: async () => ({ status: 200, json: { ok: true } }),
27
+ },
28
+ {
29
+ method: 'GET',
30
+ path: '/guide-recipes',
31
+ operationId: 'listRecipes',
32
+ summary: 'List recipes (profile.preset) with their section roles',
33
+ handler: async ({ service }) => ({ status: 200, json: { recipes: await service.listRecipes() } }),
34
+ },
35
+ {
36
+ method: 'GET',
37
+ path: '/guide-recipes/:recipeId',
38
+ operationId: 'getRecipe',
39
+ summary: 'Get one recipe: section roles, required fields, subject profile and preset rules',
40
+ handler: async ({ service, params }) => ({ status: 200, json: await service.getRecipe(params.recipeId) }),
41
+ },
42
+ {
43
+ method: 'POST',
44
+ path: '/guides',
45
+ operationId: 'createGuide',
46
+ summary: 'Scaffold a new guide from a recipe and store it as revision 1',
47
+ role: 'author',
48
+ bodySchema: 'create-request.v1',
49
+ parse: (b) => CreateGuideRequestSchema.safeParse(b),
50
+ successStatus: 201,
51
+ handler: async ({ service, principal, body, base }) => {
52
+ const r = await service.createGuide(principal, body);
53
+ return { status: 201, json: r, headers: { location: `${base}/guides/${r.guide.guideId}` } };
54
+ },
55
+ },
56
+ {
57
+ method: 'GET',
58
+ path: '/guides',
59
+ operationId: 'listGuides',
60
+ summary: 'List the tenant’s guides',
61
+ handler: async ({ service, principal }) => ({ status: 200, json: { guides: await service.listGuides(principal) } }),
62
+ },
63
+ {
64
+ method: 'GET',
65
+ path: '/guides/:guideId',
66
+ operationId: 'getGuide',
67
+ summary: 'Get a guide record (head revision and history)',
68
+ handler: async ({ service, principal, params }) => ({ status: 200, json: await service.getGuide(principal, params.guideId) }),
69
+ },
70
+ {
71
+ method: 'GET',
72
+ path: '/guides/:guideId/revisions',
73
+ operationId: 'listRevisions',
74
+ summary: 'List stored revisions of a guide',
75
+ handler: async ({ service, principal, params }) => ({ status: 200, json: { revisions: await service.listRevisions(principal, params.guideId) } }),
76
+ },
77
+ {
78
+ method: 'GET',
79
+ path: '/guides/:guideId/files',
80
+ operationId: 'getGuideFiles',
81
+ summary: 'Read the files of a revision (default: head)',
82
+ handler: async ({ service, principal, params, query }) => ({ status: 200, json: await service.getFiles(principal, params.guideId, query.get('revision') ?? undefined) }),
83
+ },
84
+ {
85
+ method: 'PUT',
86
+ path: '/guides/:guideId/files',
87
+ operationId: 'putGuideFiles',
88
+ summary: 'Save a new revision. Updating requires expectedRevision (the current head).',
89
+ role: 'author',
90
+ handler: async ({ service, principal, params, body }) => {
91
+ const files = body?.files;
92
+ if (!files || typeof files !== 'object')
93
+ throw invalid('"files" is required.');
94
+ const expected = body.expectedRevision;
95
+ const r = await service.saveFiles(principal, params.guideId, files, { expectedRevision: expected });
96
+ return { status: r.changed ? 200 : 200, json: { revision: r.revision, changed: r.changed, guide: r.guide } };
97
+ },
98
+ },
99
+ {
100
+ method: 'POST',
101
+ path: '/guides/validate',
102
+ operationId: 'validateGuide',
103
+ summary: 'Validate a bundle and return located diagnostics',
104
+ bodySchema: 'validate-request.v1',
105
+ parse: (b) => ValidateRequestSchema.safeParse(b),
106
+ handler: async ({ service, principal, body }) => ({ status: 200, json: await service.validate(principal, body) }),
107
+ },
108
+ {
109
+ method: 'POST',
110
+ path: '/guides/preview',
111
+ operationId: 'previewGuide',
112
+ summary: 'Render one track as HTML, Markdown or JSON without building artifacts',
113
+ bodySchema: 'preview-request.v1',
114
+ parse: (b) => PreviewRequestSchema.safeParse(b),
115
+ handler: async ({ service, principal, body }) => ({ status: 200, json: await service.preview(principal, body) }),
116
+ },
117
+ {
118
+ method: 'POST',
119
+ path: '/guide-build-jobs',
120
+ operationId: 'startBuild',
121
+ summary: 'Start a build job. Idempotent with an Idempotency-Key header.',
122
+ role: 'author',
123
+ bodySchema: 'build-request.v1',
124
+ parse: (b) => BuildRequestSchema.safeParse(b),
125
+ idempotent: true,
126
+ successStatus: 202,
127
+ handler: async ({ service, principal, body, headers, base }) => {
128
+ const job = await service.startBuild(principal, body, { idempotencyKey: headers.idempotencyKey });
129
+ return { status: 202, json: jobView(base, job), headers: { location: `${base}/guide-jobs/${job.id}` } };
130
+ },
131
+ },
132
+ {
133
+ method: 'POST',
134
+ path: '/guide-draft-jobs',
135
+ operationId: 'startDraft',
136
+ summary: 'Start a draft job that proposes section text from a pinned source snapshot',
137
+ role: 'author',
138
+ bodySchema: 'draft-request.v1',
139
+ parse: (b) => DraftRequestSchema.safeParse(b),
140
+ idempotent: true,
141
+ successStatus: 202,
142
+ handler: async ({ service, principal, body, headers, base }) => {
143
+ const job = await service.startDraft(principal, body, { idempotencyKey: headers.idempotencyKey });
144
+ return { status: 202, json: jobView(base, job), headers: { location: `${base}/guide-jobs/${job.id}` } };
145
+ },
146
+ },
147
+ {
148
+ method: 'POST',
149
+ path: '/guides/:guideId/draft-apply',
150
+ operationId: 'applyDraft',
151
+ summary: 'Apply a draft proposal as a new revision, only against the revision it was drafted from',
152
+ role: 'author',
153
+ handler: async ({ service, principal, params, body }) => {
154
+ const proposal = body?.proposal;
155
+ if (!proposal)
156
+ throw invalid('"proposal" is required.');
157
+ return { status: 200, json: await service.applyDraft(principal, params.guideId, { proposal, expectedRevision: str(body, 'expectedRevision'), entries: body.entries }) };
158
+ },
159
+ },
160
+ {
161
+ method: 'GET',
162
+ path: '/guide-jobs',
163
+ operationId: 'listJobs',
164
+ summary: 'List jobs, newest first',
165
+ handler: async ({ service, principal, query, base }) => ({
166
+ status: 200,
167
+ json: { jobs: (await service.listJobs(principal, { guideId: query.get('guideId') ?? undefined })).map((j) => jobView(base, j)) },
168
+ }),
169
+ },
170
+ {
171
+ method: 'GET',
172
+ path: '/guide-jobs/:jobId',
173
+ operationId: 'getJob',
174
+ summary: 'Get a job and its artifacts',
175
+ handler: async ({ service, principal, params, base }) => ({ status: 200, json: jobView(base, await service.getJob(principal, params.jobId)) }),
176
+ },
177
+ {
178
+ method: 'DELETE',
179
+ path: '/guide-jobs/:jobId',
180
+ operationId: 'cancelJob',
181
+ summary: 'Cancel a job. A cancelled worker can no longer publish artifacts. Returns the job (finished jobs are unchanged).',
182
+ role: 'author',
183
+ handler: async ({ service, principal, params, base }) => ({ status: 200, json: jobView(base, await service.cancelJob(principal, params.jobId)) }),
184
+ },
185
+ {
186
+ method: 'GET',
187
+ path: '/guide-jobs/:jobId/artifacts/:artifactId',
188
+ operationId: 'downloadArtifact',
189
+ summary: 'Download one artifact of a succeeded job',
190
+ handler: async ({ service, principal, params }) => {
191
+ const { descriptor, bytes } = await service.readArtifact(principal, params.jobId, decodeURIComponent(params.artifactId));
192
+ return { status: 200, bytes, mediaType: descriptor.mediaType, filename: descriptor.path.split('/').pop() ?? 'artifact' };
193
+ },
194
+ },
195
+ {
196
+ method: 'POST',
197
+ path: '/guides/:guideId/approvals',
198
+ operationId: 'approveRevision',
199
+ summary: 'Approve one exact revision. Approvals do not carry over to later revisions.',
200
+ role: 'reviewer',
201
+ successStatus: 201,
202
+ handler: async ({ service, principal, params, body }) => ({
203
+ status: 201,
204
+ json: await service.approve(principal, params.guideId, str(body, 'revision'), body.note),
205
+ }),
206
+ },
207
+ {
208
+ method: 'GET',
209
+ path: '/guides/:guideId/approvals',
210
+ operationId: 'listApprovals',
211
+ summary: 'List approvals of a revision (?revision=)',
212
+ handler: async ({ service, principal, params, query }) => {
213
+ const revision = query.get('revision');
214
+ if (!revision)
215
+ throw invalid('"revision" query parameter is required.');
216
+ return { status: 200, json: { approvals: await service.listApprovals(principal, params.guideId, revision) } };
217
+ },
218
+ },
219
+ {
220
+ method: 'POST',
221
+ path: '/guides/:guideId/releases',
222
+ operationId: 'releaseRevision',
223
+ summary: 'Publish an approved revision from a succeeded release build. Atomic and idempotent.',
224
+ role: 'publisher',
225
+ idempotent: true,
226
+ successStatus: 201,
227
+ handler: async ({ service, principal, params, body, headers }) => ({
228
+ status: 201,
229
+ json: await service.release(principal, params.guideId, { revision: str(body, 'revision'), jobId: str(body, 'jobId') }, { idempotencyKey: headers.idempotencyKey }),
230
+ }),
231
+ },
232
+ {
233
+ method: 'GET',
234
+ path: '/guides/:guideId/releases',
235
+ operationId: 'listReleases',
236
+ summary: 'List releases of a guide',
237
+ handler: async ({ service, principal, params }) => ({ status: 200, json: { releases: await service.listReleases(principal, params.guideId) } }),
238
+ },
239
+ {
240
+ method: 'GET',
241
+ path: '/guides/:guideId/releases/:releaseId',
242
+ operationId: 'getRelease',
243
+ summary: 'Get one release',
244
+ handler: async ({ service, principal, params }) => ({ status: 200, json: await service.getRelease(principal, params.guideId, params.releaseId) }),
245
+ },
246
+ {
247
+ method: 'GET',
248
+ path: '/guides/:guideId/releases/:releaseId/manifest',
249
+ operationId: 'getReleaseManifest',
250
+ summary: 'Get the manifest of a published release',
251
+ handler: async ({ service, principal, params }) => {
252
+ const { bytes } = await service.readReleaseArtifact(principal, params.guideId, params.releaseId, 'manifest.json');
253
+ return { status: 200, json: JSON.parse(Buffer.from(bytes).toString('utf8')) };
254
+ },
255
+ },
256
+ {
257
+ method: 'GET',
258
+ path: '/guides/:guideId/releases/:releaseId/artifacts/:artifactId',
259
+ operationId: 'downloadReleaseArtifact',
260
+ summary: 'Download one file of a published release (the edition and its companion files)',
261
+ handler: async ({ service, principal, params }) => {
262
+ const { descriptor, bytes } = await service.readReleaseArtifact(principal, params.guideId, params.releaseId, decodeURIComponent(params.artifactId));
263
+ return { status: 200, bytes, mediaType: descriptor.mediaType, filename: descriptor.path.split('/').pop() ?? 'artifact' };
264
+ },
265
+ },
266
+ ];
267
+ //# sourceMappingURL=routes.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"routes.js","sourceRoot":"","sources":["../src/routes.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,29 @@
1
1
  {
2
2
  "name": "@x12i/made-easy-api",
3
- "version": "0.0.0-stage",
4
- "stub": true,
5
- "description": "Temporary package placeholder for staged publishing"
6
- }
3
+ "version": "0.1.0",
4
+ "type": "module",
5
+ "description": "Made Easy HTTP API: a dependency-free node:http handler with bearer-token auth, tenant isolation, idempotent job endpoints and a generated OpenAPI document.",
6
+ "keywords": ["made-easy", "api", "http", "openapi", "x12i"],
7
+ "license": "MIT",
8
+ "author": "x12i",
9
+ "homepage": "https://github.com/x12i/made-easy#readme",
10
+ "repository": {
11
+ "type": "git",
12
+ "url": "git+https://github.com/x12i/made-easy.git",
13
+ "directory": "packages/api"
14
+ },
15
+ "bugs": { "url": "https://github.com/x12i/made-easy/issues" },
16
+ "engines": { "node": ">=22" },
17
+ "main": "./dist/index.js",
18
+ "types": "./dist/index.d.ts",
19
+ "exports": {
20
+ ".": { "types": "./dist/index.d.ts", "import": "./dist/index.js" },
21
+ "./package.json": "./package.json"
22
+ },
23
+ "files": ["dist", "README.md", "LICENSE"],
24
+ "publishConfig": { "access": "public" },
25
+ "dependencies": {
26
+ "@x12i/made-easy": "^0.1.0",
27
+ "@x12i/made-easy-service": "^0.1.0"
28
+ }
29
+ }