Skip to content

Commit ff94a16

Browse files
committed
fix: change BlueprintPolicy.policy_type to $type to match SQL convention
The construct_blueprint SQL procedure reads policy type via: v_policy_type := v_policy_entry->>'\'; But the TypeScript BlueprintPolicy interface used 'policy_type' which doesn't match the blueprint JSON convention used by nodes and relations. Updated buildBlueprintPolicy in generate-types.ts to always use the static definition with $type (skipping the introspection-driven path which derives from the DB column name). Regenerated types.
1 parent 142443f commit ff94a16

2 files changed

Lines changed: 31 additions & 42 deletions

File tree

graphql/node-type-registry/src/blueprint-types.generated.ts

Lines changed: 22 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -683,18 +683,18 @@ export interface BlueprintField {
683683
/** Comment/description for this field. */
684684
description?: string;
685685
}
686-
/** An RLS policy entry for a blueprint table. */
686+
/** An RLS policy entry for a blueprint table. Uses $type to match the blueprint JSON convention. */
687687
export interface BlueprintPolicy {
688688
/** Authz* policy type name (e.g., "AuthzDirectOwner", "AuthzAllowAll"). */
689-
policy_type: "AuthzDirectOwner" | "AuthzDirectOwnerAny" | "AuthzMembership" | "AuthzEntityMembership" | "AuthzRelatedEntityMembership" | "AuthzOrgHierarchy" | "AuthzTemporal" | "AuthzPublishable" | "AuthzMemberList" | "AuthzRelatedMemberList" | "AuthzAllowAll" | "AuthzDenyAll" | "AuthzComposite" | "AuthzPeerOwnership" | "AuthzRelatedPeerOwnership";
689+
$type: "AuthzDirectOwner" | "AuthzDirectOwnerAny" | "AuthzMembership" | "AuthzEntityMembership" | "AuthzRelatedEntityMembership" | "AuthzOrgHierarchy" | "AuthzTemporal" | "AuthzPublishable" | "AuthzMemberList" | "AuthzRelatedMemberList" | "AuthzAllowAll" | "AuthzDenyAll" | "AuthzComposite" | "AuthzPeerOwnership" | "AuthzRelatedPeerOwnership";
690+
/** Privileges this policy applies to (e.g., ["select"], ["insert", "update", "delete"]). */
691+
privileges?: string[];
692+
/** Whether this policy is permissive (true) or restrictive (false). Defaults to true. */
693+
permissive?: boolean;
690694
/** Role for this policy. Defaults to "authenticated". */
691695
policy_role?: string;
692-
/** Whether this policy is permissive (true) or restrictive (false). */
693-
permissive?: boolean;
694696
/** Optional custom name for this policy. */
695697
policy_name?: string;
696-
/** Privileges this policy applies to. */
697-
privileges?: string[];
698698
/** Policy-specific data (structure varies by policy type). */
699699
data?: Record<string, unknown>;
700700
}
@@ -767,6 +767,22 @@ export interface BlueprintTableIndex {
767767
/** Optional schema name override. */
768768
schema_name?: string;
769769
}
770+
/** A unique constraint definition within a blueprint (top-level, requires table_name). */
771+
export interface BlueprintUniqueConstraint {
772+
/** Table name this unique constraint belongs to. */
773+
table_name: string;
774+
/** Optional schema name for disambiguation (falls back to top-level default). */
775+
schema_name?: string;
776+
/** Column names that form the unique constraint. */
777+
columns: string[];
778+
}
779+
/** A unique constraint nested inside a table definition (table_name not required). */
780+
export interface BlueprintTableUniqueConstraint {
781+
/** Column names that form the unique constraint. */
782+
columns: string[];
783+
/** Optional schema name override. */
784+
schema_name?: string;
785+
}
770786
/**
771787
* ===========================================================================
772788
* Node types -- discriminated union for nodes[] entries
@@ -946,22 +962,6 @@ export type BlueprintRelation = {
946962
* ===========================================================================
947963
*/
948964
;
949-
/** A unique constraint definition within a blueprint (top-level, requires table_name). */
950-
export interface BlueprintUniqueConstraint {
951-
/** Table name this unique constraint belongs to. */
952-
table_name: string;
953-
/** Optional schema name for disambiguation (falls back to top-level default). */
954-
schema_name?: string;
955-
/** Column names that form the unique constraint. */
956-
columns: string[];
957-
}
958-
/** A unique constraint nested inside a table definition (table_name not required). */
959-
export interface BlueprintTableUniqueConstraint {
960-
/** Column names that form the unique constraint. */
961-
columns: string[];
962-
/** Optional schema name override. */
963-
schema_name?: string;
964-
}
965965
/** A table definition within a blueprint. */
966966
export interface BlueprintTable {
967967
/** The PostgreSQL table name to create. */

graphql/node-type-registry/src/codegen/generate-types.ts

Lines changed: 9 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -324,38 +324,27 @@ function buildBlueprintField(
324324

325325
function buildBlueprintPolicy(
326326
authzNodes: NodeTypeDefinition[],
327-
meta?: MetaTableInfo[]
327+
_meta?: MetaTableInfo[]
328328
): t.ExportNamedDeclaration {
329+
// BlueprintPolicy represents the blueprint JSON shape (not the DB table).
330+
// The SQL procedure reads $type (not policy_type) from the JSONB:
331+
// v_policy_type := v_policy_entry->>'$type';
332+
// So we always use the static definition with $type.
329333
const policyTypeAnnotation =
330334
authzNodes.length > 0
331335
? strUnion(authzNodes.map((nt) => nt.name))
332336
: t.tsStringKeyword();
333337

334-
const table = meta && findTable(meta, 'metaschema_public', 'policy');
335-
if (table) {
336-
return deriveInterfaceFromTable(
337-
table,
338-
'BlueprintPolicy',
339-
'An RLS policy entry for a blueprint table. Derived from _meta.',
340-
{
341-
// policy_type gets a typed union of known Authz* node names
342-
policy_type: policyTypeAnnotation,
343-
// data is untyped JSONB — use Record<string, unknown>
344-
data: recordType(t.tsStringKeyword(), t.tsUnknownKeyword()),
345-
},
346-
);
347-
}
348-
// Static fallback
349338
return addJSDoc(
350339
exportInterface('BlueprintPolicy', [
351-
addJSDoc(requiredProp('policy_type', policyTypeAnnotation), 'Authz* policy type name (e.g., "AuthzDirectOwner", "AuthzAllowAll").'),
340+
addJSDoc(requiredProp('$type', policyTypeAnnotation), 'Authz* policy type name (e.g., "AuthzDirectOwner", "AuthzAllowAll").'),
341+
addJSDoc(optionalProp('privileges', t.tsArrayType(t.tsStringKeyword())), 'Privileges this policy applies to (e.g., ["select"], ["insert", "update", "delete"]).'),
342+
addJSDoc(optionalProp('permissive', t.tsBooleanKeyword()), 'Whether this policy is permissive (true) or restrictive (false). Defaults to true.'),
352343
addJSDoc(optionalProp('policy_role', t.tsStringKeyword()), 'Role for this policy. Defaults to "authenticated".'),
353-
addJSDoc(optionalProp('permissive', t.tsBooleanKeyword()), 'Whether this policy is permissive (true) or restrictive (false).'),
354344
addJSDoc(optionalProp('policy_name', t.tsStringKeyword()), 'Optional custom name for this policy.'),
355-
addJSDoc(optionalProp('privileges', t.tsArrayType(t.tsStringKeyword())), 'Privileges this policy applies to.'),
356345
addJSDoc(optionalProp('data', recordType(t.tsStringKeyword(), t.tsUnknownKeyword())), 'Policy-specific data (structure varies by policy type).'),
357346
]),
358-
'An RLS policy entry for a blueprint table.'
347+
'An RLS policy entry for a blueprint table. Uses $type to match the blueprint JSON convention.'
359348
);
360349
}
361350

0 commit comments

Comments
 (0)