Skip to content

Commit

Permalink
feat: parse string array type prop of query
Browse files Browse the repository at this point in the history
  • Loading branch information
solufa committed Nov 14, 2024
1 parent 5b8bd49 commit 44864eb
Show file tree
Hide file tree
Showing 7 changed files with 90 additions and 11 deletions.
31 changes: 27 additions & 4 deletions servers/all/$server.ts
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,26 @@ export type ServerMethodHandler<T extends AspidaMethodParams, U extends Record<
handler: ServerHandler<T, U> | ServerHandlerPromise<T, U>;
};

const parseStringArrayTypeQueryParams = (stringArrayTypeParams: [string, boolean][]): preValidationHookHandler => (req, reply, done) => {
const query: any = req.query;

for (const [key, isOptional] of stringArrayTypeParams) {
const param = query[`${key}[]`] ?? query[key];

if (!isOptional && param === undefined) {
query[key] = [];
} else if (!isOptional || param !== undefined) {
const vals = (Array.isArray(param) ? param : [param]);

query[key] = vals;
}

delete query[`${key}[]`];
}

done();
};

const parseNumberTypeQueryParams = (numberTypeParams: [string, boolean, boolean][]): preValidationHookHandler => (req, reply, done) => {
const query: any = req.query;

Expand All @@ -121,7 +141,7 @@ const parseNumberTypeQueryParams = (numberTypeParams: [string, boolean, boolean]
return;
}

query[key] = vals as any;
query[key] = vals;
}

delete query[`${key}[]`];
Expand All @@ -133,7 +153,7 @@ const parseNumberTypeQueryParams = (numberTypeParams: [string, boolean, boolean]
return;
}

query[key] = val as any;
query[key] = val;
}
}

Expand All @@ -157,7 +177,7 @@ const parseBooleanTypeQueryParams = (booleanTypeParams: [string, boolean, boolea
return;
}

query[key] = vals as any;
query[key] = vals;
}

delete query[`${key}[]`];
Expand All @@ -169,7 +189,7 @@ const parseBooleanTypeQueryParams = (booleanTypeParams: [string, boolean, boolea
return;
}

query[key] = val as any;
query[key] = val;
}
}

Expand Down Expand Up @@ -334,6 +354,7 @@ export default (fastify: FastifyInstance, options: FrourioOptions = {}) => {
onRequest: hooks_gx3glp.onRequest,
preParsing: hooks_gx3glp.preParsing,
preValidation: [
callParserIfExistsQuery(parseStringArrayTypeQueryParams([['strArray', false], ['optionalStrArray', true]])),
callParserIfExistsQuery(parseNumberTypeQueryParams([['requiredNum', false, false], ['optionalNum', true, false], ['optionalNumArr', true, true], ['emptyNum', true, false], ['requiredNumArr', false, true]])),
callParserIfExistsQuery(parseBooleanTypeQueryParams([['bool', false, false], ['optionalBool', true, false], ['boolArray', false, true], ['optionalBoolArray', true, true]])),
],
Expand All @@ -349,6 +370,7 @@ export default (fastify: FastifyInstance, options: FrourioOptions = {}) => {
onRequest: hooks_gx3glp.onRequest,
preParsing: hooks_gx3glp.preParsing,
preValidation: [
parseStringArrayTypeQueryParams([['strArray', false], ['optionalStrArray', true]]),
parseNumberTypeQueryParams([['requiredNum', false, false], ['optionalNum', true, false], ['optionalNumArr', true, true], ['emptyNum', true, false], ['requiredNumArr', false, true]]),
parseBooleanTypeQueryParams([['bool', false, false], ['optionalBool', true, false], ['boolArray', false, true], ['optionalBoolArray', true, true]]),
formatMultipartData([['optionalNumArr', true], ['requiredNumArr', false], ['boolArray', false], ['optionalBoolArray', true]], [['requiredNum', false, false], ['optionalNum', true, false], ['optionalNumArr', true, true], ['emptyNum', true, false], ['requiredNumArr', false, true]], [['bool', false, false], ['optionalBool', true, false], ['boolArray', false, true], ['optionalBoolArray', true, true]]),
Expand All @@ -368,6 +390,7 @@ export default (fastify: FastifyInstance, options: FrourioOptions = {}) => {
onRequest: hooks_gx3glp.onRequest,
preParsing: hooks_gx3glp.preParsing,
preValidation: [
parseStringArrayTypeQueryParams([['strArray', false], ['optionalStrArray', true]]),
parseNumberTypeQueryParams([['requiredNum', false, false], ['optionalNum', true, false], ['optionalNumArr', true, true], ['emptyNum', true, false], ['requiredNumArr', false, true]]),
parseBooleanTypeQueryParams([['bool', false, false], ['optionalBool', true, false], ['boolArray', false, true], ['optionalBoolArray', true, true]]),
...controller_14i7wcv.put.hooks.preValidation,
Expand Down
2 changes: 2 additions & 0 deletions servers/all/api/controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,8 @@ export default defineController(
emptyNum: z.number().optional(),
requiredNumArr: z.array(z.number()),
id: z.string(),
strArray: z.array(z.string()),
optionalStrArray: z.array(z.string()).optional(),
disable: z.string(),
bool: z.boolean(),
optionalBool: z.boolean().optional(),
Expand Down
2 changes: 2 additions & 0 deletions servers/all/api/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,8 @@ export type Methods = DefineMethods<{
emptyNum?: number | undefined;
requiredNumArr: number[];
id: string;
strArray: string[];
optionalStrArray?: string[] | undefined;
disable: string;
bool: boolean;
optionalBool?: boolean | undefined;
Expand Down
4 changes: 4 additions & 0 deletions servers/all/validators.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ export type Query = {
emptyNum?: number | undefined;
requiredNumArr: number[];
id: string;
strArray: string[];
optionalStrArray?: string[] | undefined;
disable: string;
bool: boolean;
optionalBool?: boolean | undefined;
Expand Down Expand Up @@ -55,6 +57,8 @@ export const queryValidator: z.ZodType<Query> = z.object({
emptyNum: z.number().optional(),
requiredNumArr: z.array(z.number()),
id: z.string().regex(/^\d+$/),
strArray: z.array(z.string()),
optionalStrArray: z.array(z.string()).optional(),
disable: z.enum(['true', 'false']),
bool: z.boolean(),
optionalBool: z.boolean().optional(),
Expand Down
39 changes: 32 additions & 7 deletions src/buildServerFile.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ const ${isAsync ? 'asyncM' : 'm'}ethodToHandler = (

export default (input: string, project?: string) => {
const { imports, consts, controllers } = createControllersText(`${input}/api`, project ?? input);
const hasStringArrayTypeQuery = controllers.includes('parseStringArrayTypeQueryParams(');
const hasNumberTypeQuery = controllers.includes('parseNumberTypeQueryParams(');
const hasBooleanTypeQuery = controllers.includes('parseBooleanTypeQueryParams(');
const hasOptionalQuery = controllers.includes(' callParserIfExistsQuery(');
Expand Down Expand Up @@ -132,8 +133,32 @@ export type ServerMethodHandler<T extends AspidaMethodParams, U extends Record<
handler: ServerHandler<T, U> | ServerHandlerPromise<T, U>;
};
${
hasNumberTypeQuery
hasStringArrayTypeQuery
? `
const parseStringArrayTypeQueryParams = (stringArrayTypeParams: [string, boolean][]): preValidationHookHandler => (req, reply, done) => {
const query: any = req.query;
for (const [key, isOptional] of stringArrayTypeParams) {
const param = query[\`\${key}[]\`] ?? query[key];
if (!isOptional && param === undefined) {
query[key] = [];
} else if (!isOptional || param !== undefined) {
const vals = (Array.isArray(param) ? param : [param]);
query[key] = vals;
}
delete query[\`\${key}[]\`];
}
done();
};
`
: ''
}${
hasNumberTypeQuery
? `
const parseNumberTypeQueryParams = (numberTypeParams: [string, boolean, boolean][]): preValidationHookHandler => (req, reply, done) => {
const query: any = req.query;
Expand All @@ -151,7 +176,7 @@ const parseNumberTypeQueryParams = (numberTypeParams: [string, boolean, boolean]
return;
}
query[key] = vals as any;
query[key] = vals;
}
delete query[\`\${key}[]\`];
Expand All @@ -163,15 +188,15 @@ const parseNumberTypeQueryParams = (numberTypeParams: [string, boolean, boolean]
return;
}
query[key] = val as any;
query[key] = val;
}
}
done();
};
`
: ''
}${
: ''
}${
hasBooleanTypeQuery
? `
const parseBooleanTypeQueryParams = (booleanTypeParams: [string, boolean, boolean][]): preValidationHookHandler => (req, reply, done) => {
Expand All @@ -191,7 +216,7 @@ const parseBooleanTypeQueryParams = (booleanTypeParams: [string, boolean, boolea
return;
}
query[key] = vals as any;
query[key] = vals;
}
delete query[\`\${key}[]\`];
Expand All @@ -203,7 +228,7 @@ const parseBooleanTypeQueryParams = (booleanTypeParams: [string, boolean, boolea
return;
}
query[key] = val as any;
query[key] = val;
}
}
Expand Down
15 changes: 15 additions & 0 deletions src/createControllersText.ts
Original file line number Diff line number Diff line change
Expand Up @@ -458,6 +458,12 @@ export default (appDir: string, project: string) => {
? checker.getTypeOfSymbolAtLocation(m, m.valueDeclaration).getProperties()
: [];
const query = props.find(p => p.name === 'query');
const stringArrayTypeQueryParams =
query &&
getSomeTypeParams('string', query)
?.filter(params => params !== null)
.filter(params => params.endsWith(', true]'))
.map(params => params.replace(', true]', ']'));
const numberTypeQueryParams = query && getSomeTypeParams('number', query);
const booleanTypeQueryParams = query && getSomeTypeParams('boolean', query);
const reqFormat = props.find(p => p.name === 'reqFormat');
Expand All @@ -476,6 +482,15 @@ export default (appDir: string, project: string) => {
.map(key => {
if (key === 'preValidation') {
const texts = [
stringArrayTypeQueryParams?.length
? query?.declarations?.some(
d => d.getChildAt(1).kind === ts.SyntaxKind.QuestionToken,
)
? `callParserIfExistsQuery(parseStringArrayTypeQueryParams([${stringArrayTypeQueryParams.join(
', ',
)}]))`
: `parseStringArrayTypeQueryParams([${stringArrayTypeQueryParams.join(', ')}])`
: '',
numberTypeQueryParams?.length
? query?.declarations?.some(
d => d.getChildAt(1).kind === ts.SyntaxKind.QuestionToken,
Expand Down
8 changes: 8 additions & 0 deletions tests/index.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ test('GET: 200', () =>
requiredNum: 1,
requiredNumArr: [1, 2],
id: '1',
strArray: [],
disable: 'false',
bool: true,
boolArray: [false, true],
Expand All @@ -50,6 +51,7 @@ test('GET: 200', () =>
emptyNum: 0,
requiredNumArr: [],
id: '1',
strArray: ['aa'],
disable: 'false',
bool: false,
optionalBool: true,
Expand Down Expand Up @@ -201,6 +203,7 @@ test('PUT: zod validations', async () => {
requiredNum: 0,
requiredNumArr: [],
id: '1',
strArray: [],
disable: 'true',
bool: false,
boolArray: [],
Expand All @@ -214,6 +217,7 @@ test('PUT: zod validations', async () => {
requiredNum: 0,
requiredNumArr: [],
id: '1',
strArray: [],
disable: 'true',
bool: 1 as any,
boolArray: [],
Expand All @@ -229,6 +233,8 @@ test('PUT: zod validations', async () => {
requiredNum: 0,
requiredNumArr: [],
id: '1',
strArray: ['aa', 'bb'],
optionalStrArray: ['cc'],
disable: 'true',
bool: false,
boolArray: [],
Expand Down Expand Up @@ -366,6 +372,8 @@ test('controller dependency injection', async () => {
requiredNum: 1,
requiredNumArr: [0],
disable: 'true',
strArray: ['aa'],
optionalStrArray: [],
bool: false,
boolArray: [],
},
Expand Down

0 comments on commit 44864eb

Please sign in to comment.