princejs 1.9.2 → 1.9.3
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/Readme.md +61 -1
- package/dist/prince.d.ts +51 -1
- package/dist/prince.d.ts.map +1 -1
- package/dist/prince.js +12801 -11
- package/dist/scheduler.d.ts +83 -6
- package/dist/scheduler.d.ts.map +1 -1
- package/dist/scheduler.js +54 -1
- package/package.json +1 -1
package/Readme.md
CHANGED
|
@@ -105,6 +105,55 @@ const app = prince();
|
|
|
105
105
|
app.plugin(usersPlugin, { prefix: "/api" });
|
|
106
106
|
```
|
|
107
107
|
|
|
108
|
+
### OpenAPI + Scalar Docs
|
|
109
|
+
|
|
110
|
+
Auto-generate an OpenAPI 3.0 spec and serve a beautiful [Scalar](https://scalar.com) API reference UI — all from a single `app.openapi()` call. Routes, validation, and docs stay in sync automatically.
|
|
111
|
+
|
|
112
|
+
```ts
|
|
113
|
+
import { prince } from "princejs";
|
|
114
|
+
import { z } from "zod";
|
|
115
|
+
|
|
116
|
+
const app = prince();
|
|
117
|
+
|
|
118
|
+
const api = app.openapi({ title: "My API", version: "1.0.0" }, "/docs", { theme: "moon" });
|
|
119
|
+
|
|
120
|
+
api.route("GET", "/users/:id", {
|
|
121
|
+
summary: "Get user by ID",
|
|
122
|
+
tags: ["users"],
|
|
123
|
+
schema: {
|
|
124
|
+
response: z.object({ id: z.string(), name: z.string() }),
|
|
125
|
+
},
|
|
126
|
+
}, (req) => ({ id: req.params!.id, name: "Alice" }));
|
|
127
|
+
|
|
128
|
+
api.route("POST", "/users", {
|
|
129
|
+
summary: "Create user",
|
|
130
|
+
tags: ["users"],
|
|
131
|
+
schema: {
|
|
132
|
+
body: z.object({ name: z.string().min(2), email: z.string().email() }),
|
|
133
|
+
response: z.object({ id: z.string(), name: z.string(), email: z.string() }),
|
|
134
|
+
},
|
|
135
|
+
}, (req) => ({ id: crypto.randomUUID(), ...req.parsedBody }));
|
|
136
|
+
|
|
137
|
+
app.listen(3000);
|
|
138
|
+
// → GET /docs Scalar UI
|
|
139
|
+
// → GET /docs.json Raw OpenAPI JSON
|
|
140
|
+
```
|
|
141
|
+
|
|
142
|
+
**`api.route()` does three things at once:**
|
|
143
|
+
- Registers the route on PrinceJS (same as `app.get()` / `app.post()`)
|
|
144
|
+
- Auto-wires `validate(schema.body)` middleware — no separate import needed
|
|
145
|
+
- Writes the full OpenAPI spec entry including path params, request body, query params, and response schema
|
|
146
|
+
|
|
147
|
+
| `schema` key | Runtime effect | Scalar docs |
|
|
148
|
+
|---|---|---|
|
|
149
|
+
| `body` | ✅ Validates & strips via `validate()` | ✅ requestBody model |
|
|
150
|
+
| `query` | ❌ docs only | ✅ typed query params |
|
|
151
|
+
| `response` | ❌ docs only | ✅ 200 response model |
|
|
152
|
+
|
|
153
|
+
Routes registered with `app.get()` / `app.post()` directly never appear in the docs — useful for internal health checks, webhooks, and admin endpoints.
|
|
154
|
+
|
|
155
|
+
**Available themes:** `default` · `moon` · `purple` · `solarized` · `bluePlanet` · `deepSpace` · `saturn` · `kepler` · `mars`
|
|
156
|
+
|
|
108
157
|
### Database (SQLite)
|
|
109
158
|
|
|
110
159
|
### End to End Type-Safety
|
|
@@ -203,7 +252,7 @@ import { prince } from "princejs";
|
|
|
203
252
|
import { cors, logger, rateLimit, auth, apiKey, jwt, session, compress, serve } from "princejs/middleware";
|
|
204
253
|
import { validate } from "princejs/validation";
|
|
205
254
|
import { cache, upload, sse } from "princejs/helpers";
|
|
206
|
-
import { cron } from "princejs/scheduler";
|
|
255
|
+
import { cron, openapi } from "princejs/scheduler";
|
|
207
256
|
import { Html, Head, Body, H1, P, render } from "princejs/jsx"
|
|
208
257
|
import { db } from "princejs/db";
|
|
209
258
|
import { z } from "zod";
|
|
@@ -285,6 +334,17 @@ app.get("/users", () => users.query("SELECT * FROM users"));
|
|
|
285
334
|
|
|
286
335
|
cron("*/1 * * * *", () => console.log("PrinceJS heartbeat"));
|
|
287
336
|
|
|
337
|
+
// OpenAPI + Scalar
|
|
338
|
+
const api = app.openapi({ title: "PrinceJS App", version: "1.0.0" }, "/docs");
|
|
339
|
+
api.route("GET", "/items", {
|
|
340
|
+
summary: "List items",
|
|
341
|
+
tags: ["items"],
|
|
342
|
+
schema: {
|
|
343
|
+
query: z.object({ q: z.string().optional() }),
|
|
344
|
+
response: z.array(z.object({ id: z.string(), name: z.string() })),
|
|
345
|
+
},
|
|
346
|
+
}, () => [{ id: "1", name: "Widget" }]);
|
|
347
|
+
|
|
288
348
|
app.listen(3000);
|
|
289
349
|
```
|
|
290
350
|
|
package/dist/prince.d.ts
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import type { OpenAPIBuilder, ScalarOptions } from "./scheduler";
|
|
2
|
+
import { z } from "zod";
|
|
1
3
|
type Next = () => Promise<Response>;
|
|
2
4
|
type Middleware = (req: PrinceRequest, next: Next) => Promise<Response | undefined> | Response | undefined;
|
|
3
5
|
type HandlerResult = Response | Record<string, any> | string | Uint8Array;
|
|
@@ -32,13 +34,30 @@ declare class ResponseBuilder {
|
|
|
32
34
|
redirect(url: string, status?: number): Response;
|
|
33
35
|
build(): Response;
|
|
34
36
|
}
|
|
37
|
+
export interface RouteSchema {
|
|
38
|
+
/** Zod schema for the request body — auto-wires validate() middleware */
|
|
39
|
+
body?: z.ZodTypeAny;
|
|
40
|
+
/** Zod schema for query parameters — written into the OpenAPI spec */
|
|
41
|
+
query?: z.ZodObject<any>;
|
|
42
|
+
/** Zod schema for the response body — written into the OpenAPI spec */
|
|
43
|
+
response?: z.ZodTypeAny;
|
|
44
|
+
}
|
|
45
|
+
export interface RouteOperation {
|
|
46
|
+
summary?: string;
|
|
47
|
+
description?: string;
|
|
48
|
+
tags?: string[];
|
|
49
|
+
/** Attach Zod schemas to auto-generate request/response models in Scalar */
|
|
50
|
+
schema?: RouteSchema;
|
|
51
|
+
responses?: Record<string, unknown>;
|
|
52
|
+
[key: string]: unknown;
|
|
53
|
+
}
|
|
35
54
|
export declare class Prince {
|
|
36
55
|
private devMode;
|
|
37
56
|
private rawRoutes;
|
|
38
57
|
private middlewares;
|
|
39
58
|
private errorHandler?;
|
|
40
59
|
private wsRoutes;
|
|
41
|
-
private
|
|
60
|
+
private openapiSpec;
|
|
42
61
|
private router;
|
|
43
62
|
private staticRoutes;
|
|
44
63
|
private staticMiddlewares;
|
|
@@ -77,6 +96,37 @@ export declare class Prince {
|
|
|
77
96
|
private executeHandler;
|
|
78
97
|
handleFetch(req: Request): Promise<Response>;
|
|
79
98
|
fetch(req: Request): Promise<Response>;
|
|
99
|
+
/**
|
|
100
|
+
* Mounts an OpenAPI spec + Scalar UI onto this Prince app.
|
|
101
|
+
*
|
|
102
|
+
* Calling this method returns an `OpenAPIBuilder` whose `.route()` method
|
|
103
|
+
* registers a route on the Prince app **and** writes the matching path entry
|
|
104
|
+
* into the OpenAPI spec simultaneously — so the two can never drift.
|
|
105
|
+
*
|
|
106
|
+
* Two routes are auto-registered:
|
|
107
|
+
* GET `docsPath` → Scalar UI (e.g. /docs)
|
|
108
|
+
* GET `docsPath`.json → Raw spec (e.g. /docs.json)
|
|
109
|
+
*
|
|
110
|
+
* @example
|
|
111
|
+
* const app = prince();
|
|
112
|
+
* const api = app.openapi({ title: "My API", version: "1.0.0" }, "/docs");
|
|
113
|
+
*
|
|
114
|
+
* // Registers GET /hello on Prince AND adds it to the OpenAPI spec
|
|
115
|
+
* api.route("GET", "/hello", {
|
|
116
|
+
* summary: "Say hello",
|
|
117
|
+
* responses: { 200: { description: "OK" } },
|
|
118
|
+
* }, (req) => ({ message: "hello" }));
|
|
119
|
+
*
|
|
120
|
+
* app.listen(3000);
|
|
121
|
+
* // → GET /docs → Scalar UI
|
|
122
|
+
* // → GET /docs.json → raw OpenAPI JSON
|
|
123
|
+
*/
|
|
124
|
+
openapi(info: {
|
|
125
|
+
title: string;
|
|
126
|
+
version: string;
|
|
127
|
+
}, docsPath?: string, scalarOptions?: ScalarOptions): OpenAPIBuilder & {
|
|
128
|
+
route: (method: string, path: string, operation: Record<string, unknown>, ...args: (RouteHandler | Middleware)[]) => OpenAPIBuilder;
|
|
129
|
+
};
|
|
80
130
|
listen(port?: number): void;
|
|
81
131
|
}
|
|
82
132
|
export declare const prince: (dev?: boolean) => Prince;
|
package/dist/prince.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"prince.d.ts","sourceRoot":"","sources":["../src/prince.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"prince.d.ts","sourceRoot":"","sources":["../src/prince.ts"],"names":[],"mappings":"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"}
|