glideapps / quicktype

Generate types and converters from JSON, Schema, and GraphQL

Home Page:https://app.quicktype.io

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Typescript zod (and effect) language uses block scoped variables before they've been declared

kriswest opened this issue · comments

While attempting to generate zod schemas from a fairly large set of JSON Schemas we've noted multiple places where a block-scoped variable representing one of the schemas is used before its been declared, meaning the source file generated is unusable

export const RaiseIntentResultBridgeResponsePayloadSchema = z.object({
    "intentResult": IntentResultSchema,
});

...

export const IntentResultSchema = z.object({
    "context": z.union([ContextElementSchema, z.null()]).optional(),
    "channel": z.union([ChannelSchema, z.null()]).optional(),
});

The same happens in the Typescript generator, but it doesn't matter there as the interfaces aren't variables

 * The message payload typically contains return values for FDC3 API functions.
 */
export interface RaiseIntentResultAgentResponsePayload {
  intentResult: IntentResult;
}

...

export interface IntentResult {
  context?: ContextElement;
  channel?: Channel;
}

Presumably, this occurs due to a logical error in this code:

mapKey.forEach((_, index) => {
// assume first
let ordinal = 0;
// pull out all names
const source = mapValue[index];
const names = source.filter(value => value as Name);
// must be behind all these names
for (let i = 0; i < names.length; i++) {
const depName = names[i];
// find this name's ordinal, if it has already been added
for (let j = 0; j < order.length; j++) {
const depIndex = order[j];
if (mapKey[depIndex] === depName) {
// this is the index of the dependency, so make sure we come after it
ordinal = Math.max(ordinal, depIndex + 1);
}
}
}
// insert index
order.splice(ordinal, 0, index);
});
// now emit ordered source
order.forEach(i => this.emitGatheredSource(mapValue[i]));

I assume the issue also affects the TypeScript effect schema language as it uses the same code.

@ryoid @Southclaws @dvdsgl

I instrumented the above code and determined that it outputs in the same order as the input as the comparison mapKey[depIndex] === depName is never true.