yedra 0.20.6 → 0.20.7

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.
@@ -8,6 +8,7 @@ import { context, propagation, SpanKind, trace } from '@opentelemetry/api';
8
8
  import mime from 'mime';
9
9
  import { WebSocketServer } from 'ws';
10
10
  import { Counter } from '../util/counter.js';
11
+ import { collectLazySchemas } from '../validation/lazy.js';
11
12
  import { HttpError } from './errors.js';
12
13
  import { Path } from './path.js';
13
14
  import { RestEndpoint } from './rest.js';
@@ -380,18 +381,23 @@ export class Yedra {
380
381
  generateDocs(options) {
381
382
  // this set will be filled with the security schemes from all endpoints
382
383
  const securitySchemes = new Set();
383
- const paths = {};
384
- for (const route of this.restRoutes) {
385
- if (route.endpoint.isHidden()) {
386
- // do not include hidden endpoints in the documentation
387
- continue;
384
+ // Wrap path generation in collectLazySchemas so that any LazySchema
385
+ // whose documentation() is called will register its full definition.
386
+ const { result: paths, schemas } = collectLazySchemas(() => {
387
+ const paths = {};
388
+ for (const route of this.restRoutes) {
389
+ if (route.endpoint.isHidden()) {
390
+ // do not include hidden endpoints in the documentation
391
+ continue;
392
+ }
393
+ const path = route.path.toString();
394
+ const methods = paths[path] ?? {};
395
+ methods[route.endpoint.method.toLowerCase()] =
396
+ route.endpoint.documentation(path, securitySchemes);
397
+ paths[path] = methods;
388
398
  }
389
- const path = route.path.toString();
390
- const methods = paths[path] ?? {};
391
- methods[route.endpoint.method.toLowerCase()] =
392
- route.endpoint.documentation(path, securitySchemes);
393
- paths[path] = methods;
394
- }
399
+ return paths;
400
+ });
395
401
  return {
396
402
  openapi: '3.0.2',
397
403
  info: {
@@ -404,6 +410,7 @@ export class Yedra {
404
410
  securitySchemes: Object.fromEntries(securitySchemes
405
411
  .values()
406
412
  .map((scheme) => [scheme.name, scheme.scheme])),
413
+ schemas: Object.fromEntries(schemas),
407
414
  },
408
415
  servers: options?.servers ?? [],
409
416
  paths,
@@ -4,6 +4,7 @@ export { date } from './validation/date.js';
4
4
  export { _enum as enum } from './validation/enum.js';
5
5
  export { ValidationError } from './validation/error.js';
6
6
  export { integer } from './validation/integer.js';
7
+ export { lazy } from './validation/lazy.js';
7
8
  export { array } from './validation/modifiable.js';
8
9
  export { _null as null } from './validation/null.js';
9
10
  export { number } from './validation/number.js';
@@ -7,6 +7,7 @@ export { date } from './validation/date.js';
7
7
  export { _enum as enum } from './validation/enum.js';
8
8
  export { ValidationError } from './validation/error.js';
9
9
  export { integer } from './validation/integer.js';
10
+ export { lazy } from './validation/lazy.js';
10
11
  export { array } from './validation/modifiable.js';
11
12
  export { _null as null } from './validation/null.js';
12
13
  export { number } from './validation/number.js';
@@ -1,4 +1,4 @@
1
- import { Schema } from "./schema.js";
1
+ import { Schema } from './schema.js';
2
2
  export declare class DocSchema<T> extends Schema<T> {
3
3
  private readonly _schema;
4
4
  private readonly _description;
@@ -1,4 +1,4 @@
1
- import { Schema } from "./schema.js";
1
+ import { Schema } from './schema.js';
2
2
  export class DocSchema extends Schema {
3
3
  constructor(schema, description, example) {
4
4
  super();
@@ -1,4 +1,4 @@
1
- import { ModifiableSchema } from "./modifiable.js";
1
+ import { ModifiableSchema } from './modifiable.js';
2
2
  declare class IntegerSchema extends ModifiableSchema<number> {
3
3
  private readonly minValue?;
4
4
  private readonly maxValue?;
@@ -1,5 +1,5 @@
1
- import { Issue, ValidationError } from "./error.js";
2
- import { ModifiableSchema } from "./modifiable.js";
1
+ import { Issue, ValidationError } from './error.js';
2
+ import { ModifiableSchema } from './modifiable.js';
3
3
  class IntegerSchema extends ModifiableSchema {
4
4
  constructor(min, max) {
5
5
  super();
@@ -12,7 +12,7 @@ class IntegerSchema extends ModifiableSchema {
12
12
  */
13
13
  min(value) {
14
14
  if (!Number.isInteger(value)) {
15
- throw new Error("minimum value has to be an integer");
15
+ throw new Error('minimum value has to be an integer');
16
16
  }
17
17
  return new IntegerSchema(value, this.maxValue);
18
18
  }
@@ -22,17 +22,17 @@ class IntegerSchema extends ModifiableSchema {
22
22
  */
23
23
  max(value) {
24
24
  if (!Number.isInteger(value)) {
25
- throw new Error("maximum value has to be an integer");
25
+ throw new Error('maximum value has to be an integer');
26
26
  }
27
27
  return new IntegerSchema(this.minValue, value);
28
28
  }
29
29
  parse(obj) {
30
- if (typeof obj !== "number" && typeof obj !== "string") {
30
+ if (typeof obj !== 'number' && typeof obj !== 'string') {
31
31
  throw new ValidationError([
32
32
  new Issue([], `Expected number but got ${typeof obj}`),
33
33
  ]);
34
34
  }
35
- const num = typeof obj === "number" ? obj : Number.parseFloat(obj);
35
+ const num = typeof obj === 'number' ? obj : Number.parseFloat(obj);
36
36
  if (Number.isNaN(num) || !Number.isInteger(num)) {
37
37
  throw new ValidationError([
38
38
  new Issue([], `Expected integer but got ${typeof obj}`),
@@ -52,7 +52,7 @@ class IntegerSchema extends ModifiableSchema {
52
52
  }
53
53
  documentation() {
54
54
  return {
55
- type: "integer",
55
+ type: 'integer',
56
56
  ...(this.minValue !== undefined && { minimum: this.minValue }),
57
57
  ...(this.maxValue !== undefined && { maximum: this.maxValue }),
58
58
  };
@@ -0,0 +1,48 @@
1
+ import { ModifiableSchema } from './modifiable.js';
2
+ import type { Schema } from './schema.js';
3
+ /**
4
+ * Run a function while collecting lazy schema definitions.
5
+ * Any `LazySchema` whose `documentation()` is called during `fn`
6
+ * will register its full definition in the returned map.
7
+ */
8
+ export declare function collectLazySchemas<T>(fn: () => T): {
9
+ result: T;
10
+ schemas: Map<string, object>;
11
+ };
12
+ /**
13
+ * A schema that defers evaluation to support recursive definitions.
14
+ * The getter function is called lazily on each parse/documentation
15
+ * invocation, breaking the circular reference at definition time.
16
+ *
17
+ * Usage:
18
+ * ```typescript
19
+ * interface Category {
20
+ * name: string;
21
+ * subcategories: Category[];
22
+ * }
23
+ *
24
+ * const category: LazySchema<Category> = y.lazy("Category", () =>
25
+ * y.object({
26
+ * name: y.string(),
27
+ * subcategories: category.array(),
28
+ * }),
29
+ * );
30
+ * ```
31
+ */
32
+ export declare class LazySchema<T> extends ModifiableSchema<T> {
33
+ readonly schemaName: string;
34
+ private readonly getter;
35
+ constructor(name: string, getter: () => Schema<T>);
36
+ parse(obj: unknown): T;
37
+ documentation(): object;
38
+ private registerSchema;
39
+ isOptional(): boolean;
40
+ }
41
+ /**
42
+ * Create a lazily-evaluated schema for recursive type definitions.
43
+ * @param name - The schema name, used for `$ref` in OpenAPI documentation.
44
+ * @param getter - A function that returns the schema. Called at
45
+ * parse time, not at definition time, so circular references
46
+ * are safe.
47
+ */
48
+ export declare const lazy: <T>(name: string, getter: () => Schema<T>) => LazySchema<T>;
@@ -0,0 +1,78 @@
1
+ import { ModifiableSchema } from './modifiable.js';
2
+ /**
3
+ * Temporary context used during OpenAPI doc generation to accumulate
4
+ * lazy schema definitions. Set by `collectLazySchemas()`, read by
5
+ * `LazySchema.documentation()`. Not a persistent global registry —
6
+ * only lives for the duration of a single doc generation call.
7
+ */
8
+ let schemaCollector = null;
9
+ /**
10
+ * Run a function while collecting lazy schema definitions.
11
+ * Any `LazySchema` whose `documentation()` is called during `fn`
12
+ * will register its full definition in the returned map.
13
+ */
14
+ export function collectLazySchemas(fn) {
15
+ const schemas = new Map();
16
+ schemaCollector = schemas;
17
+ try {
18
+ const result = fn();
19
+ return { result, schemas };
20
+ }
21
+ finally {
22
+ schemaCollector = null;
23
+ }
24
+ }
25
+ /**
26
+ * A schema that defers evaluation to support recursive definitions.
27
+ * The getter function is called lazily on each parse/documentation
28
+ * invocation, breaking the circular reference at definition time.
29
+ *
30
+ * Usage:
31
+ * ```typescript
32
+ * interface Category {
33
+ * name: string;
34
+ * subcategories: Category[];
35
+ * }
36
+ *
37
+ * const category: LazySchema<Category> = y.lazy("Category", () =>
38
+ * y.object({
39
+ * name: y.string(),
40
+ * subcategories: category.array(),
41
+ * }),
42
+ * );
43
+ * ```
44
+ */
45
+ export class LazySchema extends ModifiableSchema {
46
+ constructor(name, getter) {
47
+ super();
48
+ this.schemaName = name;
49
+ this.getter = getter;
50
+ }
51
+ parse(obj) {
52
+ return this.getter().parse(obj);
53
+ }
54
+ documentation() {
55
+ if (schemaCollector && !schemaCollector.has(this.schemaName)) {
56
+ this.registerSchema(schemaCollector);
57
+ }
58
+ return { $ref: `#/components/schemas/${this.schemaName}` };
59
+ }
60
+ registerSchema(collector) {
61
+ // Set a placeholder first to break infinite recursion —
62
+ // if the getter references this schema, documentation()
63
+ // will see the key already exists and skip re-registration.
64
+ collector.set(this.schemaName, {});
65
+ collector.set(this.schemaName, this.getter().documentation());
66
+ }
67
+ isOptional() {
68
+ return this.getter().isOptional();
69
+ }
70
+ }
71
+ /**
72
+ * Create a lazily-evaluated schema for recursive type definitions.
73
+ * @param name - The schema name, used for `$ref` in OpenAPI documentation.
74
+ * @param getter - A function that returns the schema. Called at
75
+ * parse time, not at definition time, so circular references
76
+ * are safe.
77
+ */
78
+ export const lazy = (name, getter) => new LazySchema(name, getter);
@@ -1,6 +1,6 @@
1
- import type { Typeof } from "./body.js";
2
- import { DocSchema } from "./doc.js";
3
- import { Schema } from "./schema.js";
1
+ import type { Typeof } from './body.js';
2
+ import { DocSchema } from './doc.js';
3
+ import { Schema } from './schema.js';
4
4
  export declare abstract class ModifiableSchema<T> extends Schema<T> {
5
5
  /**
6
6
  * Mark this schema as optional.
@@ -1,6 +1,6 @@
1
- import { DocSchema } from "./doc.js";
2
- import { Issue, ValidationError } from "./error.js";
3
- import { Schema } from "./schema.js";
1
+ import { DocSchema } from './doc.js';
2
+ import { Issue, ValidationError } from './error.js';
3
+ import { Schema } from './schema.js';
4
4
  export class ModifiableSchema extends Schema {
5
5
  /**
6
6
  * Mark this schema as optional.
@@ -105,7 +105,7 @@ export class RefinedSchema extends ModifiableSchema {
105
105
  */
106
106
  min(value) {
107
107
  const docs = this.documentation();
108
- const isArray = docs.type === "array";
108
+ const isArray = docs.type === 'array';
109
109
  return this.refine(((v) => {
110
110
  const len = v.length;
111
111
  return (len >= value ||
@@ -120,7 +120,7 @@ export class RefinedSchema extends ModifiableSchema {
120
120
  */
121
121
  max(value) {
122
122
  const docs = this.documentation();
123
- const isArray = docs.type === "array";
123
+ const isArray = docs.type === 'array';
124
124
  return this.refine(((v) => {
125
125
  const len = v.length;
126
126
  return (len <= value ||
@@ -142,7 +142,7 @@ export class RefinedSchema extends ModifiableSchema {
142
142
  if (result === true) {
143
143
  return parsed;
144
144
  }
145
- const message = typeof result === "string" ? result : "Validation failed";
145
+ const message = typeof result === 'string' ? result : 'Validation failed';
146
146
  throw new ValidationError([new Issue([], message)]);
147
147
  }
148
148
  documentation() {
@@ -210,7 +210,7 @@ export class ArraySchema extends ModifiableSchema {
210
210
  }
211
211
  documentation() {
212
212
  return {
213
- type: "array",
213
+ type: 'array',
214
214
  items: this.itemSchema.documentation(),
215
215
  };
216
216
  }
@@ -1,4 +1,4 @@
1
- import { ModifiableSchema } from "./modifiable.js";
1
+ import { ModifiableSchema } from './modifiable.js';
2
2
  declare class NumberSchema extends ModifiableSchema<number> {
3
3
  private readonly minValue?;
4
4
  private readonly maxValue?;
@@ -1,5 +1,5 @@
1
- import { Issue, ValidationError } from "./error.js";
2
- import { ModifiableSchema } from "./modifiable.js";
1
+ import { Issue, ValidationError } from './error.js';
2
+ import { ModifiableSchema } from './modifiable.js';
3
3
  class NumberSchema extends ModifiableSchema {
4
4
  constructor(min, max) {
5
5
  super();
@@ -21,12 +21,12 @@ class NumberSchema extends ModifiableSchema {
21
21
  return new NumberSchema(this.minValue, value);
22
22
  }
23
23
  parse(obj) {
24
- if (typeof obj !== "number" && typeof obj !== "string") {
24
+ if (typeof obj !== 'number' && typeof obj !== 'string') {
25
25
  throw new ValidationError([
26
26
  new Issue([], `Expected number but got ${typeof obj}`),
27
27
  ]);
28
28
  }
29
- const num = typeof obj === "number" ? obj : Number.parseFloat(obj);
29
+ const num = typeof obj === 'number' ? obj : Number.parseFloat(obj);
30
30
  if (Number.isNaN(num)) {
31
31
  throw new ValidationError([
32
32
  new Issue([], `Expected number but got ${typeof obj}`),
@@ -46,7 +46,7 @@ class NumberSchema extends ModifiableSchema {
46
46
  }
47
47
  documentation() {
48
48
  return {
49
- type: "number",
49
+ type: 'number',
50
50
  ...(this.minValue !== undefined && { minimum: this.minValue }),
51
51
  ...(this.maxValue !== undefined && { maximum: this.maxValue }),
52
52
  };
@@ -1,6 +1,6 @@
1
- import type { Typeof } from "./body.js";
2
- import { ModifiableSchema } from "./modifiable.js";
3
- import { Schema } from "./schema.js";
1
+ import type { Typeof } from './body.js';
2
+ import { ModifiableSchema } from './modifiable.js';
3
+ import { Schema } from './schema.js';
4
4
  /**
5
5
  * Make a union of all keys that are not extended by undefined
6
6
  * (i.e. have undefined as a variant) of the specified type.
@@ -1,6 +1,6 @@
1
- import { Issue, ValidationError } from "./error.js";
2
- import { ModifiableSchema } from "./modifiable.js";
3
- import { Schema } from "./schema.js";
1
+ import { Issue, ValidationError } from './error.js';
2
+ import { ModifiableSchema } from './modifiable.js';
3
+ import { Schema } from './schema.js';
4
4
  export class ObjectSchema extends ModifiableSchema {
5
5
  constructor(shape, lax) {
6
6
  super();
@@ -8,14 +8,14 @@ export class ObjectSchema extends ModifiableSchema {
8
8
  this.lax = lax;
9
9
  }
10
10
  parse(obj) {
11
- if (typeof obj !== "object") {
11
+ if (typeof obj !== 'object') {
12
12
  throw new ValidationError([
13
13
  new Issue([], `Expected object but got ${typeof obj}`),
14
14
  ]);
15
15
  }
16
16
  if (obj == null) {
17
17
  throw new ValidationError([
18
- new Issue([], "Expected object but got null"),
18
+ new Issue([], 'Expected object but got null'),
19
19
  ]);
20
20
  }
21
21
  const result = {};
@@ -24,7 +24,7 @@ export class ObjectSchema extends ModifiableSchema {
24
24
  const propSchema = this.shape[prop];
25
25
  if (propSchema instanceof Schema) {
26
26
  if (!(prop in obj || propSchema.isOptional())) {
27
- issues.push(new Issue([prop], "Required"));
27
+ issues.push(new Issue([prop], 'Required'));
28
28
  continue;
29
29
  }
30
30
  try {
@@ -45,7 +45,7 @@ export class ObjectSchema extends ModifiableSchema {
45
45
  if (prop in this.shape) {
46
46
  continue;
47
47
  }
48
- issues.push(new Issue([prop], "Unrecognized"));
48
+ issues.push(new Issue([prop], 'Unrecognized'));
49
49
  }
50
50
  }
51
51
  if (issues.length > 0) {
@@ -66,7 +66,7 @@ export class ObjectSchema extends ModifiableSchema {
66
66
  }
67
67
  }
68
68
  return {
69
- type: "object",
69
+ type: 'object',
70
70
  properties,
71
71
  additionalProperties: this.lax,
72
72
  ...(required.length > 0 && { required }),
@@ -1,6 +1,6 @@
1
- import type { Readable } from "node:stream";
2
- import type { StandardSchemaV1 } from "@standard-schema/spec";
3
- import { BodyType } from "./body.js";
1
+ import type { Readable } from 'node:stream';
2
+ import type { StandardSchemaV1 } from '@standard-schema/spec';
3
+ import { BodyType } from './body.js';
4
4
  /**
5
5
  * The base class for all schemas.
6
6
  */
@@ -31,5 +31,5 @@ export declare abstract class Schema<T> extends BodyType<T, T> implements Standa
31
31
  *
32
32
  * @see https://standardschema.dev/
33
33
  */
34
- get "~standard"(): StandardSchemaV1.Props<T, T>;
34
+ get '~standard'(): StandardSchemaV1.Props<T, T>;
35
35
  }
@@ -1,5 +1,5 @@
1
- import { BodyType } from "./body.js";
2
- import { Issue, ValidationError } from "./error.js";
1
+ import { BodyType } from './body.js';
2
+ import { Issue, ValidationError } from './error.js';
3
3
  /**
4
4
  * The base class for all schemas.
5
5
  */
@@ -8,22 +8,22 @@ export class Schema extends BodyType {
8
8
  // Lazy import to keep this module browser-safe for yedra/schema.
9
9
  // deserialize() is only called server-side, so the Node-specific
10
10
  // stream utility is never resolved when bundled for the frontend.
11
- const { readableToBuffer } = await import("../util/stream.js");
11
+ const { readableToBuffer } = await import('../util/stream.js');
12
12
  const buffer = await readableToBuffer(stream);
13
13
  if (buffer.length === 0) {
14
14
  return this.parse({});
15
15
  }
16
- if (contentType !== "application/json") {
16
+ if (contentType !== 'application/json') {
17
17
  throw new ValidationError([
18
18
  new Issue([], `Expected content type \`application/json\`, but got \`${contentType}\``),
19
19
  ]);
20
20
  }
21
- const data = JSON.parse(Buffer.from(buffer).toString("utf8"));
21
+ const data = JSON.parse(Buffer.from(buffer).toString('utf8'));
22
22
  return this.parse(data);
23
23
  }
24
24
  bodyDocs() {
25
25
  return {
26
- "application/json": {
26
+ 'application/json': {
27
27
  schema: this.documentation(),
28
28
  },
29
29
  };
@@ -44,10 +44,10 @@ export class Schema extends BodyType {
44
44
  *
45
45
  * @see https://standardschema.dev/
46
46
  */
47
- get "~standard"() {
47
+ get '~standard'() {
48
48
  return {
49
49
  version: 1,
50
- vendor: "yedra",
50
+ vendor: 'yedra',
51
51
  types: {},
52
52
  // Wraps parse() to match Standard Schema's non-throwing convention:
53
53
  // returns { value } on success, { issues } on failure.
@@ -1,4 +1,4 @@
1
- import { ModifiableSchema } from "./modifiable.js";
1
+ import { ModifiableSchema } from './modifiable.js';
2
2
  declare class StringSchema extends ModifiableSchema<string> {
3
3
  /**
4
4
  * Set the minimum length the string is allowed to be.
@@ -1,5 +1,5 @@
1
- import { Issue, ValidationError } from "./error.js";
2
- import { ModifiableSchema } from "./modifiable.js";
1
+ import { Issue, ValidationError } from './error.js';
2
+ import { ModifiableSchema } from './modifiable.js';
3
3
  const EMAIL_REGEX = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
4
4
  class StringSchema extends ModifiableSchema {
5
5
  /**
@@ -20,8 +20,8 @@ class StringSchema extends ModifiableSchema {
20
20
  * Require the string to be a valid email address.
21
21
  */
22
22
  email() {
23
- return this.refine((s) => EMAIL_REGEX.test(s) || "Expected email address", {
24
- format: "email",
23
+ return this.refine((s) => EMAIL_REGEX.test(s) || 'Expected email address', {
24
+ format: 'email',
25
25
  });
26
26
  }
27
27
  /**
@@ -32,7 +32,7 @@ class StringSchema extends ModifiableSchema {
32
32
  return this.refine((s) => pattern.test(s) || `Does not match pattern /${pattern.source}/`, { pattern: pattern.source });
33
33
  }
34
34
  parse(obj) {
35
- if (typeof obj !== "string") {
35
+ if (typeof obj !== 'string') {
36
36
  throw new ValidationError([
37
37
  new Issue([], `Expected string but got ${typeof obj}`),
38
38
  ]);
@@ -41,7 +41,7 @@ class StringSchema extends ModifiableSchema {
41
41
  }
42
42
  documentation() {
43
43
  return {
44
- type: "string",
44
+ type: 'string',
45
45
  };
46
46
  }
47
47
  }
package/package.json CHANGED
@@ -1,53 +1,53 @@
1
1
  {
2
- "name": "yedra",
3
- "version": "0.20.6",
4
- "repository": "github:0codekit/yedra",
5
- "main": "dist/index.js",
6
- "exports": {
7
- ".": {
8
- "types": "./dist/index.d.ts",
9
- "default": "./dist/index.js"
10
- },
11
- "./schema": {
12
- "types": "./dist/schema.d.ts",
13
- "default": "./dist/schema.js"
14
- }
15
- },
16
- "devDependencies": {
17
- "@biomejs/biome": "^2.4.4",
18
- "@types/bun": "^1.3.9",
19
- "@types/node": "^25.3.0",
20
- "@types/uuid": "^11.0.0",
21
- "@types/ws": "^8.18.1",
22
- "typescript": "^5.9.3"
23
- },
24
- "bugs": "https://github.com/0codekit/yedra/issues",
25
- "contributors": [
26
- "Justus Zorn <jzorn@wemakefuture.com>"
27
- ],
28
- "description": "A TypeScript web framework with OpenAPI generation.",
29
- "keywords": [
30
- "typescript",
31
- "web",
32
- "http",
33
- "schema",
34
- "validation",
35
- "openapi"
36
- ],
37
- "license": "MIT",
38
- "files": [
39
- "./dist/**"
40
- ],
41
- "scripts": {
42
- "check": "biome check src/*"
43
- },
44
- "types": "dist/index.d.ts",
45
- "type": "module",
46
- "dependencies": {
47
- "@opentelemetry/api": "^1.9.0",
48
- "@standard-schema/spec": "^1.1.0",
49
- "mime": "^4.1.0",
50
- "uuid": "^13.0.0",
51
- "ws": "^8.19.0"
52
- }
2
+ "name": "yedra",
3
+ "version": "0.20.7",
4
+ "repository": "github:0codekit/yedra",
5
+ "main": "dist/index.js",
6
+ "exports": {
7
+ ".": {
8
+ "types": "./dist/index.d.ts",
9
+ "default": "./dist/index.js"
10
+ },
11
+ "./schema": {
12
+ "types": "./dist/schema.d.ts",
13
+ "default": "./dist/schema.js"
14
+ }
15
+ },
16
+ "devDependencies": {
17
+ "@biomejs/biome": "^2.4.5",
18
+ "@types/bun": "^1.3.10",
19
+ "@types/node": "^25.3.3",
20
+ "@types/uuid": "^11.0.0",
21
+ "@types/ws": "^8.18.1",
22
+ "typescript": "^5.9.3"
23
+ },
24
+ "bugs": "https://github.com/0codekit/yedra/issues",
25
+ "contributors": [
26
+ "Justus Zorn <jzorn@wemakefuture.com>"
27
+ ],
28
+ "description": "A TypeScript web framework with OpenAPI generation.",
29
+ "keywords": [
30
+ "typescript",
31
+ "web",
32
+ "http",
33
+ "schema",
34
+ "validation",
35
+ "openapi"
36
+ ],
37
+ "license": "MIT",
38
+ "files": [
39
+ "./dist/**"
40
+ ],
41
+ "scripts": {
42
+ "check": "biome check src/*"
43
+ },
44
+ "types": "dist/index.d.ts",
45
+ "type": "module",
46
+ "dependencies": {
47
+ "@opentelemetry/api": "^1.9.0",
48
+ "@standard-schema/spec": "^1.1.0",
49
+ "mime": "^4.1.0",
50
+ "uuid": "^13.0.0",
51
+ "ws": "^8.19.0"
52
+ }
53
53
  }