@@ -29,13 +29,7 @@ const MONGOLIAN_VOWEL_SEPARATOR = String.fromCharCode(32, 6158);
2929
3030const INTERNAL_HEADERS_SAMPLE_DATA = [ MONGOLIAN_VOWEL_SEPARATOR + 'string' , MONGOLIAN_VOWEL_SEPARATOR + 'yyyy-mm-dd' ] ;
3131
32- const SUBJECT_ID_REGEX = [
33- / ^ [ ^ $ \s ] + $ / ,
34- {
35- en : 'Subject ID has to be at least 1 character long, without a $ and no whitespaces' ,
36- fr : "L'ID du sujet doit comporter au moins 1 caractère, sans $ et sans espaces"
37- }
38- ] as const ;
32+ const SUBJECT_ID_REGEX = / ^ [ ^ $ \s ] + $ / ;
3933
4034type ZodTypeName = Extract < `${z . ZodFirstPartyTypeKind } `, ( typeof ZOD_TYPE_NAMES ) [ number ] > ;
4135
@@ -122,10 +116,6 @@ function isZodEffectsDef(def: AnyZodTypeDef): def is z.ZodEffectsDef {
122116 return def . typeName === z . ZodFirstPartyTypeKind . ZodEffects ;
123117}
124118
125- function isZodObjectDef ( def : AnyZodTypeDef ) : def is z . ZodObjectDef {
126- return def . typeName === z . ZodFirstPartyTypeKind . ZodObject ;
127- }
128-
129119function extractSetEntry ( entry : string ) {
130120 const result = / S E T \( \s * ( .* ?) \s * \) / . exec ( entry ) ;
131121 if ( ! result ?. [ 1 ] ) {
@@ -622,162 +612,6 @@ function jsonToZod(givenType: unknown): RequiredZodTypeName {
622612 }
623613 throw new Error ( "Failed to interpret json value / Échec de l'interprétation de la valeur json" ) ;
624614}
625- function zod4Helper ( jsonInstrumentSchema : z4 . core . JSONSchema . BaseSchema ) {
626- if (
627- jsonInstrumentSchema . properties &&
628- jsonInstrumentSchema . required &&
629- Array . isArray ( jsonInstrumentSchema . required )
630- ) {
631- const jsonColumnNames = Object . keys ( jsonInstrumentSchema . properties ) ;
632-
633- const jsonCSVColumns = INTERNAL_HEADERS . concat ( jsonColumnNames ) ;
634- const jsonSampleData = [ ...INTERNAL_HEADERS_SAMPLE_DATA ] ;
635-
636- for ( const col of jsonColumnNames ) {
637- let optional = true ;
638- let data : ZodTypeNameResult ;
639- if ( jsonInstrumentSchema . required . includes ( col ) ) {
640- optional = false ;
641- }
642-
643- const typeSafety : PropertySchema = jsonInstrumentSchema . properties [ col ] as PropertySchema ;
644-
645- if ( typeSafety . type === 'array' ) {
646- const keys = Object . keys ( typeSafety . items . properties ) ;
647- const values = Object . values ( typeSafety . items . properties ) ;
648- const multiVals : ZodTypeNameResult [ ] = [ ] ;
649- let i = 0 ;
650-
651- for ( const val of values ) {
652- // eslint-disable-next-line max-depth
653- if (
654- ( val as Zod4Object ) . type &&
655- Array . isArray ( jsonInstrumentSchema . properties [ col ] . items . required ) &&
656- keys [ i ]
657- ) {
658- // optional is false if the key is included in the required items
659- multiVals . push ( {
660- isOptional : ! ( jsonInstrumentSchema . properties [ col ] . items . required as string [ ] ) . includes ( keys [ i ] ! ) ,
661- success : true ,
662- typeName : jsonToZod ( ( val as Zod4Object ) . type )
663- } ) ;
664- i ++ ;
665- }
666- }
667-
668- data = {
669- isOptional : optional ,
670- multiKeys : keys ,
671- multiValues : multiVals ,
672- success : true ,
673- typeName : 'ZodObject'
674- } ;
675- } else if ( typeSafety . enum ) {
676- data = {
677- enumValues : typeSafety . enum as readonly string [ ] ,
678- isOptional : optional ,
679- success : true ,
680- typeName : 'ZodEnum'
681- } ;
682- } else if ( jsonToZod ( typeSafety . type ) ) {
683- data = {
684- isOptional : optional ,
685- success : true ,
686- typeName : jsonToZod ( typeSafety . type )
687- } ;
688- } else {
689- data = {
690- message : {
691- en : 'Failed to interpret JSON value from schema' ,
692- fr : "Échec de l'interprétation de la valeur JSON du schéma"
693- } ,
694- success : false
695- } ;
696- }
697-
698- if ( ! data . success ) {
699- throw new Error ( `${ data . message . en } / ${ data . message . fr } ` ) ;
700- }
701- jsonSampleData . push ( generateSampleData ( data ) ) ;
702- }
703-
704- const zod4TemplateData = unparse ( [ jsonCSVColumns , jsonSampleData ] ) ;
705-
706- return zod4TemplateData ;
707- }
708- throw new Error ( "Failed to interpret JSON schema / Échec de l'interprétation du schéma JSON" ) ;
709- }
710-
711- export function createUploadTemplateCSV ( instrument : AnyUnilingualFormInstrument ) {
712- try {
713- const instrumentSchema = instrument . validationSchema ;
714-
715- /**
716- * Steps for zod4 schemas
717- * convert schema to json schema
718- * Check properties for all questions
719- * for optional questions check if it exists in required, if not then make it optional
720- * Use the types provided by the schema to generate the sample data
721- * **/
722-
723- if ( isZodType ( instrumentSchema , { version : 4 } ) ) {
724- const jsonInstrumentSchema = z4 . toJSONSchema ( instrumentSchema as z4 . ZodSchema ) ;
725- const zod4TemplateData = zod4Helper ( jsonInstrumentSchema ) ;
726-
727- return {
728- content : zod4TemplateData ,
729- fileName : `${ instrument . internal . name } _${ instrument . internal . edition } _template.csv`
730- } ;
731- }
732-
733- if ( ! isZodObject ( instrumentSchema ) ) {
734- throw new Error (
735- 'Validation schema for this instrument is invalid / Le schéma de validation de cet instrument est invalide'
736- ) ;
737- }
738-
739- const instrumentSchemaDef : unknown = instrument . validationSchema . _def ;
740-
741- let shape : { [ key : string ] : z . ZodTypeAny } = { } ;
742-
743- if ( isZodTypeDef ( instrumentSchemaDef ) && isZodEffectsDef ( instrumentSchemaDef ) ) {
744- const innerSchemaDef : unknown = instrumentSchemaDef . schema . _def ;
745- if ( isZodTypeDef ( innerSchemaDef ) && isZodObjectDef ( innerSchemaDef ) ) {
746- shape = innerSchemaDef . shape ( ) as { [ key : string ] : z . ZodTypeAny } ;
747- }
748- } else {
749- shape = instrumentSchema . shape as { [ key : string ] : z . ZodTypeAny } ;
750- }
751-
752- const columnNames = Object . keys ( shape ) ;
753-
754- const csvColumns = INTERNAL_HEADERS . concat ( columnNames ) ;
755-
756- const sampleData = [ ...INTERNAL_HEADERS_SAMPLE_DATA ] ;
757- for ( const col of columnNames ) {
758- const typeNameResult = getZodTypeName ( shape [ col ] ! ) ;
759- if ( ! typeNameResult . success ) {
760- throw new Error ( `${ typeNameResult . message . en } / ${ typeNameResult . message . fr } ` ) ;
761- }
762- sampleData . push ( generateSampleData ( typeNameResult ) ) ;
763- }
764-
765- unparse ( [ csvColumns , sampleData ] ) ;
766-
767- return {
768- content : unparse ( [ csvColumns , sampleData ] ) ,
769- fileName : `${ instrument . internal . name } _${ instrument . internal . edition } _template.csv`
770- } ;
771- } catch ( e ) {
772- if ( e instanceof Error && e . message ) {
773- throw e ;
774- }
775-
776- throw new Error ( "Error generating Sample CSV template / Erreur lors de la génération du modèle CSV d'exemple" , {
777- cause : e
778- } ) ;
779- }
780- }
781615
782616export async function processInstrumentCSV (
783617 input : File ,
@@ -796,7 +630,7 @@ export async function processInstrumentCSV(
796630 }
797631 instrumentSchemaWithInternal = instrumentSchemaDef . schema . extend ( {
798632 date : z . coerce . date ( ) ,
799- subjectID : z . string ( ) . regex ( ... SUBJECT_ID_REGEX )
633+ subjectID : z . string ( ) . regex ( SUBJECT_ID_REGEX )
800634 } ) ;
801635 shape = ( instrumentSchemaWithInternal . _def as z . ZodObjectDef ) . shape ( ) as { [ key : string ] : z . ZodTypeAny } ;
802636 } else {
@@ -806,7 +640,7 @@ export async function processInstrumentCSV(
806640 } else {
807641 instrumentSchemaWithInternal = instrumentSchema . extend ( {
808642 date : z . coerce . date ( ) ,
809- subjectID : z . string ( ) . regex ( ... SUBJECT_ID_REGEX )
643+ subjectID : z . string ( ) . regex ( SUBJECT_ID_REGEX )
810644 } ) ;
811645 shape = instrumentSchemaWithInternal . shape as { [ key : string ] : z . ZodTypeAny } ;
812646 }
0 commit comments