tina4-nodejs 3.13.62 → 3.13.63

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "tina4-nodejs",
3
- "version": "3.13.62",
3
+ "version": "3.13.63",
4
4
  "type": "module",
5
5
  "description": "Tina4 for Node.js/TypeScript - 54 built-in features, zero dependencies",
6
6
  "keywords": [
@@ -14,28 +14,47 @@ import { validate } from "./validation.js";
14
14
  * PUT /api/{table}/{id} — update record
15
15
  * DELETE /api/{table}/{id} — delete record
16
16
  */
17
+ /**
18
+ * Options accepted by the AutoCrud registration API.
19
+ *
20
+ * `public` is the cross-backend escape hatch (parity with python's `public=True`
21
+ * and php's `bool $public`). Write routes (POST/PUT/DELETE) are secure-by-default
22
+ * — the router gates them unless a def sets `secure: false`. Set `public: true`
23
+ * to open the generated write routes explicitly. Reads (GET) are always public.
24
+ */
25
+ export interface AutoCrudOptions {
26
+ /** When true, the generated write routes (POST/PUT/DELETE) are OPEN (secure:false). Default false → secure. */
27
+ public?: boolean;
28
+ }
29
+
17
30
  export class AutoCrud {
18
31
  private static registered: Map<string, DiscoveredModel> = new Map();
32
+ /** tableName -> public-writes flag (default secure); mirrors php's `$this->public`. */
33
+ private static publicWrites: Map<string, boolean> = new Map();
19
34
 
20
35
  /**
21
36
  * Register a model for auto-CRUD.
37
+ *
38
+ * @param options.public If true, the generated write routes are OPEN (no auth).
39
+ * Default (false) keeps them secure-by-default, matching the framework's write gate.
22
40
  */
23
- static register(model: DiscoveredModel, prefix: string = "/api"): void {
41
+ static register(model: DiscoveredModel, prefix: string = "/api", options: AutoCrudOptions = {}): void {
24
42
  const tableName = model.definition.tableName;
25
43
  if (!tableName) {
26
44
  throw new Error(`AutoCrud: model has no tableName set.`);
27
45
  }
28
46
  AutoCrud.registered.set(tableName, model);
47
+ AutoCrud.publicWrites.set(tableName, options.public === true);
29
48
  }
30
49
 
31
50
  /**
32
51
  * Discover models from the provided array and register them.
33
52
  * (In Node.js, models are discovered by the server and passed in.)
34
53
  */
35
- static discover(discoveredModels: DiscoveredModel[], prefix: string = "/api"): string[] {
54
+ static discover(discoveredModels: DiscoveredModel[], prefix: string = "/api", options: AutoCrudOptions = {}): string[] {
36
55
  const names: string[] = [];
37
56
  for (const model of discoveredModels) {
38
- AutoCrud.register(model, prefix);
57
+ AutoCrud.register(model, prefix, options);
39
58
  names.push(model.definition.tableName);
40
59
  }
41
60
  return names;
@@ -53,14 +72,20 @@ export class AutoCrud {
53
72
  */
54
73
  static clear(): void {
55
74
  AutoCrud.registered.clear();
75
+ AutoCrud.publicWrites.clear();
56
76
  }
57
77
 
58
78
  /**
59
- * Generate route definitions for all registered models.
79
+ * Generate route definitions for all registered models, honouring each
80
+ * model's per-table `public` flag (set at register/discover time).
60
81
  */
61
82
  static generateRoutes(): RouteDefinition[] {
62
- const models = Array.from(AutoCrud.registered.values());
63
- return generateCrudRoutes(models);
83
+ const routes: RouteDefinition[] = [];
84
+ for (const [tableName, model] of AutoCrud.registered) {
85
+ const isPublic = AutoCrud.publicWrites.get(tableName) === true;
86
+ routes.push(...generateCrudRoutes([model], { public: isPublic }));
87
+ }
88
+ return routes;
64
89
  }
65
90
  }
66
91
 
@@ -80,9 +105,18 @@ export function crudEligibleModels(models: DiscoveredModel[]): DiscoveredModel[]
80
105
  /**
81
106
  * Generate CRUD route definitions for the given models.
82
107
  * (Standalone function for backward compatibility.)
108
+ *
109
+ * @param options.public When true, the generated write routes (POST/PUT/DELETE)
110
+ * opt OUT of the router's secure-by-default write gate (`secure: false`) — the
111
+ * cross-backend escape hatch (parity with python `public=True` / php `$public`).
112
+ * Default (false) leaves `secure` unset so the router gates writes (secure:true).
113
+ * GET routes are unaffected (reads are already public).
83
114
  */
84
- export function generateCrudRoutes(models: DiscoveredModel[]): RouteDefinition[] {
115
+ export function generateCrudRoutes(models: DiscoveredModel[], options: AutoCrudOptions = {}): RouteDefinition[] {
85
116
  const routes: RouteDefinition[] = [];
117
+ // Only writes are gated; `public` flips them open. Spread this into POST/PUT/
118
+ // DELETE defs so the default path leaves `secure` unset (router → secure:true).
119
+ const writeSecurity = options.public === true ? { secure: false as const } : {};
86
120
 
87
121
  for (const { definition } of models) {
88
122
  const { tableName, fields, softDelete, tableFilter, fieldMapping } = definition;
@@ -167,10 +201,11 @@ export function generateCrudRoutes(models: DiscoveredModel[]): RouteDefinition[]
167
201
  },
168
202
  });
169
203
 
170
- // POST /api/{table} -- Create
204
+ // POST /api/{table} -- Create (secure-by-default; secure:false only when public)
171
205
  routes.push({
172
206
  method: "POST",
173
207
  pattern: basePath,
208
+ ...writeSecurity,
174
209
  meta: {
175
210
  summary: `Create ${tableName}`,
176
211
  tags: [tableName],
@@ -228,10 +263,11 @@ export function generateCrudRoutes(models: DiscoveredModel[]): RouteDefinition[]
228
263
  },
229
264
  });
230
265
 
231
- // PUT /api/{table}/:id -- Update
266
+ // PUT /api/{table}/:id -- Update (secure-by-default; secure:false only when public)
232
267
  routes.push({
233
268
  method: "PUT",
234
269
  pattern: `${basePath}/{id}`,
270
+ ...writeSecurity,
235
271
  meta: {
236
272
  summary: `Update ${tableName}`,
237
273
  tags: [tableName],
@@ -275,10 +311,11 @@ export function generateCrudRoutes(models: DiscoveredModel[]): RouteDefinition[]
275
311
  },
276
312
  });
277
313
 
278
- // DELETE /api/{table}/:id -- Delete (soft or hard)
314
+ // DELETE /api/{table}/:id -- Delete (secure-by-default; secure:false only when public)
279
315
  routes.push({
280
316
  method: "DELETE",
281
317
  pattern: `${basePath}/{id}`,
318
+ ...writeSecurity,
282
319
  meta: {
283
320
  summary: `Delete ${tableName}`,
284
321
  tags: [tableName],
@@ -47,6 +47,7 @@ export {
47
47
  } from "./migration.js";
48
48
  export type { MigrationResult, MigrationStatus } from "./migration.js";
49
49
  export { AutoCrud, generateCrudRoutes, crudEligibleModels } from "./autoCrud.js";
50
+ export type { AutoCrudOptions } from "./autoCrud.js";
50
51
  export { buildQuery, parseQueryString } from "./query.js";
51
52
  export { validate } from "./validation.js";
52
53
  export type { ValidationError } from "./validation.js";