@@ -404,17 +404,41 @@ export const SCIMEnterpriseUserSchema = z.object({
404404
405405export type SCIMEnterpriseUser = z . infer < typeof SCIMEnterpriseUserSchema > ;
406406
407+ /**
408+ * SCIM Schema URI Validator
409+ * Validates that schema URIs are known SCIM schema identifiers
410+ */
411+ const SCIMSchemaURISchema = z . enum ( [
412+ SCIM_SCHEMAS . USER ,
413+ SCIM_SCHEMAS . GROUP ,
414+ SCIM_SCHEMAS . ENTERPRISE_USER ,
415+ SCIM_SCHEMAS . RESOURCE_TYPE ,
416+ SCIM_SCHEMAS . SERVICE_PROVIDER_CONFIG ,
417+ SCIM_SCHEMAS . SCHEMA ,
418+ SCIM_SCHEMAS . LIST_RESPONSE ,
419+ SCIM_SCHEMAS . PATCH_OP ,
420+ SCIM_SCHEMAS . BULK_REQUEST ,
421+ SCIM_SCHEMAS . BULK_RESPONSE ,
422+ SCIM_SCHEMAS . ERROR ,
423+ ] ) ;
424+
407425/**
408426 * SCIM User Schema (Core)
409427 * Complete SCIM 2.0 User resource
410428 */
411429export const SCIMUserSchema = z . object ( {
412430 /**
413431 * SCIM schema URIs
432+ * Must include at minimum the core User schema URI
414433 */
415434 schemas : z . array ( z . string ( ) )
435+ . min ( 1 )
436+ . refine (
437+ ( schemas ) => schemas . includes ( SCIM_SCHEMAS . USER ) ,
438+ 'Must include core User schema URI'
439+ )
416440 . default ( [ SCIM_SCHEMAS . USER ] )
417- . describe ( 'SCIM schema URIs' ) ,
441+ . describe ( 'SCIM schema URIs (must include User schema) ' ) ,
418442
419443 /**
420444 * Unique identifier
@@ -661,10 +685,16 @@ export type SCIMMemberReference = z.infer<typeof SCIMMemberReferenceSchema>;
661685export const SCIMGroupSchema = z . object ( {
662686 /**
663687 * SCIM schema URIs
688+ * Must include at minimum the core Group schema URI
664689 */
665690 schemas : z . array ( z . string ( ) )
691+ . min ( 1 )
692+ . refine (
693+ ( schemas ) => schemas . includes ( SCIM_SCHEMAS . GROUP ) ,
694+ 'Must include core Group schema URI'
695+ )
666696 . default ( [ SCIM_SCHEMAS . GROUP ] )
667- . describe ( 'SCIM schema URIs' ) ,
697+ . describe ( 'SCIM schema URIs (must include Group schema) ' ) ,
668698
669699 /**
670700 * Unique identifier
@@ -704,9 +734,18 @@ export const SCIMGroupSchema = z.object({
704734
705735export type SCIMGroup = z . infer < typeof SCIMGroupSchema > ;
706736
737+ /**
738+ * SCIM Resource Union Type
739+ * Known SCIM resource types for type-safe list responses
740+ */
741+ export type SCIMResource = SCIMUser | SCIMGroup ;
742+
707743/**
708744 * SCIM List Response
709745 * Paginated list of resources
746+ *
747+ * Generic type T allows for type-safe responses when the resource type is known.
748+ * For mixed resource types, use SCIMResource union.
710749 */
711750export const SCIMListResponseSchema = z . object ( {
712751 /**
@@ -726,9 +765,10 @@ export const SCIMListResponseSchema = z.object({
726765
727766 /**
728767 * Resources returned in this response
768+ * Use SCIMListResponseOf<T> for type-safe responses
729769 */
730- Resources : z . array ( z . any ( ) )
731- . describe ( 'Resources array' ) ,
770+ Resources : z . array ( z . union ( [ SCIMUserSchema , SCIMGroupSchema , z . record ( z . any ( ) ) ] ) )
771+ . describe ( 'Resources array (Users, Groups, or custom resources) ' ) ,
732772
733773 /**
734774 * 1-based index of the first result
@@ -890,10 +930,16 @@ export const SCIM = {
890930 /**
891931 * Create an error response
892932 */
893- error : ( status : number , detail : string , scimType ?: string ) : SCIMError => ( {
933+ error : (
934+ status : number ,
935+ detail : string ,
936+ scimType ?: 'invalidFilter' | 'tooMany' | 'uniqueness' | 'mutability' |
937+ 'invalidSyntax' | 'invalidPath' | 'noTarget' | 'invalidValue' |
938+ 'invalidVers' | 'sensitive'
939+ ) : SCIMError => ( {
894940 schemas : [ SCIM_SCHEMAS . ERROR ] ,
895941 status,
896942 detail,
897- scimType : scimType as any ,
943+ scimType,
898944 } ) ,
899945} as const ;
0 commit comments