node-type-registry 0.21.0 → 0.23.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.
Files changed (47) hide show
  1. package/authz/authz-app-membership.d.ts +2 -0
  2. package/authz/{authz-membership-check.js → authz-app-membership.js} +17 -23
  3. package/authz/index.d.ts +1 -1
  4. package/authz/index.js +3 -3
  5. package/blueprint-types.generated.d.ts +339 -270
  6. package/blueprint-types.generated.js +6 -0
  7. package/codegen/generate-types.js +105 -4
  8. package/data/data-feature-flag.d.ts +2 -0
  9. package/data/data-feature-flag.js +33 -0
  10. package/data/data-image-embedding.d.ts +2 -0
  11. package/data/data-image-embedding.js +80 -0
  12. package/data/data-job-trigger.js +38 -1
  13. package/data/data-limit-counter.d.ts +2 -0
  14. package/data/data-limit-counter.js +42 -0
  15. package/data/data-ownership-in-entity.js +12 -0
  16. package/data/data-peoplestamps.js +12 -0
  17. package/data/data-publishable.js +12 -0
  18. package/data/data-soft-delete.js +12 -0
  19. package/data/data-timestamps.js +12 -0
  20. package/data/index.d.ts +3 -0
  21. package/data/index.js +7 -1
  22. package/esm/authz/authz-app-membership.d.ts +2 -0
  23. package/esm/authz/{authz-membership-check.js → authz-app-membership.js} +16 -22
  24. package/esm/authz/index.d.ts +1 -1
  25. package/esm/authz/index.js +1 -1
  26. package/esm/blueprint-types.generated.d.ts +339 -270
  27. package/esm/blueprint-types.generated.js +6 -0
  28. package/esm/codegen/generate-types.js +105 -4
  29. package/esm/data/data-feature-flag.d.ts +2 -0
  30. package/esm/data/data-feature-flag.js +30 -0
  31. package/esm/data/data-image-embedding.d.ts +2 -0
  32. package/esm/data/data-image-embedding.js +77 -0
  33. package/esm/data/data-job-trigger.js +38 -1
  34. package/esm/data/data-limit-counter.d.ts +2 -0
  35. package/esm/data/data-limit-counter.js +39 -0
  36. package/esm/data/data-ownership-in-entity.js +12 -0
  37. package/esm/data/data-peoplestamps.js +12 -0
  38. package/esm/data/data-publishable.js +12 -0
  39. package/esm/data/data-soft-delete.js +12 -0
  40. package/esm/data/data-timestamps.js +12 -0
  41. package/esm/data/index.d.ts +3 -0
  42. package/esm/data/index.js +3 -0
  43. package/esm/view/view-aggregated.js +1 -0
  44. package/package.json +2 -2
  45. package/view/view-aggregated.js +1 -0
  46. package/authz/authz-membership-check.d.ts +0 -2
  47. package/esm/authz/authz-membership-check.d.ts +0 -2
@@ -6,6 +6,12 @@
6
6
  //
7
7
  // These types match the JSONB shape expected by construct_blueprint().
8
8
  // All field names are snake_case to match the SQL convention.
9
+ /**
10
+ * ===========================================================================
11
+ * Shared recursive types
12
+ * ===========================================================================
13
+ */
14
+ ;
9
15
  /**
10
16
  * ===========================================================================
11
17
  * Data node type parameters
@@ -76,6 +76,15 @@ function partialOf(inner) {
76
76
  // ---------------------------------------------------------------------------
77
77
  function ensureArrayItems(schema) {
78
78
  const out = { ...schema };
79
+ // Strip $defs — they exist for JSON Schema validators but schema-typescript
80
+ // doesn't understand them and the TS types are emitted separately.
81
+ delete out.$defs;
82
+ // Properties with x-codegen-type get their TS type replaced post-generation,
83
+ // so collapse them to a simple {type:'object'} to avoid confusing
84
+ // schema-typescript with $ref or oneOf it can't resolve.
85
+ if (out['x-codegen-type']) {
86
+ return { type: 'object', description: out.description, 'x-codegen-type': out['x-codegen-type'] };
87
+ }
79
88
  // Ensure arrays have an items spec (schema-typescript throws without one)
80
89
  if (out.type === 'array' && !out.items) {
81
90
  out.items = { type: 'string' };
@@ -101,6 +110,93 @@ function ensureArrayItems(schema) {
101
110
  return out;
102
111
  }
103
112
  // ---------------------------------------------------------------------------
113
+ // TriggerCondition — recursive type for compound WHEN clause conditions.
114
+ // Hand-written because JSON Schema / schema-typescript cannot express
115
+ // self-referencing types.
116
+ // ---------------------------------------------------------------------------
117
+ function buildTriggerConditionInterface() {
118
+ const opType = t.tsUnionType(['=', '!=', '>', '<', '>=', '<=', 'LIKE', 'NOT LIKE', 'IS NULL', 'IS NOT NULL', 'IS DISTINCT FROM']
119
+ .map((op) => t.tsLiteralType(t.stringLiteral(op))));
120
+ const rowType = t.tsUnionType([
121
+ t.tsLiteralType(t.stringLiteral('NEW')),
122
+ t.tsLiteralType(t.stringLiteral('OLD'))
123
+ ]);
124
+ const condRef = t.tsTypeReference(t.identifier('TriggerCondition'));
125
+ return addJSDoc(exportInterface('TriggerCondition', [
126
+ addJSDoc(optionalProp('field', t.tsStringKeyword()), 'Column name (validated against the table).'),
127
+ addJSDoc(optionalProp('op', opType), 'Comparison operator.'),
128
+ addJSDoc(optionalProp('value', t.tsAnyKeyword()), 'Comparison value. Type is resolved from the column definition.'),
129
+ addJSDoc(optionalProp('row', rowType), 'Row reference (default: NEW).'),
130
+ addJSDoc(optionalProp('ref', t.tsTypeLiteral([
131
+ optionalProp('field', t.tsStringKeyword()),
132
+ optionalProp('row', rowType)
133
+ ])), 'Column reference for field-to-field comparison (alternative to value).'),
134
+ addJSDoc(optionalProp('AND', t.tsArrayType(condRef)), 'Array of conditions combined with AND.'),
135
+ addJSDoc(optionalProp('OR', t.tsArrayType(condRef)), 'Array of conditions combined with OR.'),
136
+ addJSDoc(optionalProp('NOT', condRef), 'Negated condition.')
137
+ ]), 'Recursive condition type for compound trigger WHEN clauses. Leaf conditions specify {field, op, value?, row?, ref?}. Combinators nest via AND, OR, NOT.');
138
+ }
139
+ // ---------------------------------------------------------------------------
140
+ // x-codegen-type post-processing — replaces properties that have an
141
+ // 'x-codegen-type' marker in their JSON Schema with a hand-written TS type
142
+ // reference. This lets node type definitions delegate complex types
143
+ // (like recursive TriggerCondition) to the codegen instead of trying to
144
+ // express them in JSON Schema.
145
+ // ---------------------------------------------------------------------------
146
+ function applyCodegenTypeOverrides(statements, nodeTypes) {
147
+ // Build a map of typeName -> { propName -> typeString }
148
+ const overrides = new Map();
149
+ for (const nt of nodeTypes) {
150
+ const props = nt.parameter_schema?.properties;
151
+ if (!props)
152
+ continue;
153
+ for (const [propName, propSchema] of Object.entries(props)) {
154
+ const schema = propSchema;
155
+ if (schema['x-codegen-type']) {
156
+ const typeName = `${nt.name}Params`;
157
+ if (!overrides.has(typeName))
158
+ overrides.set(typeName, new Map());
159
+ overrides.get(typeName).set(propName, schema['x-codegen-type']);
160
+ }
161
+ }
162
+ }
163
+ if (overrides.size === 0)
164
+ return;
165
+ for (const stmt of statements) {
166
+ const decl = stmt.declaration;
167
+ if (!t.isTSInterfaceDeclaration(decl))
168
+ continue;
169
+ const ifaceName = decl.id.name;
170
+ const propOverrides = overrides.get(ifaceName);
171
+ if (!propOverrides)
172
+ continue;
173
+ for (const member of decl.body.body) {
174
+ if (!t.isTSPropertySignature(member))
175
+ continue;
176
+ const key = t.isIdentifier(member.key)
177
+ ? member.key.name
178
+ : t.isStringLiteral(member.key)
179
+ ? member.key.value
180
+ : null;
181
+ if (!key || !propOverrides.has(key))
182
+ continue;
183
+ const typeStr = propOverrides.get(key);
184
+ // Parse "TypeA | TypeB[]" into a TS union of type references
185
+ const parts = typeStr.split('|').map((s) => s.trim());
186
+ const tsTypes = parts.map((part) => {
187
+ const isArray = part.endsWith('[]');
188
+ const name = isArray ? part.slice(0, -2) : part;
189
+ const ref = t.tsTypeReference(t.identifier(name));
190
+ return isArray ? t.tsArrayType(ref) : ref;
191
+ });
192
+ const annotation = tsTypes.length === 1
193
+ ? tsTypes[0]
194
+ : t.tsUnionType(tsTypes);
195
+ member.typeAnnotation = t.tsTypeAnnotation(annotation);
196
+ }
197
+ }
198
+ }
199
+ // ---------------------------------------------------------------------------
104
200
  // Generate per-node-type parameter interfaces via schema-typescript
105
201
  // ---------------------------------------------------------------------------
106
202
  function generateParamsInterfaces(nodeTypes) {
@@ -127,6 +223,9 @@ function generateParamsInterfaces(nodeTypes) {
127
223
  results.push(addJSDoc(exportInterface(typeName, []), nt.description));
128
224
  }
129
225
  }
226
+ // Apply x-codegen-type overrides to replace schema-generated types with
227
+ // hand-written recursive types (e.g. TriggerCondition)
228
+ applyCodegenTypeOverrides(results, nodeTypes);
130
229
  return results;
131
230
  }
132
231
  // ---------------------------------------------------------------------------
@@ -388,9 +487,8 @@ function buildBlueprintStorageConfig() {
388
487
  addJSDoc(optionalProp('allowed_origins', t.tsArrayType(t.tsStringKeyword())), 'CORS allowed origins for the storage module.'),
389
488
  addJSDoc(optionalProp('provisions', t.tsTypeLiteral([
390
489
  optionalProp('files', t.tsTypeReference(t.identifier('BlueprintEntityTableProvision'))),
391
- optionalProp('buckets', t.tsTypeReference(t.identifier('BlueprintEntityTableProvision'))),
392
- optionalProp('upload_requests', t.tsTypeReference(t.identifier('BlueprintEntityTableProvision')))
393
- ])), 'Per-table overrides for storage tables. Each key targets a specific storage table (files, buckets, upload_requests) and uses the same shape as table_provision: { nodes, fields, grants, use_rls, policies }. Fanned out to secure_table_provision targeting the corresponding table. When a key includes policies[], those REPLACE the default storage policies for that table; tables without a key still get defaults.')
490
+ optionalProp('buckets', t.tsTypeReference(t.identifier('BlueprintEntityTableProvision')))
491
+ ])), 'Per-table overrides for storage tables. Each key targets a specific storage table (files, buckets) and uses the same shape as table_provision: { nodes, fields, grants, use_rls, policies }. Fanned out to secure_table_provision targeting the corresponding table. When a key includes policies[], those REPLACE the default storage policies for that table; tables without a key still get defaults.')
394
492
  ]), 'Storage configuration for an entity type. Seeds initial buckets, overrides module-level settings (expiry times, file size limits, CORS), and provides per-table provisioning overrides via provisions.');
395
493
  }
396
494
  function buildBlueprintEntityTableProvision() {
@@ -416,7 +514,7 @@ function buildBlueprintEntityType() {
416
514
  addJSDoc(optionalProp('has_limits', t.tsBooleanKeyword()), 'Whether to provision a limits module for this entity type. Defaults to false.'),
417
515
  addJSDoc(optionalProp('has_profiles', t.tsBooleanKeyword()), 'Whether to provision a profiles module for this entity type. Defaults to false.'),
418
516
  addJSDoc(optionalProp('has_levels', t.tsBooleanKeyword()), 'Whether to provision a levels module for this entity type. Defaults to false.'),
419
- addJSDoc(optionalProp('has_storage', t.tsBooleanKeyword()), 'Whether to provision a storage module (buckets, files, upload_requests tables) for this entity type. Defaults to false.'),
517
+ addJSDoc(optionalProp('has_storage', t.tsBooleanKeyword()), 'Whether to provision a storage module (buckets, files tables) for this entity type. Defaults to false.'),
420
518
  addJSDoc(optionalProp('has_invites', t.tsBooleanKeyword()), 'Whether to provision entity-scoped invite tables ({prefix}_invites, {prefix}_claimed_invites) and a submit_{prefix}_invite_code() function. Defaults to false.'),
421
519
  addJSDoc(optionalProp('skip_entity_policies', t.tsBooleanKeyword()), 'Escape hatch: when true AND table_provision is NULL, zero policies are provisioned on the entity table. Defaults to false.'),
422
520
  addJSDoc(optionalProp('table_provision', t.tsTypeReference(t.identifier('BlueprintEntityTableProvision'))), 'Override for the entity table. Shape mirrors BlueprintTable / secure_table_provision vocabulary. When supplied, its policies[] replaces the five default entity-table policies; is_visible becomes a no-op. When NULL (default), the five default policies are applied (gated by is_visible).'),
@@ -479,6 +577,9 @@ function buildProgram(meta) {
479
577
  const dataNodes = allNodeTypes.filter((nt) => nt.category !== 'relation' && nt.category !== 'view');
480
578
  const relationNodes = allNodeTypes.filter((nt) => nt.category === 'relation');
481
579
  const authzNodes = allNodeTypes.filter((nt) => nt.category === 'authz');
580
+ // -- Shared recursive types (emitted before parameter interfaces) --
581
+ statements.push(sectionComment('Shared recursive types'));
582
+ statements.push(buildTriggerConditionInterface());
482
583
  // -- Parameter interfaces grouped by category --
483
584
  const categoryOrder = ['data', 'search', 'authz', 'relation', 'view'];
484
585
  for (const cat of categoryOrder) {
@@ -0,0 +1,2 @@
1
+ import type { NodeTypeDefinition } from '../types';
2
+ export declare const DataFeatureFlag: NodeTypeDefinition;
@@ -0,0 +1,30 @@
1
+ export const DataFeatureFlag = {
2
+ name: 'DataFeatureFlag',
3
+ slug: 'data_feature_flag',
4
+ category: 'data',
5
+ display_name: 'Feature Flag',
6
+ description: '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).',
7
+ parameter_schema: {
8
+ type: 'object',
9
+ properties: {
10
+ feature_name: {
11
+ type: 'string',
12
+ description: 'Cap name representing this feature (must match a limit_caps_defaults entry with max=0 or max=1)',
13
+ },
14
+ scope: {
15
+ type: 'string',
16
+ enum: ['app', 'org'],
17
+ description: 'Feature scope: "app" (membership_type=1, app-level caps) or "org" (membership_type=2, per-entity caps)',
18
+ default: 'app',
19
+ },
20
+ entity_field: {
21
+ type: 'string',
22
+ format: 'column-ref',
23
+ description: 'Column on the target table that holds the entity id for per-entity cap lookups (only used for org scope)',
24
+ default: 'entity_id',
25
+ },
26
+ },
27
+ required: ['feature_name'],
28
+ },
29
+ tags: ['limits', 'triggers', 'feature-flags', 'billing', 'caps'],
30
+ };
@@ -0,0 +1,2 @@
1
+ import type { NodeTypeDefinition } from '../types';
2
+ export declare const DataImageEmbedding: NodeTypeDefinition;
@@ -0,0 +1,77 @@
1
+ export const DataImageEmbedding = {
2
+ name: 'DataImageEmbedding',
3
+ slug: 'data_image_embedding',
4
+ category: 'data',
5
+ display_name: 'Image Embedding',
6
+ description: 'Composition wrapper that creates a vector embedding field with HNSW/IVFFlat index (via SearchVector) and a job trigger with compound conditions (via DataJobTrigger) that fires on INSERT for image files matching mime_type patterns. Designed for storage file tables.',
7
+ parameter_schema: {
8
+ type: 'object',
9
+ properties: {
10
+ field_name: {
11
+ type: 'string',
12
+ format: 'column-ref',
13
+ description: 'Name of the vector embedding column',
14
+ default: 'embedding'
15
+ },
16
+ dimensions: {
17
+ type: 'integer',
18
+ description: 'Vector dimensions',
19
+ default: 512
20
+ },
21
+ index_method: {
22
+ type: 'string',
23
+ enum: [
24
+ 'hnsw',
25
+ 'ivfflat'
26
+ ],
27
+ description: 'Index type for similarity search',
28
+ default: 'hnsw'
29
+ },
30
+ metric: {
31
+ type: 'string',
32
+ enum: [
33
+ 'cosine',
34
+ 'l2',
35
+ 'ip'
36
+ ],
37
+ description: 'Distance metric',
38
+ default: 'cosine'
39
+ },
40
+ task_identifier: {
41
+ type: 'string',
42
+ description: 'Job task identifier for the embedding worker',
43
+ default: 'process_image_embedding'
44
+ },
45
+ mime_patterns: {
46
+ type: 'array',
47
+ items: {
48
+ type: 'string'
49
+ },
50
+ description: 'MIME type LIKE patterns to match (e.g., image/%, video/%). Multiple patterns are OR\'d together.',
51
+ default: ['image/%']
52
+ },
53
+ payload_custom: {
54
+ type: 'object',
55
+ additionalProperties: {
56
+ type: 'string',
57
+ format: 'column-ref'
58
+ },
59
+ description: 'Custom payload key-to-column mapping for the job trigger',
60
+ default: {
61
+ file_id: 'id',
62
+ key: 'key',
63
+ mime_type: 'mime_type',
64
+ bucket_id: 'bucket_id'
65
+ }
66
+ }
67
+ }
68
+ },
69
+ tags: [
70
+ 'embedding',
71
+ 'image',
72
+ 'vector',
73
+ 'ai',
74
+ 'composition',
75
+ 'jobs'
76
+ ]
77
+ };
@@ -1,3 +1,28 @@
1
+ const triggerConditionSchema = {
2
+ type: 'object',
3
+ description: 'A leaf condition ({field, op, value?, row?, ref?}) or a combinator ({AND, OR, NOT}).',
4
+ properties: {
5
+ field: { type: 'string', format: 'column-ref', description: 'Column name (validated against the table).' },
6
+ op: {
7
+ type: 'string',
8
+ enum: ['=', '!=', '>', '<', '>=', '<=', 'LIKE', 'NOT LIKE', 'IS NULL', 'IS NOT NULL', 'IS DISTINCT FROM'],
9
+ description: 'Comparison operator.'
10
+ },
11
+ value: { description: 'Comparison value. Type is resolved from the column definition. Omit for IS NULL, IS NOT NULL, IS DISTINCT FROM.' },
12
+ row: { type: 'string', enum: ['NEW', 'OLD'], default: 'NEW', description: 'Row reference (default: NEW).' },
13
+ ref: {
14
+ type: 'object',
15
+ description: 'Column reference for field-to-field comparison (alternative to value).',
16
+ properties: {
17
+ field: { type: 'string', format: 'column-ref' },
18
+ row: { type: 'string', enum: ['NEW', 'OLD'], default: 'NEW' }
19
+ }
20
+ },
21
+ AND: { type: 'array', description: 'Array of conditions combined with AND.', items: { $ref: '#/$defs/triggerCondition' } },
22
+ OR: { type: 'array', description: 'Array of conditions combined with OR.', items: { $ref: '#/$defs/triggerCondition' } },
23
+ NOT: { $ref: '#/$defs/triggerCondition', description: 'Negated condition.' }
24
+ }
25
+ };
1
26
  export const DataJobTrigger = {
2
27
  name: 'DataJobTrigger',
3
28
  slug: 'data_job_trigger',
@@ -6,6 +31,9 @@ export const DataJobTrigger = {
6
31
  description: 'Dynamically creates PostgreSQL triggers that enqueue jobs via app_jobs.add_job() when table rows are inserted, updated, or deleted. Supports configurable payload strategies (full row, row ID, selected fields, or custom mapping), conditional firing via WHEN clauses, watched field changes, and extended job options (queue, priority, delay, max attempts).',
7
32
  parameter_schema: {
8
33
  type: 'object',
34
+ $defs: {
35
+ triggerCondition: triggerConditionSchema
36
+ },
9
37
  properties: {
10
38
  task_identifier: {
11
39
  type: 'string',
@@ -33,7 +61,8 @@ export const DataJobTrigger = {
33
61
  payload_custom: {
34
62
  type: 'object',
35
63
  additionalProperties: {
36
- type: 'string'
64
+ type: 'string',
65
+ format: 'column-ref'
37
66
  },
38
67
  description: 'Key-to-column mapping for custom payload (e.g., {"invoice_id": "id", "total": "amount"})'
39
68
  },
@@ -72,6 +101,14 @@ export const DataJobTrigger = {
72
101
  type: 'string',
73
102
  description: 'Value to compare against condition_field in WHEN clause'
74
103
  },
104
+ conditions: {
105
+ description: 'Compound conditions for the trigger WHEN clause. Accepts a single leaf condition, an array of conditions (implicitly AND), or a nested combinator tree ({AND: [...], OR: [...], NOT: {...}}). Each leaf is {field, op, value?, row?, ref?}. Column types are resolved automatically from the table schema. Cannot be combined with condition_field or watch_fields.',
106
+ 'x-codegen-type': 'TriggerCondition | TriggerCondition[]',
107
+ oneOf: [
108
+ { $ref: '#/$defs/triggerCondition' },
109
+ { type: 'array', items: { $ref: '#/$defs/triggerCondition' } }
110
+ ]
111
+ },
75
112
  watch_fields: {
76
113
  type: 'array',
77
114
  items: {
@@ -0,0 +1,2 @@
1
+ import type { NodeTypeDefinition } from '../types';
2
+ export declare const DataLimitCounter: NodeTypeDefinition;
@@ -0,0 +1,39 @@
1
+ export const DataLimitCounter = {
2
+ name: 'DataLimitCounter',
3
+ slug: 'data_limit_counter',
4
+ category: 'data',
5
+ display_name: 'Limit Counter',
6
+ description: '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.',
7
+ parameter_schema: {
8
+ type: 'object',
9
+ properties: {
10
+ limit_name: {
11
+ type: 'string',
12
+ description: 'Name of the limit to track (must match a default_limits entry, e.g. "projects", "members")',
13
+ },
14
+ scope: {
15
+ type: 'string',
16
+ enum: ['app', 'org'],
17
+ description: 'Limit scope: "app" (membership_type=1, user-level) or "org" (membership_type=2, entity-level)',
18
+ default: 'app',
19
+ },
20
+ actor_field: {
21
+ type: 'string',
22
+ format: 'column-ref',
23
+ description: 'Column on the target table that holds the actor or entity id used for limit lookup',
24
+ default: 'owner_id',
25
+ },
26
+ events: {
27
+ type: 'array',
28
+ items: {
29
+ type: 'string',
30
+ enum: ['INSERT', 'DELETE', 'UPDATE'],
31
+ },
32
+ description: 'Which DML events to attach triggers for',
33
+ default: ['INSERT', 'DELETE'],
34
+ },
35
+ },
36
+ required: ['limit_name'],
37
+ },
38
+ tags: ['limits', 'triggers', 'billing'],
39
+ };
@@ -7,6 +7,18 @@ export const DataOwnershipInEntity = {
7
7
  parameter_schema: {
8
8
  type: 'object',
9
9
  properties: {
10
+ owner_field_name: {
11
+ type: 'string',
12
+ format: 'column-ref',
13
+ description: 'Column name for the owner reference',
14
+ default: 'owner_id'
15
+ },
16
+ entity_field_name: {
17
+ type: 'string',
18
+ format: 'column-ref',
19
+ description: 'Column name for the entity reference',
20
+ default: 'entity_id'
21
+ },
10
22
  include_id: {
11
23
  type: 'boolean',
12
24
  description: 'If true, also adds a UUID primary key column with auto-generation',
@@ -7,6 +7,18 @@ export const DataPeoplestamps = {
7
7
  parameter_schema: {
8
8
  type: 'object',
9
9
  properties: {
10
+ created_by_field: {
11
+ type: 'string',
12
+ format: 'column-ref',
13
+ description: 'Column name for the creating user reference',
14
+ default: 'created_by'
15
+ },
16
+ updated_by_field: {
17
+ type: 'string',
18
+ format: 'column-ref',
19
+ description: 'Column name for the last-updating user reference',
20
+ default: 'updated_by'
21
+ },
10
22
  include_id: {
11
23
  type: 'boolean',
12
24
  description: 'If true, also adds a UUID primary key column with auto-generation',
@@ -7,6 +7,18 @@ export const DataPublishable = {
7
7
  parameter_schema: {
8
8
  type: 'object',
9
9
  properties: {
10
+ is_published_field: {
11
+ type: 'string',
12
+ format: 'column-ref',
13
+ description: 'Column name for the published boolean flag',
14
+ default: 'is_published'
15
+ },
16
+ published_at_field: {
17
+ type: 'string',
18
+ format: 'column-ref',
19
+ description: 'Column name for the publish timestamp',
20
+ default: 'published_at'
21
+ },
10
22
  include_id: {
11
23
  type: 'boolean',
12
24
  description: 'If true, also adds a UUID primary key column with auto-generation',
@@ -7,6 +7,18 @@ export const DataSoftDelete = {
7
7
  parameter_schema: {
8
8
  type: 'object',
9
9
  properties: {
10
+ deleted_at_field: {
11
+ type: 'string',
12
+ format: 'column-ref',
13
+ description: 'Column name for the soft-delete timestamp',
14
+ default: 'deleted_at'
15
+ },
16
+ is_deleted_field: {
17
+ type: 'string',
18
+ format: 'column-ref',
19
+ description: 'Column name for the soft-delete boolean flag',
20
+ default: 'is_deleted'
21
+ },
10
22
  include_id: {
11
23
  type: 'boolean',
12
24
  description: 'If true, also adds a UUID primary key column with auto-generation',
@@ -7,6 +7,18 @@ export const DataTimestamps = {
7
7
  parameter_schema: {
8
8
  type: 'object',
9
9
  properties: {
10
+ created_at_field: {
11
+ type: 'string',
12
+ format: 'column-ref',
13
+ description: 'Column name for the creation timestamp',
14
+ default: 'created_at'
15
+ },
16
+ updated_at_field: {
17
+ type: 'string',
18
+ format: 'column-ref',
19
+ description: 'Column name for the last-updated timestamp',
20
+ default: 'updated_at'
21
+ },
10
22
  include_id: {
11
23
  type: 'boolean',
12
24
  description: 'If true, also adds a UUID primary key column with auto-generation',
@@ -1,12 +1,15 @@
1
1
  export { DataCompositeField } from './data-composite-field';
2
2
  export { DataDirectOwner } from './data-direct-owner';
3
3
  export { DataEntityMembership } from './data-entity-membership';
4
+ export { DataFeatureFlag } from './data-feature-flag';
4
5
  export { DataForceCurrentUser } from './data-force-current-user';
5
6
  export { DataId } from './data-id';
7
+ export { DataImageEmbedding } from './data-image-embedding';
6
8
  export { DataImmutableFields } from './data-immutable-fields';
7
9
  export { DataInflection } from './data-inflection';
8
10
  export { DataInheritFromParent } from './data-inherit-from-parent';
9
11
  export { DataJobTrigger } from './data-job-trigger';
12
+ export { DataLimitCounter } from './data-limit-counter';
10
13
  export { DataJsonb } from './data-jsonb';
11
14
  export { DataOwnedFields } from './data-owned-fields';
12
15
  export { DataOwnershipInEntity } from './data-ownership-in-entity';
package/esm/data/index.js CHANGED
@@ -1,12 +1,15 @@
1
1
  export { DataCompositeField } from './data-composite-field';
2
2
  export { DataDirectOwner } from './data-direct-owner';
3
3
  export { DataEntityMembership } from './data-entity-membership';
4
+ export { DataFeatureFlag } from './data-feature-flag';
4
5
  export { DataForceCurrentUser } from './data-force-current-user';
5
6
  export { DataId } from './data-id';
7
+ export { DataImageEmbedding } from './data-image-embedding';
6
8
  export { DataImmutableFields } from './data-immutable-fields';
7
9
  export { DataInflection } from './data-inflection';
8
10
  export { DataInheritFromParent } from './data-inherit-from-parent';
9
11
  export { DataJobTrigger } from './data-job-trigger';
12
+ export { DataLimitCounter } from './data-limit-counter';
10
13
  export { DataJsonb } from './data-jsonb';
11
14
  export { DataOwnedFields } from './data-owned-fields';
12
15
  export { DataOwnershipInEntity } from './data-ownership-in-entity';
@@ -42,6 +42,7 @@ export const ViewAggregated = {
42
42
  },
43
43
  alias: {
44
44
  type: 'string',
45
+ format: 'column-ref',
45
46
  description: 'Output column name'
46
47
  }
47
48
  },
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "node-type-registry",
3
- "version": "0.21.0",
3
+ "version": "0.23.0",
4
4
  "description": "Node type definitions for the Constructive blueprint system. Single source of truth for all Authz*, Data*, Relation*, and View* node types.",
5
5
  "author": "Constructive <developers@constructive.io>",
6
6
  "main": "index.js",
@@ -47,5 +47,5 @@
47
47
  "registry",
48
48
  "graphile"
49
49
  ],
50
- "gitHead": "425a7111ec17cbe975a12c8528e7cef151fc03df"
50
+ "gitHead": "fb12131bc72ca66e2eb554e15c49e35dc5b362ac"
51
51
  }
@@ -45,6 +45,7 @@ exports.ViewAggregated = {
45
45
  },
46
46
  alias: {
47
47
  type: 'string',
48
+ format: 'column-ref',
48
49
  description: 'Output column name'
49
50
  }
50
51
  },
@@ -1,2 +0,0 @@
1
- import type { NodeTypeDefinition } from '../types';
2
- export declare const AuthzMembership: NodeTypeDefinition;
@@ -1,2 +0,0 @@
1
- import type { NodeTypeDefinition } from '../types';
2
- export declare const AuthzMembership: NodeTypeDefinition;