node-type-registry 0.42.0 → 0.43.1

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.
Files changed (57) hide show
  1. package/authz/authz-app-membership.js +8 -8
  2. package/authz/index.d.ts +2 -2
  3. package/authz/index.js +5 -5
  4. package/blueprint-types.generated.d.ts +99 -10
  5. package/codegen/generate-types.js +56 -2
  6. package/data/check-greater-than.js +6 -6
  7. package/data/check-less-than.js +6 -6
  8. package/data/check-not-equal.js +4 -4
  9. package/data/check-one-of.js +5 -5
  10. package/data/data-jsonb.js +4 -3
  11. package/data/data-status-field.js +4 -3
  12. package/data/data-tags.js +4 -3
  13. package/esm/authz/authz-app-membership.js +8 -8
  14. package/esm/authz/index.d.ts +2 -2
  15. package/esm/authz/index.js +2 -2
  16. package/esm/blueprint-types.generated.d.ts +99 -10
  17. package/esm/codegen/generate-types.js +56 -2
  18. package/esm/data/check-greater-than.js +6 -6
  19. package/esm/data/check-less-than.js +6 -6
  20. package/esm/data/check-not-equal.js +4 -4
  21. package/esm/data/check-one-of.js +5 -5
  22. package/esm/data/data-jsonb.js +4 -3
  23. package/esm/data/data-status-field.js +4 -3
  24. package/esm/data/data-tags.js +4 -3
  25. package/esm/event/referral.js +21 -2
  26. package/esm/event/tracker.js +20 -1
  27. package/esm/index.d.ts +1 -1
  28. package/esm/limit/enforce-aggregate.js +32 -8
  29. package/esm/limit/enforce-counter.js +33 -10
  30. package/esm/limit/enforce-feature.js +26 -8
  31. package/esm/limit/enforce-rate.js +28 -9
  32. package/esm/limit/track-usage.js +28 -9
  33. package/esm/limit/warning-aggregate.js +29 -5
  34. package/esm/limit/warning-counter.js +30 -7
  35. package/esm/limit/warning-rate.js +31 -7
  36. package/esm/module-presets/full.js +1 -1
  37. package/esm/process/chunks.js +1 -1
  38. package/esm/process/file-embedding.js +1 -1
  39. package/esm/types.d.ts +92 -0
  40. package/esm/types.js +1 -0
  41. package/event/referral.js +21 -2
  42. package/event/tracker.js +20 -1
  43. package/index.d.ts +1 -1
  44. package/limit/enforce-aggregate.js +32 -8
  45. package/limit/enforce-counter.js +33 -10
  46. package/limit/enforce-feature.js +26 -8
  47. package/limit/enforce-rate.js +28 -9
  48. package/limit/track-usage.js +28 -9
  49. package/limit/warning-aggregate.js +29 -5
  50. package/limit/warning-counter.js +30 -7
  51. package/limit/warning-rate.js +31 -7
  52. package/module-presets/full.js +1 -1
  53. package/package.json +2 -2
  54. package/process/chunks.js +1 -1
  55. package/process/file-embedding.js +1 -1
  56. package/types.d.ts +92 -0
  57. package/types.js +1 -0
@@ -12,25 +12,25 @@ exports.AuthzAppMembership = {
12
12
  properties: {
13
13
  permission: {
14
14
  type: 'string',
15
- description: 'Single permission name to check (resolved to bitstring mask)',
15
+ description: 'Single permission name to check (resolved to bitstring mask)'
16
16
  },
17
17
  permissions: {
18
18
  type: 'array',
19
19
  items: {
20
- type: 'string',
20
+ type: 'string'
21
21
  },
22
- description: 'Multiple permission names to check (ORed together into mask)',
22
+ description: 'Multiple permission names to check (ORed together into mask)'
23
23
  },
24
24
  is_admin: {
25
25
  type: 'boolean',
26
- description: 'If true, require is_admin flag',
26
+ description: 'If true, require is_admin flag'
27
27
  },
28
28
  is_owner: {
29
29
  type: 'boolean',
30
- description: 'If true, require is_owner flag',
31
- },
30
+ description: 'If true, require is_owner flag'
31
+ }
32
32
  },
33
- required: [],
33
+ required: []
34
34
  },
35
- tags: ['membership', 'authz'],
35
+ tags: ['membership', 'authz']
36
36
  };
package/authz/index.d.ts CHANGED
@@ -2,14 +2,14 @@ export { AuthzAllowAll } from './authz-allow-all';
2
2
  export { AuthzAppMembership } from './authz-app-membership';
3
3
  export { AuthzComposite } from './authz-composite';
4
4
  export { AuthzDenyAll } from './authz-deny-all';
5
- export { AuthzFilePath } from './authz-file-path';
6
5
  export { AuthzDirectOwner } from './authz-direct-owner';
7
6
  export { AuthzDirectOwnerAny } from './authz-direct-owner-any';
8
7
  export { AuthzEntityMembership } from './authz-entity-membership';
8
+ export { AuthzFilePath } from './authz-file-path';
9
9
  export { AuthzMemberList } from './authz-member-list';
10
+ export { AuthzMemberOwner } from './authz-member-owner';
10
11
  export { AuthzNotReadOnly } from './authz-not-read-only';
11
12
  export { AuthzOrgHierarchy } from './authz-org-hierarchy';
12
- export { AuthzMemberOwner } from './authz-member-owner';
13
13
  export { AuthzPeerOwnership } from './authz-peer-ownership';
14
14
  export { AuthzPublishable } from './authz-publishable';
15
15
  export { AuthzRelatedEntityMembership } from './authz-related-entity-membership';
package/authz/index.js CHANGED
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.AuthzTemporal = exports.AuthzRelatedPeerOwnership = exports.AuthzRelatedMemberList = exports.AuthzRelatedEntityMembership = exports.AuthzPublishable = exports.AuthzPeerOwnership = exports.AuthzMemberOwner = exports.AuthzOrgHierarchy = exports.AuthzNotReadOnly = exports.AuthzMemberList = exports.AuthzEntityMembership = exports.AuthzDirectOwnerAny = exports.AuthzDirectOwner = exports.AuthzFilePath = exports.AuthzDenyAll = exports.AuthzComposite = exports.AuthzAppMembership = exports.AuthzAllowAll = void 0;
3
+ exports.AuthzTemporal = exports.AuthzRelatedPeerOwnership = exports.AuthzRelatedMemberList = exports.AuthzRelatedEntityMembership = exports.AuthzPublishable = exports.AuthzPeerOwnership = exports.AuthzOrgHierarchy = exports.AuthzNotReadOnly = exports.AuthzMemberOwner = exports.AuthzMemberList = exports.AuthzFilePath = exports.AuthzEntityMembership = exports.AuthzDirectOwnerAny = exports.AuthzDirectOwner = exports.AuthzDenyAll = exports.AuthzComposite = exports.AuthzAppMembership = exports.AuthzAllowAll = void 0;
4
4
  var authz_allow_all_1 = require("./authz-allow-all");
5
5
  Object.defineProperty(exports, "AuthzAllowAll", { enumerable: true, get: function () { return authz_allow_all_1.AuthzAllowAll; } });
6
6
  var authz_app_membership_1 = require("./authz-app-membership");
@@ -9,22 +9,22 @@ var authz_composite_1 = require("./authz-composite");
9
9
  Object.defineProperty(exports, "AuthzComposite", { enumerable: true, get: function () { return authz_composite_1.AuthzComposite; } });
10
10
  var authz_deny_all_1 = require("./authz-deny-all");
11
11
  Object.defineProperty(exports, "AuthzDenyAll", { enumerable: true, get: function () { return authz_deny_all_1.AuthzDenyAll; } });
12
- var authz_file_path_1 = require("./authz-file-path");
13
- Object.defineProperty(exports, "AuthzFilePath", { enumerable: true, get: function () { return authz_file_path_1.AuthzFilePath; } });
14
12
  var authz_direct_owner_1 = require("./authz-direct-owner");
15
13
  Object.defineProperty(exports, "AuthzDirectOwner", { enumerable: true, get: function () { return authz_direct_owner_1.AuthzDirectOwner; } });
16
14
  var authz_direct_owner_any_1 = require("./authz-direct-owner-any");
17
15
  Object.defineProperty(exports, "AuthzDirectOwnerAny", { enumerable: true, get: function () { return authz_direct_owner_any_1.AuthzDirectOwnerAny; } });
18
16
  var authz_entity_membership_1 = require("./authz-entity-membership");
19
17
  Object.defineProperty(exports, "AuthzEntityMembership", { enumerable: true, get: function () { return authz_entity_membership_1.AuthzEntityMembership; } });
18
+ var authz_file_path_1 = require("./authz-file-path");
19
+ Object.defineProperty(exports, "AuthzFilePath", { enumerable: true, get: function () { return authz_file_path_1.AuthzFilePath; } });
20
20
  var authz_member_list_1 = require("./authz-member-list");
21
21
  Object.defineProperty(exports, "AuthzMemberList", { enumerable: true, get: function () { return authz_member_list_1.AuthzMemberList; } });
22
+ var authz_member_owner_1 = require("./authz-member-owner");
23
+ Object.defineProperty(exports, "AuthzMemberOwner", { enumerable: true, get: function () { return authz_member_owner_1.AuthzMemberOwner; } });
22
24
  var authz_not_read_only_1 = require("./authz-not-read-only");
23
25
  Object.defineProperty(exports, "AuthzNotReadOnly", { enumerable: true, get: function () { return authz_not_read_only_1.AuthzNotReadOnly; } });
24
26
  var authz_org_hierarchy_1 = require("./authz-org-hierarchy");
25
27
  Object.defineProperty(exports, "AuthzOrgHierarchy", { enumerable: true, get: function () { return authz_org_hierarchy_1.AuthzOrgHierarchy; } });
26
- var authz_member_owner_1 = require("./authz-member-owner");
27
- Object.defineProperty(exports, "AuthzMemberOwner", { enumerable: true, get: function () { return authz_member_owner_1.AuthzMemberOwner; } });
28
28
  var authz_peer_ownership_1 = require("./authz-peer-ownership");
29
29
  Object.defineProperty(exports, "AuthzPeerOwnership", { enumerable: true, get: function () { return authz_peer_ownership_1.AuthzPeerOwnership; } });
30
30
  var authz_publishable_1 = require("./authz-publishable");
@@ -20,6 +20,40 @@ export interface TriggerCondition {
20
20
  /** Negated condition. */
21
21
  NOT?: TriggerCondition;
22
22
  }
23
+ /** Structured representation of a PostgreSQL data type. Stored as JSONB in metaschema_public.field.type. */
24
+ export interface FieldType {
25
+ /** Type name. Must be a valid SQL identifier. */
26
+ name: string;
27
+ /** Schema qualifier. */
28
+ schema?: string;
29
+ /** Type arguments (e.g., [10, 2] for numeric(10,2), ["Point", 4326] for geometry). */
30
+ args?: (string | number | boolean)[];
31
+ /** Number of array dimensions. 1 = text[], 2 = text[][]. */
32
+ array_dimensions?: number;
33
+ /** Interval field range. 1-2 elements: ["day"] or ["day", "second"]. */
34
+ range?: string[];
35
+ }
36
+ /** Structured representation of a PostgreSQL default value expression. Stored as JSONB in metaschema_public.field.default_value. */
37
+ export interface FieldDefault {
38
+ /** Literal value (string, number, boolean, null, array, or object). */
39
+ value?: string | number | boolean | null | unknown[] | Record<string, unknown>;
40
+ /** Function name. Must be a valid SQL identifier. */
41
+ function?: string;
42
+ /** Schema qualifier for function. */
43
+ schema?: string;
44
+ /** Function arguments (recursive). */
45
+ args?: (string | number | boolean | null | FieldDefault)[];
46
+ /** Output type cast. */
47
+ cast?: FieldType;
48
+ /** Binary operator (e.g., "+", "-", "||"). */
49
+ operator?: string;
50
+ /** Left operand for operator expression. */
51
+ left?: FieldDefault;
52
+ /** Right operand for operator expression. */
53
+ right?: FieldDefault;
54
+ /** SQL keyword (e.g., "CURRENT_TIMESTAMP", "CURRENT_USER"). */
55
+ sql_keyword?: string;
56
+ }
23
57
  /** Adds a CHECK constraint that validates a column value is greater than a threshold (single-column: column > value) or that one column is greater than another (cross-column: columns[0] > columns[1]). Compiled via AST helpers. */
24
58
  export interface CheckGreaterThanParams {
25
59
  column?: string;
@@ -95,7 +129,7 @@ export interface DataInheritFromParentParams {
95
129
  /** Adds a JSONB column with optional GIN index for containment queries (@>, ?, ?|, ?&). Standard pattern for semi-structured metadata. */
96
130
  export interface DataJsonbParams {
97
131
  field_name?: string;
98
- default_value?: string;
132
+ default_value?: FieldDefault;
99
133
  is_required?: boolean;
100
134
  create_index?: boolean;
101
135
  }
@@ -154,7 +188,7 @@ export interface DataSoftDeleteParams {
154
188
  /** Adds a status column with B-tree index for efficient equality filtering and sorting. Optionally constrains values via CHECK constraint when allowed_values is provided. */
155
189
  export interface DataStatusFieldParams {
156
190
  field_name?: string;
157
- type?: string;
191
+ type?: FieldType;
158
192
  default_value?: string;
159
193
  is_required?: boolean;
160
194
  allowed_values?: string[];
@@ -162,7 +196,7 @@ export interface DataStatusFieldParams {
162
196
  /** Adds a citext[] tags column with GIN index for efficient array containment queries (@>, &&). Standard tagging pattern for categorization and filtering. */
163
197
  export interface DataTagsParams {
164
198
  field_name?: string;
165
- default_value?: string;
199
+ default_value?: FieldDefault;
166
200
  is_required?: boolean;
167
201
  }
168
202
  /** Adds automatic timestamp tracking with created_at and updated_at columns. */
@@ -183,6 +217,11 @@ export interface EventReferralParams {
183
217
  events?: ('INSERT' | 'UPDATE' | 'DELETE')[];
184
218
  actor_field?: string;
185
219
  entity_field?: string;
220
+ entity_lookup?: {
221
+ obj_table: string;
222
+ obj_schema?: string;
223
+ obj_field: string;
224
+ };
186
225
  max_depth?: number;
187
226
  auto_register_type?: boolean;
188
227
  condition_field?: string;
@@ -198,6 +237,11 @@ export interface EventTrackerParams {
198
237
  toggle?: boolean;
199
238
  actor_field?: string;
200
239
  entity_field?: string;
240
+ entity_lookup?: {
241
+ obj_table: string;
242
+ obj_schema?: string;
243
+ obj_field: string;
244
+ };
201
245
  auto_register_type?: boolean;
202
246
  condition_field?: string;
203
247
  condition_value?: string;
@@ -207,26 +251,48 @@ export interface EventTrackerParams {
207
251
  /** Declaratively attaches aggregate limit-tracking triggers to a table. On INSERT the named limit is incremented per entity; on DELETE it is decremented. Uses org_limit_aggregates_inc/dec for per-entity (org-level) aggregate limits rather than per-user limits. Requires a provisioned limits_module for the target database. */
208
252
  export interface LimitEnforceAggregateParams {
209
253
  limit_name: string;
254
+ scope?: string;
210
255
  entity_field?: string;
256
+ entity_lookup?: {
257
+ obj_table: string;
258
+ obj_schema?: string;
259
+ obj_field: string;
260
+ };
211
261
  events?: ('INSERT' | 'DELETE' | 'UPDATE')[];
212
262
  }
213
263
  /** Declaratively attaches limit-tracking triggers to a table. On INSERT the named limit is incremented; on DELETE it is decremented. Requires a provisioned limits_module for the target scope. */
214
264
  export interface LimitEnforceCounterParams {
215
265
  limit_name: string;
216
- scope?: 'app' | 'org';
266
+ scope?: string;
217
267
  actor_field?: string;
268
+ entity_field?: string;
269
+ entity_lookup?: {
270
+ obj_table: string;
271
+ obj_schema?: string;
272
+ obj_field: string;
273
+ };
218
274
  events?: ('INSERT' | 'DELETE' | 'UPDATE')[];
219
275
  }
220
276
  /** Gates a table behind a feature flag backed by the cap tables. Attaches a BEFORE INSERT trigger that checks whether the named feature cap value is > 0. Features are modeled as caps with max=0 (disabled) or max=1 (enabled) in limit_caps / limit_caps_defaults tables. Resolution: COALESCE(per-entity cap, scope default, 0). */
221
277
  export interface LimitEnforceFeatureParams {
222
278
  feature_name: string;
223
- scope?: 'app' | 'org';
279
+ scope?: string;
224
280
  entity_field?: string;
281
+ entity_lookup?: {
282
+ obj_table: string;
283
+ obj_schema?: string;
284
+ obj_field: string;
285
+ };
225
286
  }
226
287
  /** Attaches a BEFORE trigger that calls check_rate_limit() to enforce sliding-window rate limits before allowing mutations. The function checks all three scopes (entity, actor-in-entity, actor) in a single call; which scopes are actually enforced is controlled by what rows exist in rate_window_limits (plan-based config). Requires a provisioned meter_rate_limits_module and billing_module for the target database. */
227
288
  export interface LimitEnforceRateParams {
228
289
  meter_slug: string;
229
290
  entity_field?: string;
291
+ entity_lookup?: {
292
+ obj_table: string;
293
+ obj_schema?: string;
294
+ obj_field: string;
295
+ };
230
296
  actor_field?: string;
231
297
  events?: ('INSERT' | 'UPDATE')[];
232
298
  }
@@ -234,24 +300,47 @@ export interface LimitEnforceRateParams {
234
300
  export interface LimitTrackUsageParams {
235
301
  meter_slug: string;
236
302
  entity_field?: string;
303
+ entity_lookup?: {
304
+ obj_table: string;
305
+ obj_schema?: string;
306
+ obj_field: string;
307
+ };
237
308
  quantity?: number;
238
309
  events?: ('INSERT' | 'DELETE' | 'UPDATE')[];
239
310
  }
240
311
  /** Attaches an AFTER INSERT trigger that checks if the entity's aggregate usage has crossed any warning threshold configured in the limit_warnings table. If a threshold is reached for the first time, enqueues a background job (e.g. email notification). Uses limit_warning_state for one-time dedup per warning/actor/entity triple. Requires a provisioned limits_module with limit_warnings and aggregate limits enabled. */
241
312
  export interface LimitWarningAggregateParams {
242
313
  limit_name: string;
314
+ scope?: string;
243
315
  entity_field?: string;
316
+ entity_lookup?: {
317
+ obj_table: string;
318
+ obj_schema?: string;
319
+ obj_field: string;
320
+ };
244
321
  }
245
322
  /** Attaches an AFTER INSERT trigger that checks if the actor's current usage has crossed any warning threshold configured in the limit_warnings table. If a threshold is reached for the first time, enqueues a background job (e.g. email notification). Uses limit_warning_state for one-time dedup per warning/actor pair. Requires a provisioned limits_module with limit_warnings enabled. */
246
323
  export interface LimitWarningCounterParams {
247
324
  limit_name: string;
248
- scope?: 'app' | 'org';
325
+ scope?: string;
249
326
  actor_field?: string;
327
+ entity_field?: string;
328
+ entity_lookup?: {
329
+ obj_table: string;
330
+ obj_schema?: string;
331
+ obj_field: string;
332
+ };
250
333
  }
251
334
  /** Attaches an AFTER INSERT trigger that checks if the actor's current request count in the active sliding window has crossed any warning threshold configured in the limit_warnings table. If a threshold is reached for the first time, enqueues a background job (e.g. email notification). Uses limit_warning_state for one-time dedup per warning/actor pair. Requires both a limits_module with limit_warnings enabled and a rate_limit_meters_module. */
252
335
  export interface LimitWarningRateParams {
253
336
  meter_slug: string;
337
+ scope?: string;
254
338
  entity_field?: string;
339
+ entity_lookup?: {
340
+ obj_table: string;
341
+ obj_schema?: string;
342
+ obj_field: string;
343
+ };
255
344
  actor_field?: string;
256
345
  }
257
346
  /** Creates a BM25 index on an existing text column using pg_textsearch. Enables statistical relevance ranking with configurable k1 and b parameters. The BM25 index is auto-detected by graphile-search. */
@@ -804,12 +893,12 @@ export interface ViewTableProjectionParams {
804
893
  export interface BlueprintField {
805
894
  /** The column name. */
806
895
  name: string;
807
- /** The PostgreSQL type (e.g., "text", "integer", "boolean", "uuid"). */
808
- type: string;
896
+ /** PostgreSQL type as a FieldType object (e.g., { name: "text" }) or legacy string. */
897
+ type: FieldType | string;
809
898
  /** Whether the column has a NOT NULL constraint. */
810
899
  is_required?: boolean;
811
- /** SQL default value expression (e.g., "true", "now()"). */
812
- default_value?: string;
900
+ /** Default value as a FieldDefault object (e.g., { function: "now" }) or legacy string. */
901
+ default_value?: FieldDefault | string;
813
902
  /** Comment/description for this field. */
814
903
  description?: string;
815
904
  }
@@ -172,6 +172,56 @@ function buildTriggerConditionInterface() {
172
172
  ]), 'Recursive condition type for compound trigger WHEN clauses. Leaf conditions specify {field, op, value?, row?, ref?}. Combinators nest via AND, OR, NOT.');
173
173
  }
174
174
  // ---------------------------------------------------------------------------
175
+ // FieldType — structured PostgreSQL type representation.
176
+ // ---------------------------------------------------------------------------
177
+ function buildFieldTypeInterface() {
178
+ const argType = t.tsUnionType([
179
+ t.tsStringKeyword(),
180
+ t.tsNumberKeyword(),
181
+ t.tsBooleanKeyword()
182
+ ]);
183
+ return addJSDoc(exportInterface('FieldType', [
184
+ addJSDoc(requiredProp('name', t.tsStringKeyword()), 'Type name. Must be a valid SQL identifier.'),
185
+ addJSDoc(optionalProp('schema', t.tsStringKeyword()), 'Schema qualifier.'),
186
+ addJSDoc(optionalProp('args', t.tsArrayType(argType)), 'Type arguments (e.g., [10, 2] for numeric(10,2), ["Point", 4326] for geometry).'),
187
+ addJSDoc(optionalProp('array_dimensions', t.tsNumberKeyword()), 'Number of array dimensions. 1 = text[], 2 = text[][].'),
188
+ addJSDoc(optionalProp('range', t.tsArrayType(t.tsStringKeyword())), 'Interval field range. 1-2 elements: ["day"] or ["day", "second"].')
189
+ ]), 'Structured representation of a PostgreSQL data type. Stored as JSONB in metaschema_public.field.type.');
190
+ }
191
+ // ---------------------------------------------------------------------------
192
+ // FieldDefault — structured PostgreSQL default value expression.
193
+ // ---------------------------------------------------------------------------
194
+ function buildFieldDefaultInterface() {
195
+ const defaultRef = t.tsTypeReference(t.identifier('FieldDefault'));
196
+ const fieldTypeRef = t.tsTypeReference(t.identifier('FieldType'));
197
+ const valueType = t.tsUnionType([
198
+ t.tsStringKeyword(),
199
+ t.tsNumberKeyword(),
200
+ t.tsBooleanKeyword(),
201
+ t.tsNullKeyword(),
202
+ t.tsArrayType(t.tsUnknownKeyword()),
203
+ recordType(t.tsStringKeyword(), t.tsUnknownKeyword())
204
+ ]);
205
+ const argType = t.tsUnionType([
206
+ t.tsStringKeyword(),
207
+ t.tsNumberKeyword(),
208
+ t.tsBooleanKeyword(),
209
+ t.tsNullKeyword(),
210
+ defaultRef
211
+ ]);
212
+ return addJSDoc(exportInterface('FieldDefault', [
213
+ addJSDoc(optionalProp('value', valueType), 'Literal value (string, number, boolean, null, array, or object).'),
214
+ addJSDoc(optionalProp('function', t.tsStringKeyword()), 'Function name. Must be a valid SQL identifier.'),
215
+ addJSDoc(optionalProp('schema', t.tsStringKeyword()), 'Schema qualifier for function.'),
216
+ addJSDoc(optionalProp('args', t.tsArrayType(argType)), 'Function arguments (recursive).'),
217
+ addJSDoc(optionalProp('cast', fieldTypeRef), 'Output type cast.'),
218
+ addJSDoc(optionalProp('operator', t.tsStringKeyword()), 'Binary operator (e.g., "+", "-", "||").'),
219
+ addJSDoc(optionalProp('left', defaultRef), 'Left operand for operator expression.'),
220
+ addJSDoc(optionalProp('right', defaultRef), 'Right operand for operator expression.'),
221
+ addJSDoc(optionalProp('sql_keyword', t.tsStringKeyword()), 'SQL keyword (e.g., "CURRENT_TIMESTAMP", "CURRENT_USER").')
222
+ ]), 'Structured representation of a PostgreSQL default value expression. Stored as JSONB in metaschema_public.field.default_value.');
223
+ }
224
+ // ---------------------------------------------------------------------------
175
225
  // x-codegen-type post-processing — replaces properties that have an
176
226
  // 'x-codegen-type' marker in their JSON Schema with a hand-written TS type
177
227
  // reference. This lets node type definitions delegate complex types
@@ -337,11 +387,13 @@ function buildBlueprintField(meta) {
337
387
  return deriveInterfaceFromTable(table, 'BlueprintField', 'A custom field (column) to add to a blueprint table. Derived from _meta.');
338
388
  }
339
389
  // Static fallback
390
+ const fieldTypeRef = t.tsTypeReference(t.identifier('FieldType'));
391
+ const fieldDefaultRef = t.tsTypeReference(t.identifier('FieldDefault'));
340
392
  return addJSDoc(exportInterface('BlueprintField', [
341
393
  addJSDoc(requiredProp('name', t.tsStringKeyword()), 'The column name.'),
342
- addJSDoc(requiredProp('type', t.tsStringKeyword()), 'The PostgreSQL type (e.g., "text", "integer", "boolean", "uuid").'),
394
+ addJSDoc(requiredProp('type', t.tsUnionType([fieldTypeRef, t.tsStringKeyword()])), 'PostgreSQL type as a FieldType object (e.g., { name: "text" }) or legacy string.'),
343
395
  addJSDoc(optionalProp('is_required', t.tsBooleanKeyword()), 'Whether the column has a NOT NULL constraint.'),
344
- addJSDoc(optionalProp('default_value', t.tsStringKeyword()), 'SQL default value expression (e.g., "true", "now()").'),
396
+ addJSDoc(optionalProp('default_value', t.tsUnionType([fieldDefaultRef, t.tsStringKeyword()])), 'Default value as a FieldDefault object (e.g., { function: "now" }) or legacy string.'),
345
397
  addJSDoc(optionalProp('description', t.tsStringKeyword()), 'Comment/description for this field.')
346
398
  ]), 'A custom field (column) to add to a blueprint table.');
347
399
  }
@@ -763,6 +815,8 @@ function buildProgram(meta) {
763
815
  // -- Shared recursive types (emitted before parameter interfaces) --
764
816
  statements.push(sectionComment('Shared recursive types'));
765
817
  statements.push(buildTriggerConditionInterface());
818
+ statements.push(buildFieldTypeInterface());
819
+ statements.push(buildFieldDefaultInterface());
766
820
  // -- Parameter interfaces grouped by category --
767
821
  const categoryOrder = ['billing', 'check', 'data', 'event', 'limit', 'limit_enforce', 'limit_track', 'limit_warning', 'search', 'job', 'process', 'authz', 'relation', 'view'];
768
822
  for (const cat of categoryOrder) {
@@ -13,21 +13,21 @@ exports.CheckGreaterThan = {
13
13
  column: {
14
14
  type: 'string',
15
15
  format: 'column-ref',
16
- description: 'Single column to compare against value (mutually exclusive with columns)',
16
+ description: 'Single column to compare against value (mutually exclusive with columns)'
17
17
  },
18
18
  value: {
19
19
  type: 'number',
20
20
  description: 'Threshold value for single-column comparison (column > value)',
21
- default: 0,
21
+ default: 0
22
22
  },
23
23
  columns: {
24
24
  type: 'array',
25
25
  items: { type: 'string', format: 'column-ref' },
26
26
  description: 'Two columns for cross-column comparison (columns[0] > columns[1])',
27
27
  minItems: 2,
28
- maxItems: 2,
29
- },
30
- },
28
+ maxItems: 2
29
+ }
30
+ }
31
31
  },
32
- tags: ['check', 'constraint', 'validation', 'comparison'],
32
+ tags: ['check', 'constraint', 'validation', 'comparison']
33
33
  };
@@ -13,20 +13,20 @@ exports.CheckLessThan = {
13
13
  column: {
14
14
  type: 'string',
15
15
  format: 'column-ref',
16
- description: 'Single column to compare against value (mutually exclusive with columns)',
16
+ description: 'Single column to compare against value (mutually exclusive with columns)'
17
17
  },
18
18
  value: {
19
19
  type: 'number',
20
- description: 'Threshold value for single-column comparison (column < value)',
20
+ description: 'Threshold value for single-column comparison (column < value)'
21
21
  },
22
22
  columns: {
23
23
  type: 'array',
24
24
  items: { type: 'string', format: 'column-ref' },
25
25
  description: 'Two columns for cross-column comparison (columns[0] < columns[1])',
26
26
  minItems: 2,
27
- maxItems: 2,
28
- },
29
- },
27
+ maxItems: 2
28
+ }
29
+ }
30
30
  },
31
- tags: ['check', 'constraint', 'validation', 'comparison'],
31
+ tags: ['check', 'constraint', 'validation', 'comparison']
32
32
  };
@@ -15,10 +15,10 @@ exports.CheckNotEqual = {
15
15
  items: { type: 'string', format: 'column-ref' },
16
16
  description: 'Two columns that must not be equal',
17
17
  minItems: 2,
18
- maxItems: 2,
19
- },
18
+ maxItems: 2
19
+ }
20
20
  },
21
- required: ['columns'],
21
+ required: ['columns']
22
22
  },
23
- tags: ['check', 'constraint', 'validation', 'inequality'],
23
+ tags: ['check', 'constraint', 'validation', 'inequality']
24
24
  };
@@ -13,15 +13,15 @@ exports.CheckOneOf = {
13
13
  column: {
14
14
  type: 'string',
15
15
  format: 'column-ref',
16
- description: 'Column to validate against the allowed values',
16
+ description: 'Column to validate against the allowed values'
17
17
  },
18
18
  values: {
19
19
  type: 'array',
20
20
  items: { type: 'string' },
21
- description: 'Array of allowed values for the column',
22
- },
21
+ description: 'Array of allowed values for the column'
22
+ }
23
23
  },
24
- required: ['column', 'values'],
24
+ required: ['column', 'values']
25
25
  },
26
- tags: ['check', 'constraint', 'validation', 'enum'],
26
+ tags: ['check', 'constraint', 'validation', 'enum']
27
27
  };
@@ -17,9 +17,10 @@ exports.DataJsonb = {
17
17
  default: 'metadata'
18
18
  },
19
19
  default_value: {
20
- type: 'string',
21
- description: 'Default value expression',
22
- default: "'{}'::jsonb"
20
+ type: 'object',
21
+ description: 'Default value as a FieldDefault object',
22
+ 'x-codegen-type': 'FieldDefault',
23
+ default: { value: {}, cast: { name: 'jsonb' } }
23
24
  },
24
25
  is_required: {
25
26
  type: 'boolean',
@@ -17,9 +17,10 @@ exports.DataStatusField = {
17
17
  default: 'status'
18
18
  },
19
19
  type: {
20
- type: 'string',
21
- description: 'Column type (text or citext)',
22
- default: 'text'
20
+ type: 'object',
21
+ description: 'Column type as a FieldType object',
22
+ 'x-codegen-type': 'FieldType',
23
+ default: { name: 'text' }
23
24
  },
24
25
  default_value: {
25
26
  type: 'string',
package/data/data-tags.js CHANGED
@@ -17,9 +17,10 @@ exports.DataTags = {
17
17
  default: 'tags'
18
18
  },
19
19
  default_value: {
20
- type: 'string',
21
- description: 'Default value expression for the tags column',
22
- default: 'ARRAY[]::citext[]'
20
+ type: 'object',
21
+ description: 'Default value as a FieldDefault object',
22
+ 'x-codegen-type': 'FieldDefault',
23
+ default: { value: [], cast: { name: 'citext', array_dimensions: 1 } }
23
24
  },
24
25
  is_required: {
25
26
  type: 'boolean',
@@ -9,25 +9,25 @@ export const AuthzAppMembership = {
9
9
  properties: {
10
10
  permission: {
11
11
  type: 'string',
12
- description: 'Single permission name to check (resolved to bitstring mask)',
12
+ description: 'Single permission name to check (resolved to bitstring mask)'
13
13
  },
14
14
  permissions: {
15
15
  type: 'array',
16
16
  items: {
17
- type: 'string',
17
+ type: 'string'
18
18
  },
19
- description: 'Multiple permission names to check (ORed together into mask)',
19
+ description: 'Multiple permission names to check (ORed together into mask)'
20
20
  },
21
21
  is_admin: {
22
22
  type: 'boolean',
23
- description: 'If true, require is_admin flag',
23
+ description: 'If true, require is_admin flag'
24
24
  },
25
25
  is_owner: {
26
26
  type: 'boolean',
27
- description: 'If true, require is_owner flag',
28
- },
27
+ description: 'If true, require is_owner flag'
28
+ }
29
29
  },
30
- required: [],
30
+ required: []
31
31
  },
32
- tags: ['membership', 'authz'],
32
+ tags: ['membership', 'authz']
33
33
  };
@@ -2,14 +2,14 @@ export { AuthzAllowAll } from './authz-allow-all';
2
2
  export { AuthzAppMembership } from './authz-app-membership';
3
3
  export { AuthzComposite } from './authz-composite';
4
4
  export { AuthzDenyAll } from './authz-deny-all';
5
- export { AuthzFilePath } from './authz-file-path';
6
5
  export { AuthzDirectOwner } from './authz-direct-owner';
7
6
  export { AuthzDirectOwnerAny } from './authz-direct-owner-any';
8
7
  export { AuthzEntityMembership } from './authz-entity-membership';
8
+ export { AuthzFilePath } from './authz-file-path';
9
9
  export { AuthzMemberList } from './authz-member-list';
10
+ export { AuthzMemberOwner } from './authz-member-owner';
10
11
  export { AuthzNotReadOnly } from './authz-not-read-only';
11
12
  export { AuthzOrgHierarchy } from './authz-org-hierarchy';
12
- export { AuthzMemberOwner } from './authz-member-owner';
13
13
  export { AuthzPeerOwnership } from './authz-peer-ownership';
14
14
  export { AuthzPublishable } from './authz-publishable';
15
15
  export { AuthzRelatedEntityMembership } from './authz-related-entity-membership';
@@ -2,14 +2,14 @@ export { AuthzAllowAll } from './authz-allow-all';
2
2
  export { AuthzAppMembership } from './authz-app-membership';
3
3
  export { AuthzComposite } from './authz-composite';
4
4
  export { AuthzDenyAll } from './authz-deny-all';
5
- export { AuthzFilePath } from './authz-file-path';
6
5
  export { AuthzDirectOwner } from './authz-direct-owner';
7
6
  export { AuthzDirectOwnerAny } from './authz-direct-owner-any';
8
7
  export { AuthzEntityMembership } from './authz-entity-membership';
8
+ export { AuthzFilePath } from './authz-file-path';
9
9
  export { AuthzMemberList } from './authz-member-list';
10
+ export { AuthzMemberOwner } from './authz-member-owner';
10
11
  export { AuthzNotReadOnly } from './authz-not-read-only';
11
12
  export { AuthzOrgHierarchy } from './authz-org-hierarchy';
12
- export { AuthzMemberOwner } from './authz-member-owner';
13
13
  export { AuthzPeerOwnership } from './authz-peer-ownership';
14
14
  export { AuthzPublishable } from './authz-publishable';
15
15
  export { AuthzRelatedEntityMembership } from './authz-related-entity-membership';