node-type-registry 0.18.1 → 0.20.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/authz/authz-allow-all.js +10 -10
- package/authz/authz-composite.js +28 -28
- package/authz/authz-deny-all.js +10 -10
- package/authz/authz-direct-owner-any.js +19 -18
- package/authz/authz-direct-owner.js +17 -16
- package/authz/authz-entity-membership.js +39 -38
- package/authz/authz-member-list.js +17 -16
- package/authz/authz-membership-check.js +34 -34
- package/authz/authz-not-read-only.js +23 -22
- package/authz/authz-org-hierarchy.js +33 -31
- package/authz/authz-peer-ownership.js +40 -39
- package/authz/authz-publishable.js +26 -24
- package/authz/authz-related-entity-membership.js +57 -55
- package/authz/authz-related-member-list.js +35 -32
- package/authz/authz-related-peer-ownership.js +62 -59
- package/authz/authz-temporal.js +32 -30
- package/authz/index.d.ts +9 -9
- package/authz/index.js +19 -19
- package/blueprint-types.generated.d.ts +10 -17
- package/blueprint-types.generated.js +1 -1
- package/codegen/generate-types.js +10 -21
- package/data/data-composite-field.js +27 -25
- package/data/data-direct-owner.js +24 -23
- package/data/data-entity-membership.js +24 -23
- package/data/data-force-current-user.js +17 -16
- package/data/data-id.js +16 -15
- package/data/data-immutable-fields.js +20 -19
- package/data/data-inflection.js +33 -32
- package/data/data-inherit-from-parent.js +31 -29
- package/data/data-job-trigger.js +87 -84
- package/data/data-jsonb.js +27 -26
- package/data/data-owned-fields.js +25 -23
- package/data/data-ownership-in-entity.js +21 -21
- package/data/data-peoplestamps.js +19 -19
- package/data/data-publishable.js +16 -16
- package/data/data-slug.js +21 -19
- package/data/data-soft-delete.js +14 -14
- package/data/data-status-field.js +32 -31
- package/data/data-tags.js +23 -22
- package/data/data-timestamps.js +15 -15
- package/data/index.d.ts +17 -17
- package/data/index.js +35 -35
- package/data/search-bm25.js +34 -33
- package/data/search-full-text.js +49 -47
- package/data/search-spatial-aggregate.js +77 -74
- package/data/search-spatial.js +51 -50
- package/data/search-trgm.js +20 -19
- package/data/search-unified.js +170 -162
- package/data/search-vector.js +104 -101
- package/data/table-organization-settings.js +13 -13
- package/data/table-user-profiles.js +13 -13
- package/data/table-user-settings.js +13 -13
- package/esm/authz/authz-allow-all.js +10 -10
- package/esm/authz/authz-composite.js +28 -28
- package/esm/authz/authz-deny-all.js +10 -10
- package/esm/authz/authz-direct-owner-any.js +19 -18
- package/esm/authz/authz-direct-owner.js +17 -16
- package/esm/authz/authz-entity-membership.js +39 -38
- package/esm/authz/authz-member-list.js +17 -16
- package/esm/authz/authz-membership-check.js +34 -34
- package/esm/authz/authz-not-read-only.js +23 -22
- package/esm/authz/authz-org-hierarchy.js +33 -31
- package/esm/authz/authz-peer-ownership.js +40 -39
- package/esm/authz/authz-publishable.js +26 -24
- package/esm/authz/authz-related-entity-membership.js +57 -55
- package/esm/authz/authz-related-member-list.js +35 -32
- package/esm/authz/authz-related-peer-ownership.js +62 -59
- package/esm/authz/authz-temporal.js +32 -30
- package/esm/authz/index.d.ts +9 -9
- package/esm/authz/index.js +9 -9
- package/esm/blueprint-types.generated.d.ts +10 -17
- package/esm/blueprint-types.generated.js +1 -1
- package/esm/codegen/generate-types.js +10 -21
- package/esm/data/data-composite-field.js +27 -25
- package/esm/data/data-direct-owner.js +24 -23
- package/esm/data/data-entity-membership.js +24 -23
- package/esm/data/data-force-current-user.js +17 -16
- package/esm/data/data-id.js +16 -15
- package/esm/data/data-immutable-fields.js +20 -19
- package/esm/data/data-inflection.js +33 -32
- package/esm/data/data-inherit-from-parent.js +31 -29
- package/esm/data/data-job-trigger.js +87 -84
- package/esm/data/data-jsonb.js +27 -26
- package/esm/data/data-owned-fields.js +25 -23
- package/esm/data/data-ownership-in-entity.js +21 -21
- package/esm/data/data-peoplestamps.js +19 -19
- package/esm/data/data-publishable.js +16 -16
- package/esm/data/data-slug.js +21 -19
- package/esm/data/data-soft-delete.js +14 -14
- package/esm/data/data-status-field.js +32 -31
- package/esm/data/data-tags.js +23 -22
- package/esm/data/data-timestamps.js +15 -15
- package/esm/data/index.d.ts +17 -17
- package/esm/data/index.js +17 -17
- package/esm/data/search-bm25.js +34 -33
- package/esm/data/search-full-text.js +49 -47
- package/esm/data/search-spatial-aggregate.js +77 -74
- package/esm/data/search-spatial.js +51 -50
- package/esm/data/search-trgm.js +20 -19
- package/esm/data/search-unified.js +170 -162
- package/esm/data/search-vector.js +104 -101
- package/esm/data/table-organization-settings.js +13 -13
- package/esm/data/table-user-profiles.js +13 -13
- package/esm/data/table-user-settings.js +13 -13
- package/esm/index.d.ts +3 -3
- package/esm/index.js +3 -3
- package/esm/module-presets/auth-email-magic.js +2 -2
- package/esm/module-presets/auth-email.js +8 -8
- package/esm/module-presets/auth-passkey.js +4 -4
- package/esm/module-presets/auth-sso.js +7 -7
- package/esm/module-presets/full.js +1 -1
- package/esm/module-presets/index.d.ts +5 -5
- package/esm/module-presets/index.js +4 -4
- package/esm/relation/index.d.ts +1 -1
- package/esm/relation/index.js +1 -1
- package/esm/relation/relation-belongs-to.js +41 -40
- package/esm/relation/relation-has-many.js +42 -41
- package/esm/relation/relation-has-one.js +42 -41
- package/esm/relation/relation-many-to-many.js +70 -68
- package/esm/relation/relation-spatial.js +54 -54
- package/esm/view/index.d.ts +3 -3
- package/esm/view/index.js +3 -3
- package/esm/view/view-aggregated.js +50 -48
- package/esm/view/view-composite.js +18 -18
- package/esm/view/view-filtered-table.js +37 -36
- package/esm/view/view-joined-tables.js +65 -61
- package/esm/view/view-table-projection.js +29 -28
- package/index.d.ts +3 -3
- package/index.js +3 -3
- package/module-presets/auth-email-magic.js +2 -2
- package/module-presets/auth-email.js +8 -8
- package/module-presets/auth-passkey.js +4 -4
- package/module-presets/auth-sso.js +7 -7
- package/module-presets/full.js +1 -1
- package/module-presets/index.d.ts +5 -5
- package/module-presets/index.js +7 -7
- package/package.json +2 -2
- package/relation/index.d.ts +1 -1
- package/relation/index.js +3 -3
- package/relation/relation-belongs-to.js +41 -40
- package/relation/relation-has-many.js +42 -41
- package/relation/relation-has-one.js +42 -41
- package/relation/relation-many-to-many.js +70 -68
- package/relation/relation-spatial.js +54 -54
- package/view/index.d.ts +3 -3
- package/view/index.js +7 -7
- package/view/view-aggregated.js +50 -48
- package/view/view-composite.js +18 -18
- package/view/view-filtered-table.js +37 -36
- package/view/view-joined-tables.js +65 -61
- package/view/view-table-projection.js +29 -28
package/authz/index.d.ts
CHANGED
|
@@ -1,16 +1,16 @@
|
|
|
1
|
+
export { AuthzAllowAll } from './authz-allow-all';
|
|
2
|
+
export { AuthzComposite } from './authz-composite';
|
|
3
|
+
export { AuthzDenyAll } from './authz-deny-all';
|
|
1
4
|
export { AuthzDirectOwner } from './authz-direct-owner';
|
|
2
5
|
export { AuthzDirectOwnerAny } from './authz-direct-owner-any';
|
|
3
|
-
export { AuthzMembership } from './authz-membership-check';
|
|
4
6
|
export { AuthzEntityMembership } from './authz-entity-membership';
|
|
5
|
-
export { AuthzRelatedEntityMembership } from './authz-related-entity-membership';
|
|
6
|
-
export { AuthzOrgHierarchy } from './authz-org-hierarchy';
|
|
7
|
-
export { AuthzTemporal } from './authz-temporal';
|
|
8
|
-
export { AuthzPublishable } from './authz-publishable';
|
|
9
7
|
export { AuthzMemberList } from './authz-member-list';
|
|
10
|
-
export {
|
|
11
|
-
export { AuthzAllowAll } from './authz-allow-all';
|
|
12
|
-
export { AuthzDenyAll } from './authz-deny-all';
|
|
13
|
-
export { AuthzComposite } from './authz-composite';
|
|
8
|
+
export { AuthzMembership } from './authz-membership-check';
|
|
14
9
|
export { AuthzNotReadOnly } from './authz-not-read-only';
|
|
10
|
+
export { AuthzOrgHierarchy } from './authz-org-hierarchy';
|
|
15
11
|
export { AuthzPeerOwnership } from './authz-peer-ownership';
|
|
12
|
+
export { AuthzPublishable } from './authz-publishable';
|
|
13
|
+
export { AuthzRelatedEntityMembership } from './authz-related-entity-membership';
|
|
14
|
+
export { AuthzRelatedMemberList } from './authz-related-member-list';
|
|
16
15
|
export { AuthzRelatedPeerOwnership } from './authz-related-peer-ownership';
|
|
16
|
+
export { AuthzTemporal } from './authz-temporal';
|
package/authz/index.js
CHANGED
|
@@ -1,35 +1,35 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.
|
|
3
|
+
exports.AuthzTemporal = exports.AuthzRelatedPeerOwnership = exports.AuthzRelatedMemberList = exports.AuthzRelatedEntityMembership = exports.AuthzPublishable = exports.AuthzPeerOwnership = exports.AuthzOrgHierarchy = exports.AuthzNotReadOnly = exports.AuthzMembership = exports.AuthzMemberList = exports.AuthzEntityMembership = exports.AuthzDirectOwnerAny = exports.AuthzDirectOwner = exports.AuthzDenyAll = exports.AuthzComposite = exports.AuthzAllowAll = void 0;
|
|
4
|
+
var authz_allow_all_1 = require("./authz-allow-all");
|
|
5
|
+
Object.defineProperty(exports, "AuthzAllowAll", { enumerable: true, get: function () { return authz_allow_all_1.AuthzAllowAll; } });
|
|
6
|
+
var authz_composite_1 = require("./authz-composite");
|
|
7
|
+
Object.defineProperty(exports, "AuthzComposite", { enumerable: true, get: function () { return authz_composite_1.AuthzComposite; } });
|
|
8
|
+
var authz_deny_all_1 = require("./authz-deny-all");
|
|
9
|
+
Object.defineProperty(exports, "AuthzDenyAll", { enumerable: true, get: function () { return authz_deny_all_1.AuthzDenyAll; } });
|
|
4
10
|
var authz_direct_owner_1 = require("./authz-direct-owner");
|
|
5
11
|
Object.defineProperty(exports, "AuthzDirectOwner", { enumerable: true, get: function () { return authz_direct_owner_1.AuthzDirectOwner; } });
|
|
6
12
|
var authz_direct_owner_any_1 = require("./authz-direct-owner-any");
|
|
7
13
|
Object.defineProperty(exports, "AuthzDirectOwnerAny", { enumerable: true, get: function () { return authz_direct_owner_any_1.AuthzDirectOwnerAny; } });
|
|
8
|
-
var authz_membership_check_1 = require("./authz-membership-check");
|
|
9
|
-
Object.defineProperty(exports, "AuthzMembership", { enumerable: true, get: function () { return authz_membership_check_1.AuthzMembership; } });
|
|
10
14
|
var authz_entity_membership_1 = require("./authz-entity-membership");
|
|
11
15
|
Object.defineProperty(exports, "AuthzEntityMembership", { enumerable: true, get: function () { return authz_entity_membership_1.AuthzEntityMembership; } });
|
|
12
|
-
var authz_related_entity_membership_1 = require("./authz-related-entity-membership");
|
|
13
|
-
Object.defineProperty(exports, "AuthzRelatedEntityMembership", { enumerable: true, get: function () { return authz_related_entity_membership_1.AuthzRelatedEntityMembership; } });
|
|
14
|
-
var authz_org_hierarchy_1 = require("./authz-org-hierarchy");
|
|
15
|
-
Object.defineProperty(exports, "AuthzOrgHierarchy", { enumerable: true, get: function () { return authz_org_hierarchy_1.AuthzOrgHierarchy; } });
|
|
16
|
-
var authz_temporal_1 = require("./authz-temporal");
|
|
17
|
-
Object.defineProperty(exports, "AuthzTemporal", { enumerable: true, get: function () { return authz_temporal_1.AuthzTemporal; } });
|
|
18
|
-
var authz_publishable_1 = require("./authz-publishable");
|
|
19
|
-
Object.defineProperty(exports, "AuthzPublishable", { enumerable: true, get: function () { return authz_publishable_1.AuthzPublishable; } });
|
|
20
16
|
var authz_member_list_1 = require("./authz-member-list");
|
|
21
17
|
Object.defineProperty(exports, "AuthzMemberList", { enumerable: true, get: function () { return authz_member_list_1.AuthzMemberList; } });
|
|
22
|
-
var
|
|
23
|
-
Object.defineProperty(exports, "
|
|
24
|
-
var authz_allow_all_1 = require("./authz-allow-all");
|
|
25
|
-
Object.defineProperty(exports, "AuthzAllowAll", { enumerable: true, get: function () { return authz_allow_all_1.AuthzAllowAll; } });
|
|
26
|
-
var authz_deny_all_1 = require("./authz-deny-all");
|
|
27
|
-
Object.defineProperty(exports, "AuthzDenyAll", { enumerable: true, get: function () { return authz_deny_all_1.AuthzDenyAll; } });
|
|
28
|
-
var authz_composite_1 = require("./authz-composite");
|
|
29
|
-
Object.defineProperty(exports, "AuthzComposite", { enumerable: true, get: function () { return authz_composite_1.AuthzComposite; } });
|
|
18
|
+
var authz_membership_check_1 = require("./authz-membership-check");
|
|
19
|
+
Object.defineProperty(exports, "AuthzMembership", { enumerable: true, get: function () { return authz_membership_check_1.AuthzMembership; } });
|
|
30
20
|
var authz_not_read_only_1 = require("./authz-not-read-only");
|
|
31
21
|
Object.defineProperty(exports, "AuthzNotReadOnly", { enumerable: true, get: function () { return authz_not_read_only_1.AuthzNotReadOnly; } });
|
|
22
|
+
var authz_org_hierarchy_1 = require("./authz-org-hierarchy");
|
|
23
|
+
Object.defineProperty(exports, "AuthzOrgHierarchy", { enumerable: true, get: function () { return authz_org_hierarchy_1.AuthzOrgHierarchy; } });
|
|
32
24
|
var authz_peer_ownership_1 = require("./authz-peer-ownership");
|
|
33
25
|
Object.defineProperty(exports, "AuthzPeerOwnership", { enumerable: true, get: function () { return authz_peer_ownership_1.AuthzPeerOwnership; } });
|
|
26
|
+
var authz_publishable_1 = require("./authz-publishable");
|
|
27
|
+
Object.defineProperty(exports, "AuthzPublishable", { enumerable: true, get: function () { return authz_publishable_1.AuthzPublishable; } });
|
|
28
|
+
var authz_related_entity_membership_1 = require("./authz-related-entity-membership");
|
|
29
|
+
Object.defineProperty(exports, "AuthzRelatedEntityMembership", { enumerable: true, get: function () { return authz_related_entity_membership_1.AuthzRelatedEntityMembership; } });
|
|
30
|
+
var authz_related_member_list_1 = require("./authz-related-member-list");
|
|
31
|
+
Object.defineProperty(exports, "AuthzRelatedMemberList", { enumerable: true, get: function () { return authz_related_member_list_1.AuthzRelatedMemberList; } });
|
|
34
32
|
var authz_related_peer_ownership_1 = require("./authz-related-peer-ownership");
|
|
35
33
|
Object.defineProperty(exports, "AuthzRelatedPeerOwnership", { enumerable: true, get: function () { return authz_related_peer_ownership_1.AuthzRelatedPeerOwnership; } });
|
|
34
|
+
var authz_temporal_1 = require("./authz-temporal");
|
|
35
|
+
Object.defineProperty(exports, "AuthzTemporal", { enumerable: true, get: function () { return authz_temporal_1.AuthzTemporal; } });
|
|
@@ -574,19 +574,6 @@ export interface BlueprintTableUniqueConstraint {
|
|
|
574
574
|
/** Optional schema name override. */
|
|
575
575
|
schema_name?: string;
|
|
576
576
|
}
|
|
577
|
-
/** A storage-specific RLS policy object for apply_storage_security(). Each entry defines an Authz* policy with explicit privileges, scoped to specific storage tables. */
|
|
578
|
-
export interface BlueprintStoragePolicy {
|
|
579
|
-
/** Authz* policy generator type (e.g., "AuthzPublishable", "AuthzDirectOwner", "AuthzEntityMembership"). */
|
|
580
|
-
$type: string;
|
|
581
|
-
/** Privilege array (e.g., ["select", "insert", "update", "delete"]). Intersected with each storage table's supported operations. */
|
|
582
|
-
privileges: string[];
|
|
583
|
-
/** Policy data config. Auto-derived from $type when omitted (e.g., AuthzPublishable defaults to {"is_published_field": "is_public", "require_published_at": false}). */
|
|
584
|
-
data?: Record<string, unknown>;
|
|
585
|
-
/** Which storage tables to apply this policy to. Defaults to all three when omitted. Uses logical names (not prefixed). */
|
|
586
|
-
tables?: ('buckets' | 'files' | 'upload_requests')[];
|
|
587
|
-
/** Custom RLS policy name suffix. Auto-derived from $type when omitted (pub/own/mem). */
|
|
588
|
-
policy_name?: string;
|
|
589
|
-
}
|
|
590
577
|
/** A bucket seed entry for storage_config.buckets[]. Creates an initial bucket row in the {prefix}_buckets table during entity type provisioning. Only used for app-level storage (not entity-scoped). */
|
|
591
578
|
export interface BlueprintBucketSeed {
|
|
592
579
|
/** Bucket key name (e.g., "avatars", "documents"). Becomes the key column value. */
|
|
@@ -602,10 +589,8 @@ export interface BlueprintBucketSeed {
|
|
|
602
589
|
/** CORS allowed origins for this bucket. */
|
|
603
590
|
allowed_origins?: string[];
|
|
604
591
|
}
|
|
605
|
-
/** Storage configuration for an entity type.
|
|
592
|
+
/** 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. */
|
|
606
593
|
export interface BlueprintStorageConfig {
|
|
607
|
-
/** Custom RLS policies for storage tables. When provided, replaces the default policy set (AuthzPublishable + membership + AuthzDirectOwner). Each entry is a policy object with $type, privileges, and optional data/tables/policy_name. */
|
|
608
|
-
policies?: BlueprintStoragePolicy[];
|
|
609
594
|
/** Initial bucket seed entries. Each creates a row in {prefix}_buckets during provisioning. Only used for app-level storage (not entity-scoped). */
|
|
610
595
|
buckets?: BlueprintBucketSeed[];
|
|
611
596
|
/** Override for presigned upload URL expiry time in seconds. */
|
|
@@ -616,6 +601,12 @@ export interface BlueprintStorageConfig {
|
|
|
616
601
|
default_max_file_size?: number;
|
|
617
602
|
/** CORS allowed origins for the storage module. */
|
|
618
603
|
allowed_origins?: string[];
|
|
604
|
+
/** 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. */
|
|
605
|
+
provisions?: {
|
|
606
|
+
files?: BlueprintEntityTableProvision;
|
|
607
|
+
buckets?: BlueprintEntityTableProvision;
|
|
608
|
+
upload_requests?: BlueprintEntityTableProvision;
|
|
609
|
+
};
|
|
619
610
|
}
|
|
620
611
|
/** Override object for the entity table created by a BlueprintEntityType. Shape mirrors BlueprintTable / secure_table_provision vocabulary. When supplied, policies[] replaces the default entity-table policies entirely. */
|
|
621
612
|
export interface BlueprintEntityTableProvision {
|
|
@@ -655,6 +646,8 @@ export interface BlueprintEntityType {
|
|
|
655
646
|
has_levels?: boolean;
|
|
656
647
|
/** Whether to provision a storage module (buckets, files, upload_requests tables) for this entity type. Defaults to false. */
|
|
657
648
|
has_storage?: boolean;
|
|
649
|
+
/** Whether to provision entity-scoped invite tables ({prefix}_invites, {prefix}_claimed_invites) and a submit_{prefix}_invite_code() function. Defaults to false. */
|
|
650
|
+
has_invites?: boolean;
|
|
658
651
|
/** Escape hatch: when true AND table_provision is NULL, zero policies are provisioned on the entity table. Defaults to false. */
|
|
659
652
|
skip_entity_policies?: boolean;
|
|
660
653
|
/** 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). */
|
|
@@ -877,6 +870,6 @@ export interface BlueprintDefinition {
|
|
|
877
870
|
unique_constraints?: BlueprintUniqueConstraint[];
|
|
878
871
|
/** Entity types to provision in Phase 0 (before tables). Each entry creates an entity table with membership modules and security. */
|
|
879
872
|
entity_types?: BlueprintEntityType[];
|
|
880
|
-
/** App-level storage configuration. Creates a storage_module (membership_type = NULL)
|
|
873
|
+
/** App-level storage configuration. Creates a storage_module (membership_type = NULL), seeds initial buckets, and overrides module-level settings (expiry times, file size limits, CORS). Use provisions for per-table policy overrides. For entity-scoped storage, use entity_types[].has_storage + entity_types[].storage instead. */
|
|
881
874
|
storage?: BlueprintStorageConfig;
|
|
882
875
|
}
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
/* eslint-disable @typescript-eslint/no-empty-object-type */
|
|
4
4
|
//
|
|
5
5
|
// Regenerate with:
|
|
6
|
-
// cd
|
|
6
|
+
// cd packages/node-type-registry && pnpm generate:types
|
|
7
7
|
//
|
|
8
8
|
// These types match the JSONB shape expected by construct_blueprint().
|
|
9
9
|
// All field names are snake_case to match the SQL convention.
|
|
@@ -394,21 +394,6 @@ function buildBlueprintTableUniqueConstraint() {
|
|
|
394
394
|
addJSDoc(optionalProp('schema_name', t.tsStringKeyword()), 'Optional schema name override.')
|
|
395
395
|
]), 'A unique constraint nested inside a table definition (table_name not required).');
|
|
396
396
|
}
|
|
397
|
-
/**
|
|
398
|
-
* Build the BlueprintStoragePolicy interface.
|
|
399
|
-
*
|
|
400
|
-
* Matches the jsonb policy objects accepted by apply_storage_security():
|
|
401
|
-
* { "$type": "AuthzPublishable", "privileges": ["select"], "data": {...}, "tables": [...], "policy_name": "pub" }
|
|
402
|
-
*/
|
|
403
|
-
function buildBlueprintStoragePolicy() {
|
|
404
|
-
return addJSDoc(exportInterface('BlueprintStoragePolicy', [
|
|
405
|
-
addJSDoc(requiredProp('$type', t.tsStringKeyword()), 'Authz* policy generator type (e.g., "AuthzPublishable", "AuthzDirectOwner", "AuthzEntityMembership").'),
|
|
406
|
-
addJSDoc(requiredProp('privileges', t.tsArrayType(t.tsStringKeyword())), 'Privilege array (e.g., ["select", "insert", "update", "delete"]). Intersected with each storage table\'s supported operations.'),
|
|
407
|
-
addJSDoc(optionalProp('data', recordType(t.tsStringKeyword(), t.tsUnknownKeyword())), 'Policy data config. Auto-derived from $type when omitted (e.g., AuthzPublishable defaults to {"is_published_field": "is_public", "require_published_at": false}).'),
|
|
408
|
-
addJSDoc(optionalProp('tables', t.tsArrayType(strUnion(['buckets', 'files', 'upload_requests']))), 'Which storage tables to apply this policy to. Defaults to all three when omitted. Uses logical names (not prefixed).'),
|
|
409
|
-
addJSDoc(optionalProp('policy_name', t.tsStringKeyword()), 'Custom RLS policy name suffix. Auto-derived from $type when omitted (pub/own/mem).')
|
|
410
|
-
]), 'A storage-specific RLS policy object for apply_storage_security(). Each entry defines an Authz* policy with explicit privileges, scoped to specific storage tables.');
|
|
411
|
-
}
|
|
412
397
|
/**
|
|
413
398
|
* Build the BlueprintBucketSeed interface.
|
|
414
399
|
*
|
|
@@ -431,13 +416,17 @@ function buildBlueprintBucketSeed() {
|
|
|
431
416
|
*/
|
|
432
417
|
function buildBlueprintStorageConfig() {
|
|
433
418
|
return addJSDoc(exportInterface('BlueprintStorageConfig', [
|
|
434
|
-
addJSDoc(optionalProp('policies', t.tsArrayType(t.tsTypeReference(t.identifier('BlueprintStoragePolicy')))), 'Custom RLS policies for storage tables. When provided, replaces the default policy set (AuthzPublishable + membership + AuthzDirectOwner). Each entry is a policy object with $type, privileges, and optional data/tables/policy_name.'),
|
|
435
419
|
addJSDoc(optionalProp('buckets', t.tsArrayType(t.tsTypeReference(t.identifier('BlueprintBucketSeed')))), 'Initial bucket seed entries. Each creates a row in {prefix}_buckets during provisioning. Only used for app-level storage (not entity-scoped).'),
|
|
436
420
|
addJSDoc(optionalProp('upload_url_expiry_seconds', t.tsNumberKeyword()), 'Override for presigned upload URL expiry time in seconds.'),
|
|
437
421
|
addJSDoc(optionalProp('download_url_expiry_seconds', t.tsNumberKeyword()), 'Override for presigned download URL expiry time in seconds.'),
|
|
438
422
|
addJSDoc(optionalProp('default_max_file_size', t.tsNumberKeyword()), 'Default maximum file size in bytes for the storage module.'),
|
|
439
|
-
addJSDoc(optionalProp('allowed_origins', t.tsArrayType(t.tsStringKeyword())), 'CORS allowed origins for the storage module.')
|
|
440
|
-
|
|
423
|
+
addJSDoc(optionalProp('allowed_origins', t.tsArrayType(t.tsStringKeyword())), 'CORS allowed origins for the storage module.'),
|
|
424
|
+
addJSDoc(optionalProp('provisions', t.tsTypeLiteral([
|
|
425
|
+
optionalProp('files', t.tsTypeReference(t.identifier('BlueprintEntityTableProvision'))),
|
|
426
|
+
optionalProp('buckets', t.tsTypeReference(t.identifier('BlueprintEntityTableProvision'))),
|
|
427
|
+
optionalProp('upload_requests', t.tsTypeReference(t.identifier('BlueprintEntityTableProvision')))
|
|
428
|
+
])), '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.')
|
|
429
|
+
]), '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.');
|
|
441
430
|
}
|
|
442
431
|
function buildBlueprintEntityTableProvision() {
|
|
443
432
|
return addJSDoc(exportInterface('BlueprintEntityTableProvision', [
|
|
@@ -463,6 +452,7 @@ function buildBlueprintEntityType() {
|
|
|
463
452
|
addJSDoc(optionalProp('has_profiles', t.tsBooleanKeyword()), 'Whether to provision a profiles module for this entity type. Defaults to false.'),
|
|
464
453
|
addJSDoc(optionalProp('has_levels', t.tsBooleanKeyword()), 'Whether to provision a levels module for this entity type. Defaults to false.'),
|
|
465
454
|
addJSDoc(optionalProp('has_storage', t.tsBooleanKeyword()), 'Whether to provision a storage module (buckets, files, upload_requests tables) for this entity type. Defaults to false.'),
|
|
455
|
+
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.'),
|
|
466
456
|
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.'),
|
|
467
457
|
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).'),
|
|
468
458
|
addJSDoc(optionalProp('storage', t.tsTypeReference(t.identifier('BlueprintStorageConfig'))), 'Storage configuration. Only used when has_storage is true. Controls RLS policies on storage tables, seeds initial buckets, and overrides module-level settings (expiry times, file size limits, CORS).')
|
|
@@ -493,7 +483,7 @@ function buildBlueprintDefinition() {
|
|
|
493
483
|
addJSDoc(optionalProp('full_text_searches', t.tsArrayType(t.tsTypeReference(t.identifier('BlueprintFullTextSearch')))), 'Full-text search configurations.'),
|
|
494
484
|
addJSDoc(optionalProp('unique_constraints', t.tsArrayType(t.tsTypeReference(t.identifier('BlueprintUniqueConstraint')))), 'Unique constraints on table columns.'),
|
|
495
485
|
addJSDoc(optionalProp('entity_types', t.tsArrayType(t.tsTypeReference(t.identifier('BlueprintEntityType')))), 'Entity types to provision in Phase 0 (before tables). Each entry creates an entity table with membership modules and security.'),
|
|
496
|
-
addJSDoc(optionalProp('storage', t.tsTypeReference(t.identifier('BlueprintStorageConfig'))), 'App-level storage configuration. Creates a storage_module (membership_type = NULL)
|
|
486
|
+
addJSDoc(optionalProp('storage', t.tsTypeReference(t.identifier('BlueprintStorageConfig'))), 'App-level storage configuration. Creates a storage_module (membership_type = NULL), seeds initial buckets, and overrides module-level settings (expiry times, file size limits, CORS). Use provisions for per-table policy overrides. For entity-scoped storage, use entity_types[].has_storage + entity_types[].storage instead.')
|
|
497
487
|
]), 'The complete blueprint definition -- the JSONB shape accepted by construct_blueprint().');
|
|
498
488
|
}
|
|
499
489
|
// ---------------------------------------------------------------------------
|
|
@@ -547,7 +537,6 @@ function buildProgram(meta) {
|
|
|
547
537
|
statements.push(buildBlueprintTableIndex());
|
|
548
538
|
statements.push(buildBlueprintUniqueConstraint());
|
|
549
539
|
statements.push(buildBlueprintTableUniqueConstraint());
|
|
550
|
-
statements.push(buildBlueprintStoragePolicy());
|
|
551
540
|
statements.push(buildBlueprintBucketSeed());
|
|
552
541
|
statements.push(buildBlueprintStorageConfig());
|
|
553
542
|
statements.push(buildBlueprintEntityTableProvision());
|
|
@@ -570,7 +559,7 @@ function buildProgram(meta) {
|
|
|
570
559
|
'/* eslint-disable @typescript-eslint/no-empty-object-type */',
|
|
571
560
|
'//',
|
|
572
561
|
'// Regenerate with:',
|
|
573
|
-
'// cd
|
|
562
|
+
'// cd packages/node-type-registry && pnpm generate:types',
|
|
574
563
|
'//',
|
|
575
564
|
'// These types match the JSONB shape expected by construct_blueprint().',
|
|
576
565
|
'// All field names are snake_case to match the SQL convention.',
|
|
@@ -2,37 +2,39 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.DataCompositeField = void 0;
|
|
4
4
|
exports.DataCompositeField = {
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
5
|
+
name: 'DataCompositeField',
|
|
6
|
+
slug: 'data_composite_field',
|
|
7
|
+
category: 'data',
|
|
8
|
+
display_name: 'Composite Field',
|
|
9
|
+
description: "Creates a derived text field that automatically concatenates multiple source fields via BEFORE INSERT/UPDATE triggers. Used to produce a unified text representation (e.g., embedding_text) from multiple columns on a table. The trigger fires with '_000' prefix to run before Search* triggers alphabetically.",
|
|
10
|
+
parameter_schema: {
|
|
11
|
+
type: 'object',
|
|
12
|
+
properties: {
|
|
13
|
+
target: {
|
|
14
|
+
type: 'string',
|
|
15
|
+
format: 'column-ref',
|
|
16
|
+
description: "Name of the derived text field to create (default: 'embedding_text')"
|
|
16
17
|
},
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
18
|
+
source_fields: {
|
|
19
|
+
type: 'array',
|
|
20
|
+
items: {
|
|
21
|
+
type: 'string',
|
|
22
|
+
format: 'column-ref'
|
|
21
23
|
},
|
|
22
|
-
|
|
24
|
+
description: 'Array of source field names to concatenate into the target field'
|
|
23
25
|
},
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
26
|
+
format: {
|
|
27
|
+
type: 'string',
|
|
28
|
+
enum: ['labeled', 'plain'],
|
|
29
|
+
description: "Output format: 'labeled' (field_name: value) or 'plain' (values only). Default: 'labeled'"
|
|
28
30
|
}
|
|
29
31
|
},
|
|
30
|
-
|
|
31
|
-
|
|
32
|
+
required: [
|
|
33
|
+
'source_fields'
|
|
32
34
|
]
|
|
33
35
|
},
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
36
|
+
tags: [
|
|
37
|
+
'transform',
|
|
38
|
+
'behavior'
|
|
37
39
|
]
|
|
38
40
|
};
|
|
@@ -2,33 +2,34 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.DataDirectOwner = void 0;
|
|
4
4
|
exports.DataDirectOwner = {
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
5
|
+
name: 'DataDirectOwner',
|
|
6
|
+
slug: 'data_direct_owner',
|
|
7
|
+
category: 'data',
|
|
8
|
+
display_name: 'Ownership',
|
|
9
|
+
description: 'Adds ownership column for direct user ownership. Enables AuthzDirectOwner authorization.',
|
|
10
|
+
parameter_schema: {
|
|
11
|
+
type: 'object',
|
|
12
|
+
properties: {
|
|
13
|
+
owner_field_name: {
|
|
14
|
+
type: 'string',
|
|
15
|
+
format: 'column-ref',
|
|
16
|
+
description: 'Column name for owner ID',
|
|
17
|
+
default: 'owner_id'
|
|
17
18
|
},
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
19
|
+
include_id: {
|
|
20
|
+
type: 'boolean',
|
|
21
|
+
description: 'If true, also adds a UUID primary key column with auto-generation',
|
|
22
|
+
default: true
|
|
22
23
|
},
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
24
|
+
include_user_fk: {
|
|
25
|
+
type: 'boolean',
|
|
26
|
+
description: 'If true, adds a foreign key constraint from owner_id to the users table',
|
|
27
|
+
default: true
|
|
27
28
|
}
|
|
28
29
|
}
|
|
29
30
|
},
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
31
|
+
tags: [
|
|
32
|
+
'ownership',
|
|
33
|
+
'schema'
|
|
33
34
|
]
|
|
34
35
|
};
|
|
@@ -2,33 +2,34 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.DataEntityMembership = void 0;
|
|
4
4
|
exports.DataEntityMembership = {
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
5
|
+
name: 'DataEntityMembership',
|
|
6
|
+
slug: 'data_entity_membership',
|
|
7
|
+
category: 'data',
|
|
8
|
+
display_name: 'Entity Membership',
|
|
9
|
+
description: 'Adds entity reference for organization/group scoping. Enables AuthzEntityMembership, AuthzMembership, AuthzOrgHierarchy authorization.',
|
|
10
|
+
parameter_schema: {
|
|
11
|
+
type: 'object',
|
|
12
|
+
properties: {
|
|
13
|
+
entity_field_name: {
|
|
14
|
+
type: 'string',
|
|
15
|
+
format: 'column-ref',
|
|
16
|
+
description: 'Column name for entity ID',
|
|
17
|
+
default: 'entity_id'
|
|
17
18
|
},
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
19
|
+
include_id: {
|
|
20
|
+
type: 'boolean',
|
|
21
|
+
description: 'If true, also adds a UUID primary key column with auto-generation',
|
|
22
|
+
default: true
|
|
22
23
|
},
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
24
|
+
include_user_fk: {
|
|
25
|
+
type: 'boolean',
|
|
26
|
+
description: 'If true, adds a foreign key constraint from entity_id to the users table',
|
|
27
|
+
default: true
|
|
27
28
|
}
|
|
28
29
|
}
|
|
29
30
|
},
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
31
|
+
tags: [
|
|
32
|
+
'membership',
|
|
33
|
+
'schema'
|
|
33
34
|
]
|
|
34
35
|
};
|
|
@@ -2,24 +2,25 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.DataForceCurrentUser = void 0;
|
|
4
4
|
exports.DataForceCurrentUser = {
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
5
|
+
name: 'DataForceCurrentUser',
|
|
6
|
+
slug: 'data_force_current_user',
|
|
7
|
+
category: 'data',
|
|
8
|
+
display_name: 'Force Current User',
|
|
9
|
+
description: 'BEFORE INSERT trigger that forces a field to the value of jwt_public.current_user_id(). Prevents clients from spoofing the actor/uploader identity. The field value is always overwritten regardless of what the client provides.',
|
|
10
|
+
parameter_schema: {
|
|
11
|
+
type: 'object',
|
|
12
|
+
properties: {
|
|
13
|
+
field_name: {
|
|
14
|
+
type: 'string',
|
|
15
|
+
format: 'column-ref',
|
|
16
|
+
description: 'Name of the field to force to current_user_id()',
|
|
17
|
+
default: 'actor_id'
|
|
17
18
|
}
|
|
18
19
|
}
|
|
19
20
|
},
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
21
|
+
tags: [
|
|
22
|
+
'trigger',
|
|
23
|
+
'security',
|
|
24
|
+
'schema'
|
|
24
25
|
]
|
|
25
26
|
};
|
package/data/data-id.js
CHANGED
|
@@ -2,23 +2,24 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.DataId = void 0;
|
|
4
4
|
exports.DataId = {
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
5
|
+
name: 'DataId',
|
|
6
|
+
slug: 'data_id',
|
|
7
|
+
category: 'data',
|
|
8
|
+
display_name: 'Primary Key ID',
|
|
9
|
+
description: 'Adds a UUID primary key column with auto-generation default (uuidv7). This is the standard primary key pattern for all tables.',
|
|
10
|
+
parameter_schema: {
|
|
11
|
+
type: 'object',
|
|
12
|
+
properties: {
|
|
13
|
+
field_name: {
|
|
14
|
+
type: 'string',
|
|
15
|
+
format: 'column-ref',
|
|
16
|
+
description: 'Column name for the primary key',
|
|
17
|
+
default: 'id'
|
|
17
18
|
}
|
|
18
19
|
}
|
|
19
20
|
},
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
21
|
+
tags: [
|
|
22
|
+
'primary_key',
|
|
23
|
+
'schema'
|
|
23
24
|
]
|
|
24
25
|
};
|
|
@@ -2,29 +2,30 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.DataImmutableFields = void 0;
|
|
4
4
|
exports.DataImmutableFields = {
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
5
|
+
name: 'DataImmutableFields',
|
|
6
|
+
slug: 'data_immutable_fields',
|
|
7
|
+
category: 'data',
|
|
8
|
+
display_name: 'Immutable Fields',
|
|
9
|
+
description: 'BEFORE UPDATE trigger that prevents changes to a list of specified fields after INSERT. Raises an exception if any of the listed fields have changed. Unlike FieldImmutable (single-field), this handles multiple fields in a single trigger for efficiency.',
|
|
10
|
+
parameter_schema: {
|
|
11
|
+
type: 'object',
|
|
12
|
+
properties: {
|
|
13
|
+
fields: {
|
|
14
|
+
type: 'array',
|
|
15
|
+
items: {
|
|
16
|
+
type: 'string',
|
|
17
|
+
format: 'column-ref'
|
|
17
18
|
},
|
|
18
|
-
|
|
19
|
+
description: 'Field names that cannot be modified after INSERT (e.g. ["key", "bucket_id", "owner_id"])'
|
|
19
20
|
}
|
|
20
21
|
},
|
|
21
|
-
|
|
22
|
-
|
|
22
|
+
required: [
|
|
23
|
+
'fields'
|
|
23
24
|
]
|
|
24
25
|
},
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
26
|
+
tags: [
|
|
27
|
+
'trigger',
|
|
28
|
+
'constraint',
|
|
29
|
+
'schema'
|
|
29
30
|
]
|
|
30
31
|
};
|