- 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
82 lines
2.0 KiB
TypeScript
82 lines
2.0 KiB
TypeScript
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);
|
|
},
|
|
};
|
|
}
|