Feature Policies API + Invitations Policies (#375)
- Added Feature Policy API: a declarative system to enable/disable/modify default behavior in the SaaS kit - Team invitation policies with pre-checks using the Feature Policy API: Invite Members dialog now shows loading, errors, and clear reasons when invitations are blocked - Version bump to 2.16.0 and widespread dependency updates (Supabase, React types, react-i18next, etc.). - Added comprehensive docs for the new policy system and orchestrators. - Subscription cancellations now trigger immediate invoicing explicitly
This commit is contained in:
committed by
GitHub
parent
3c13b5ec1e
commit
1dd6fdad22
81
packages/policies/src/registry.ts
Normal file
81
packages/policies/src/registry.ts
Normal file
@@ -0,0 +1,81 @@
|
||||
import { createRegistry } from '@kit/shared/registry';
|
||||
|
||||
import type { FeaturePolicyDefinition } from './declarative';
|
||||
import type { PolicyContext } from './types';
|
||||
|
||||
/**
|
||||
* Simple policy registry interface
|
||||
*/
|
||||
export interface PolicyRegistry {
|
||||
/** Register a single policy definition */
|
||||
registerPolicy<
|
||||
TContext extends PolicyContext = PolicyContext,
|
||||
TConfig = unknown,
|
||||
>(
|
||||
definition: FeaturePolicyDefinition<TContext, TConfig>,
|
||||
): PolicyRegistry;
|
||||
|
||||
/** Get a policy definition by ID */
|
||||
getPolicy<TContext extends PolicyContext = PolicyContext, TConfig = unknown>(
|
||||
id: string,
|
||||
): Promise<FeaturePolicyDefinition<TContext, TConfig>>;
|
||||
|
||||
/** Check if a policy exists */
|
||||
hasPolicy(id: string): boolean;
|
||||
|
||||
/** List all registered policy IDs */
|
||||
listPolicies(): string[];
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new policy registry instance
|
||||
*/
|
||||
export function createPolicyRegistry(): PolicyRegistry {
|
||||
const baseRegistry = createRegistry<
|
||||
FeaturePolicyDefinition<PolicyContext, unknown>,
|
||||
string
|
||||
>();
|
||||
|
||||
const policyIds = new Set<string>();
|
||||
|
||||
return {
|
||||
registerPolicy<
|
||||
TContext extends PolicyContext = PolicyContext,
|
||||
TConfig = unknown,
|
||||
>(definition: FeaturePolicyDefinition<TContext, TConfig>) {
|
||||
// Check for duplicates
|
||||
if (policyIds.has(definition.id)) {
|
||||
throw new Error(
|
||||
`Policy with ID "${definition.id}" is already registered`,
|
||||
);
|
||||
}
|
||||
|
||||
// Register the policy definition
|
||||
baseRegistry.register(definition.id, () => definition);
|
||||
policyIds.add(definition.id);
|
||||
|
||||
return this;
|
||||
},
|
||||
|
||||
async getPolicy<
|
||||
TContext extends PolicyContext = PolicyContext,
|
||||
TConfig = unknown,
|
||||
>(id: string) {
|
||||
if (!policyIds.has(id)) {
|
||||
throw new Error(`Policy with ID "${id}" is not registered`);
|
||||
}
|
||||
|
||||
return baseRegistry.get(id) as Promise<
|
||||
FeaturePolicyDefinition<TContext, TConfig>
|
||||
>;
|
||||
},
|
||||
|
||||
hasPolicy(id: string) {
|
||||
return policyIds.has(id);
|
||||
},
|
||||
|
||||
listPolicies() {
|
||||
return Array.from(policyIds);
|
||||
},
|
||||
};
|
||||
}
|
||||
Reference in New Issue
Block a user