@aggiovato/yrest 0.1.1 → 0.2.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/README.md +201 -28
- package/dist/cli/index.js +569 -59
- package/dist/cli/index.mjs +569 -59
- package/dist/index.d.mts +124 -3
- package/dist/index.d.ts +124 -3
- package/dist/index.js +494 -44
- package/dist/index.mjs +494 -44
- package/package.json +13 -4
package/dist/index.d.mts
CHANGED
|
@@ -2,37 +2,158 @@ import * as fastify from 'fastify';
|
|
|
2
2
|
import * as http from 'http';
|
|
3
3
|
import { z } from 'zod';
|
|
4
4
|
|
|
5
|
+
/** A single REST resource item. Field names and value types are user-defined in the YAML file. */
|
|
5
6
|
type Resource = Record<string, unknown>;
|
|
6
|
-
|
|
7
|
+
/**
|
|
8
|
+
* The full in-memory database.
|
|
9
|
+
* Keys are collection names (e.g. `"users"`); values are arrays of {@link Resource} items.
|
|
10
|
+
*/
|
|
11
|
+
type Data = Record<string, Resource[]>;
|
|
12
|
+
/**
|
|
13
|
+
* Relational mappings declared under `_rel` in the YAML file.
|
|
14
|
+
*
|
|
15
|
+
* - Outer key: child collection name.
|
|
16
|
+
* - Inner key: foreign key field on the child.
|
|
17
|
+
* - Inner value: parent collection name.
|
|
18
|
+
*
|
|
19
|
+
* @example
|
|
20
|
+
* // Given: _rel: { posts: { userId: users } }
|
|
21
|
+
* // GET /users/1/posts → returns posts where userId === "1"
|
|
22
|
+
*/
|
|
7
23
|
type Relations = Record<string, Record<string, string>>;
|
|
8
24
|
|
|
25
|
+
/**
|
|
26
|
+
* In-memory store backed by a YAML file.
|
|
27
|
+
*
|
|
28
|
+
* All reads operate on a live in-memory snapshot. Writes must be explicitly
|
|
29
|
+
* flushed to disk by calling {@link persist}. Use {@link reload} to pull in
|
|
30
|
+
* changes made to the file externally (e.g. in watch mode).
|
|
31
|
+
*/
|
|
9
32
|
interface YamlStorage {
|
|
10
|
-
|
|
33
|
+
/** Returns the full in-memory dataset (all collections). */
|
|
34
|
+
getData(): Data;
|
|
35
|
+
/** Returns the relational mappings declared under `_rel`. */
|
|
11
36
|
getRelations(): Relations;
|
|
37
|
+
/**
|
|
38
|
+
* Returns the items in a named collection, or `undefined` if it does not exist.
|
|
39
|
+
*
|
|
40
|
+
* @param name - Collection name as declared in the YAML file (e.g. `"users"`).
|
|
41
|
+
*/
|
|
12
42
|
getCollection(name: string): Resource[] | undefined;
|
|
43
|
+
/**
|
|
44
|
+
* Replaces the items of a named collection in memory.
|
|
45
|
+
* Call {@link persist} afterwards to flush the change to disk.
|
|
46
|
+
*
|
|
47
|
+
* @param name - Collection name.
|
|
48
|
+
* @param items - New array of items to store.
|
|
49
|
+
*/
|
|
13
50
|
setCollection(name: string, items: Resource[]): void;
|
|
51
|
+
/**
|
|
52
|
+
* Atomically writes the current in-memory state to the YAML file.
|
|
53
|
+
*
|
|
54
|
+
* Uses a write-to-temp-then-rename strategy so a crash during the write
|
|
55
|
+
* never leaves the file in a partially written state.
|
|
56
|
+
*
|
|
57
|
+
* @throws {Error} If the filesystem write or rename fails.
|
|
58
|
+
*/
|
|
14
59
|
persist(): void;
|
|
60
|
+
/**
|
|
61
|
+
* Reloads the YAML file from disk and updates the in-memory state in place.
|
|
62
|
+
*
|
|
63
|
+
* Mutates the existing `data` and `relations` objects rather than replacing them,
|
|
64
|
+
* so any code holding a reference to the storage instance sees the updated values
|
|
65
|
+
* without needing to re-fetch.
|
|
66
|
+
*
|
|
67
|
+
* @throws {Error} If the file cannot be read or the YAML is malformed.
|
|
68
|
+
*/
|
|
69
|
+
reload(): void;
|
|
15
70
|
}
|
|
71
|
+
/**
|
|
72
|
+
* Creates a {@link YamlStorage} instance backed by the given YAML file.
|
|
73
|
+
*
|
|
74
|
+
* The file is read and parsed eagerly on construction. The `_rel` key is
|
|
75
|
+
* extracted as relational metadata; all other top-level keys become collections.
|
|
76
|
+
*
|
|
77
|
+
* @param filePath - Relative or absolute path to the YAML database file.
|
|
78
|
+
* @throws {Error} If the file cannot be read or its YAML is invalid.
|
|
79
|
+
*/
|
|
16
80
|
declare function createYamlStorage(filePath: string): YamlStorage;
|
|
17
81
|
|
|
82
|
+
/**
|
|
83
|
+
* Zod schema for all server runtime options.
|
|
84
|
+
*
|
|
85
|
+
* Validates and normalises options from three sources in ascending priority:
|
|
86
|
+
* schema defaults → `yrest.config.yml` → explicit CLI flags.
|
|
87
|
+
*/
|
|
18
88
|
declare const serverOptionsSchema: z.ZodObject<{
|
|
89
|
+
/** Path to the YAML database file. Must be a non-empty string. */
|
|
19
90
|
file: z.ZodString;
|
|
91
|
+
/** TCP port the server listens on. Accepts string input and coerces to number. */
|
|
20
92
|
port: z.ZodDefault<z.ZodNumber>;
|
|
93
|
+
/** Hostname or IP address to bind. */
|
|
21
94
|
host: z.ZodDefault<z.ZodString>;
|
|
95
|
+
/**
|
|
96
|
+
* URL prefix prepended to every route (e.g. `/api`).
|
|
97
|
+
* A leading slash is added automatically if omitted.
|
|
98
|
+
*/
|
|
22
99
|
base: z.ZodEffects<z.ZodDefault<z.ZodString>, string, string | undefined>;
|
|
100
|
+
/** When `true`, the server reloads the YAML file automatically on disk changes. */
|
|
101
|
+
watch: z.ZodDefault<z.ZodBoolean>;
|
|
102
|
+
/** When `true`, all mutating requests (POST, PUT, PATCH, DELETE) are rejected with 405. */
|
|
103
|
+
readonly: z.ZodDefault<z.ZodBoolean>;
|
|
104
|
+
/** Milliseconds to delay every response, simulating network latency. `0` = disabled. */
|
|
105
|
+
delay: z.ZodDefault<z.ZodNumber>;
|
|
106
|
+
/**
|
|
107
|
+
* Wraps GET collection responses in a `{ data, pagination }` envelope.
|
|
108
|
+
* Accepts `true` (default limit 10), `false` (disabled), or a positive integer (custom limit).
|
|
109
|
+
*/
|
|
110
|
+
pageable: z.ZodEffects<z.ZodDefault<z.ZodUnion<[z.ZodBoolean, z.ZodNumber]>>, {
|
|
111
|
+
enabled: boolean;
|
|
112
|
+
limit: number;
|
|
113
|
+
}, number | boolean | undefined>;
|
|
23
114
|
}, "strip", z.ZodTypeAny, {
|
|
24
115
|
file: string;
|
|
25
116
|
port: number;
|
|
26
117
|
host: string;
|
|
27
118
|
base: string;
|
|
119
|
+
watch: boolean;
|
|
120
|
+
readonly: boolean;
|
|
121
|
+
delay: number;
|
|
122
|
+
pageable: {
|
|
123
|
+
enabled: boolean;
|
|
124
|
+
limit: number;
|
|
125
|
+
};
|
|
28
126
|
}, {
|
|
29
127
|
file: string;
|
|
30
128
|
port?: number | undefined;
|
|
31
129
|
host?: string | undefined;
|
|
32
130
|
base?: string | undefined;
|
|
131
|
+
watch?: boolean | undefined;
|
|
132
|
+
readonly?: boolean | undefined;
|
|
133
|
+
delay?: number | undefined;
|
|
134
|
+
pageable?: number | boolean | undefined;
|
|
33
135
|
}>;
|
|
136
|
+
/**
|
|
137
|
+
* Resolved server configuration after Zod validation and transformation.
|
|
138
|
+
* Inferred from {@link serverOptionsSchema}.
|
|
139
|
+
*/
|
|
34
140
|
type ServerOptions = z.infer<typeof serverOptionsSchema>;
|
|
35
141
|
|
|
142
|
+
/**
|
|
143
|
+
* Creates and configures a Fastify instance wired to the given YAML storage.
|
|
144
|
+
*
|
|
145
|
+
* Registers, in order:
|
|
146
|
+
* 1. CORS (all origins, permissive defaults).
|
|
147
|
+
* 2. Readonly guard hook — rejects mutating requests with 405 when enabled.
|
|
148
|
+
* 3. Delay hook — defers `onSend` by N ms when enabled.
|
|
149
|
+
* 4. All resource routes derived from the storage collections.
|
|
150
|
+
*
|
|
151
|
+
* The server is returned before `listen()` is called so tests can inject
|
|
152
|
+
* requests without binding a real port.
|
|
153
|
+
*
|
|
154
|
+
* @param storage - Initialised YAML storage instance.
|
|
155
|
+
* @param options - Validated server options.
|
|
156
|
+
*/
|
|
36
157
|
declare function createServer(storage: YamlStorage, options: ServerOptions): Promise<fastify.FastifyInstance<http.Server<typeof http.IncomingMessage, typeof http.ServerResponse>, http.IncomingMessage, http.ServerResponse<http.IncomingMessage>, fastify.FastifyBaseLogger, fastify.FastifyTypeProviderDefault>>;
|
|
37
158
|
|
|
38
|
-
export { type
|
|
159
|
+
export { type Data, type Relations, type Resource, type ServerOptions, createServer, createYamlStorage, serverOptionsSchema };
|
package/dist/index.d.ts
CHANGED
|
@@ -2,37 +2,158 @@ import * as fastify from 'fastify';
|
|
|
2
2
|
import * as http from 'http';
|
|
3
3
|
import { z } from 'zod';
|
|
4
4
|
|
|
5
|
+
/** A single REST resource item. Field names and value types are user-defined in the YAML file. */
|
|
5
6
|
type Resource = Record<string, unknown>;
|
|
6
|
-
|
|
7
|
+
/**
|
|
8
|
+
* The full in-memory database.
|
|
9
|
+
* Keys are collection names (e.g. `"users"`); values are arrays of {@link Resource} items.
|
|
10
|
+
*/
|
|
11
|
+
type Data = Record<string, Resource[]>;
|
|
12
|
+
/**
|
|
13
|
+
* Relational mappings declared under `_rel` in the YAML file.
|
|
14
|
+
*
|
|
15
|
+
* - Outer key: child collection name.
|
|
16
|
+
* - Inner key: foreign key field on the child.
|
|
17
|
+
* - Inner value: parent collection name.
|
|
18
|
+
*
|
|
19
|
+
* @example
|
|
20
|
+
* // Given: _rel: { posts: { userId: users } }
|
|
21
|
+
* // GET /users/1/posts → returns posts where userId === "1"
|
|
22
|
+
*/
|
|
7
23
|
type Relations = Record<string, Record<string, string>>;
|
|
8
24
|
|
|
25
|
+
/**
|
|
26
|
+
* In-memory store backed by a YAML file.
|
|
27
|
+
*
|
|
28
|
+
* All reads operate on a live in-memory snapshot. Writes must be explicitly
|
|
29
|
+
* flushed to disk by calling {@link persist}. Use {@link reload} to pull in
|
|
30
|
+
* changes made to the file externally (e.g. in watch mode).
|
|
31
|
+
*/
|
|
9
32
|
interface YamlStorage {
|
|
10
|
-
|
|
33
|
+
/** Returns the full in-memory dataset (all collections). */
|
|
34
|
+
getData(): Data;
|
|
35
|
+
/** Returns the relational mappings declared under `_rel`. */
|
|
11
36
|
getRelations(): Relations;
|
|
37
|
+
/**
|
|
38
|
+
* Returns the items in a named collection, or `undefined` if it does not exist.
|
|
39
|
+
*
|
|
40
|
+
* @param name - Collection name as declared in the YAML file (e.g. `"users"`).
|
|
41
|
+
*/
|
|
12
42
|
getCollection(name: string): Resource[] | undefined;
|
|
43
|
+
/**
|
|
44
|
+
* Replaces the items of a named collection in memory.
|
|
45
|
+
* Call {@link persist} afterwards to flush the change to disk.
|
|
46
|
+
*
|
|
47
|
+
* @param name - Collection name.
|
|
48
|
+
* @param items - New array of items to store.
|
|
49
|
+
*/
|
|
13
50
|
setCollection(name: string, items: Resource[]): void;
|
|
51
|
+
/**
|
|
52
|
+
* Atomically writes the current in-memory state to the YAML file.
|
|
53
|
+
*
|
|
54
|
+
* Uses a write-to-temp-then-rename strategy so a crash during the write
|
|
55
|
+
* never leaves the file in a partially written state.
|
|
56
|
+
*
|
|
57
|
+
* @throws {Error} If the filesystem write or rename fails.
|
|
58
|
+
*/
|
|
14
59
|
persist(): void;
|
|
60
|
+
/**
|
|
61
|
+
* Reloads the YAML file from disk and updates the in-memory state in place.
|
|
62
|
+
*
|
|
63
|
+
* Mutates the existing `data` and `relations` objects rather than replacing them,
|
|
64
|
+
* so any code holding a reference to the storage instance sees the updated values
|
|
65
|
+
* without needing to re-fetch.
|
|
66
|
+
*
|
|
67
|
+
* @throws {Error} If the file cannot be read or the YAML is malformed.
|
|
68
|
+
*/
|
|
69
|
+
reload(): void;
|
|
15
70
|
}
|
|
71
|
+
/**
|
|
72
|
+
* Creates a {@link YamlStorage} instance backed by the given YAML file.
|
|
73
|
+
*
|
|
74
|
+
* The file is read and parsed eagerly on construction. The `_rel` key is
|
|
75
|
+
* extracted as relational metadata; all other top-level keys become collections.
|
|
76
|
+
*
|
|
77
|
+
* @param filePath - Relative or absolute path to the YAML database file.
|
|
78
|
+
* @throws {Error} If the file cannot be read or its YAML is invalid.
|
|
79
|
+
*/
|
|
16
80
|
declare function createYamlStorage(filePath: string): YamlStorage;
|
|
17
81
|
|
|
82
|
+
/**
|
|
83
|
+
* Zod schema for all server runtime options.
|
|
84
|
+
*
|
|
85
|
+
* Validates and normalises options from three sources in ascending priority:
|
|
86
|
+
* schema defaults → `yrest.config.yml` → explicit CLI flags.
|
|
87
|
+
*/
|
|
18
88
|
declare const serverOptionsSchema: z.ZodObject<{
|
|
89
|
+
/** Path to the YAML database file. Must be a non-empty string. */
|
|
19
90
|
file: z.ZodString;
|
|
91
|
+
/** TCP port the server listens on. Accepts string input and coerces to number. */
|
|
20
92
|
port: z.ZodDefault<z.ZodNumber>;
|
|
93
|
+
/** Hostname or IP address to bind. */
|
|
21
94
|
host: z.ZodDefault<z.ZodString>;
|
|
95
|
+
/**
|
|
96
|
+
* URL prefix prepended to every route (e.g. `/api`).
|
|
97
|
+
* A leading slash is added automatically if omitted.
|
|
98
|
+
*/
|
|
22
99
|
base: z.ZodEffects<z.ZodDefault<z.ZodString>, string, string | undefined>;
|
|
100
|
+
/** When `true`, the server reloads the YAML file automatically on disk changes. */
|
|
101
|
+
watch: z.ZodDefault<z.ZodBoolean>;
|
|
102
|
+
/** When `true`, all mutating requests (POST, PUT, PATCH, DELETE) are rejected with 405. */
|
|
103
|
+
readonly: z.ZodDefault<z.ZodBoolean>;
|
|
104
|
+
/** Milliseconds to delay every response, simulating network latency. `0` = disabled. */
|
|
105
|
+
delay: z.ZodDefault<z.ZodNumber>;
|
|
106
|
+
/**
|
|
107
|
+
* Wraps GET collection responses in a `{ data, pagination }` envelope.
|
|
108
|
+
* Accepts `true` (default limit 10), `false` (disabled), or a positive integer (custom limit).
|
|
109
|
+
*/
|
|
110
|
+
pageable: z.ZodEffects<z.ZodDefault<z.ZodUnion<[z.ZodBoolean, z.ZodNumber]>>, {
|
|
111
|
+
enabled: boolean;
|
|
112
|
+
limit: number;
|
|
113
|
+
}, number | boolean | undefined>;
|
|
23
114
|
}, "strip", z.ZodTypeAny, {
|
|
24
115
|
file: string;
|
|
25
116
|
port: number;
|
|
26
117
|
host: string;
|
|
27
118
|
base: string;
|
|
119
|
+
watch: boolean;
|
|
120
|
+
readonly: boolean;
|
|
121
|
+
delay: number;
|
|
122
|
+
pageable: {
|
|
123
|
+
enabled: boolean;
|
|
124
|
+
limit: number;
|
|
125
|
+
};
|
|
28
126
|
}, {
|
|
29
127
|
file: string;
|
|
30
128
|
port?: number | undefined;
|
|
31
129
|
host?: string | undefined;
|
|
32
130
|
base?: string | undefined;
|
|
131
|
+
watch?: boolean | undefined;
|
|
132
|
+
readonly?: boolean | undefined;
|
|
133
|
+
delay?: number | undefined;
|
|
134
|
+
pageable?: number | boolean | undefined;
|
|
33
135
|
}>;
|
|
136
|
+
/**
|
|
137
|
+
* Resolved server configuration after Zod validation and transformation.
|
|
138
|
+
* Inferred from {@link serverOptionsSchema}.
|
|
139
|
+
*/
|
|
34
140
|
type ServerOptions = z.infer<typeof serverOptionsSchema>;
|
|
35
141
|
|
|
142
|
+
/**
|
|
143
|
+
* Creates and configures a Fastify instance wired to the given YAML storage.
|
|
144
|
+
*
|
|
145
|
+
* Registers, in order:
|
|
146
|
+
* 1. CORS (all origins, permissive defaults).
|
|
147
|
+
* 2. Readonly guard hook — rejects mutating requests with 405 when enabled.
|
|
148
|
+
* 3. Delay hook — defers `onSend` by N ms when enabled.
|
|
149
|
+
* 4. All resource routes derived from the storage collections.
|
|
150
|
+
*
|
|
151
|
+
* The server is returned before `listen()` is called so tests can inject
|
|
152
|
+
* requests without binding a real port.
|
|
153
|
+
*
|
|
154
|
+
* @param storage - Initialised YAML storage instance.
|
|
155
|
+
* @param options - Validated server options.
|
|
156
|
+
*/
|
|
36
157
|
declare function createServer(storage: YamlStorage, options: ServerOptions): Promise<fastify.FastifyInstance<http.Server<typeof http.IncomingMessage, typeof http.ServerResponse>, http.IncomingMessage, http.ServerResponse<http.IncomingMessage>, fastify.FastifyBaseLogger, fastify.FastifyTypeProviderDefault>>;
|
|
37
158
|
|
|
38
|
-
export { type
|
|
159
|
+
export { type Data, type Relations, type Resource, type ServerOptions, createServer, createYamlStorage, serverOptionsSchema };
|