ts-json-schema-generator
ts-json-schema-generator copied to clipboard
Invalid index in type
Hello,
I'm trying to use your module to progamaticly generate JSON Schema from my defined types. Most of my custom types extends from packages types, such as Prisma. I don't have a lot of types, for here there are:
import { Prisma, Challenge } from "@prisma/client"
import { SessionRequest } from "supertokens-node/framework/fastify"
import { Certificate } from "tls"
export interface ChallengeWithStats extends Challenge {
currentValue: number
}
export interface ExoCertificate extends Certificate {
DC: string
}
interface RouteInterface {
Params?: unknown
Body?: unknown
}
export interface FastifyRequestSession<T extends RouteInterface> extends SessionRequest {
body: T["Body"]
params: T["Params"]
}
export interface UserWithRoles extends Prisma.UserGetPayload<{ include: { preferences: true } }>{
roles: string[]
}
export interface SessionJsonData {
sessionId: string
start_date: Date
end_date: Date
steps: number
distance: number
verticalDuration: number
walkDuration: number
totalDuration: number
}
export interface SessionStatistics {
total: {
steps: number
distance: number
verticalDuration: number
walkDuration: number
totalDuration: number
}
}
Note that all those types are located in ./src/types/**.ts, and all exported in ./src/types/index.ts.
Here is my script I'm trying to run to make my schema:
const fs = require("fs")
import("ts-json-schema-generator").then(async tsj => {
const config = {
path: "./src/types/index.ts",
tsconfig: "./tsconfig.json",
type: "*",
}
const outputPath = "./testSchema.json"
const schema = tsj.createGenerator(config).createSchema(config.type)
const schemaString = JSON.stringify(schema, null, 2)
fs.writeFile(outputPath, schemaString, err => {
if (err) throw err
})
})
This file is located in ./src/generateSchema.js and i'm running the script like node ./src/schemaGenerator.js
And the output throw me this error:
file:///src/api/node_modules/ts-json-schema-generator/dist/src/NodeParser/IndexedAccessTypeNodeParser.js:60
throw new LogicError(`Invalid index "${type.getValue()}" in type "${objectType.getId()}"`);
^
LogicError: Invalid index "exoskeleton" in type "indexed-type-1777104669-59854-59949-1777104669-59841-59950-1777104669-59839-60229-1777104669-59543-60230-1777104669-0-108983<structure-1777104669-16731-16733-1777104669-16717-16746-1777104669-16680-16747-1777104669-0-108983,structure-1777104669-16734-16737-1777104669-16717-16746-1777104669-16680-16747-1777104669-0-108983,structure-1777104669-16738-16741-1777104669-16717-16746-1777104669-16680-16747-1777104669-0-108983,structure-1777104669-16742-16745-1777104669-16717-16746-1777104669-16680-16747-1777104669-0-108983>"
at file:///src/api/node_modules/ts-json-schema-generator/dist/src/NodeParser/IndexedAccessTypeNodeParser.js:60:27
at Array.map (<anonymous>)
at IndexedAccessTypeNodeParser.createType (file:///src/api/node_modules/ts-json-schema-generator/dist/src/NodeParser/IndexedAccessTypeNodeParser.js:47:42)
at ChainNodeParser.createType (file:///src/api/node_modules/ts-json-schema-generator/dist/src/ChainNodeParser.js:27:54)
at TypeReferenceNodeParser.createSubContext (file:///src/api/node_modules/ts-json-schema-generator/dist/src/NodeParser/TypeReferenceNodeParser.js:60:62)
at TypeReferenceNodeParser.createType (file:///src/api/node_modules/ts-json-schema-generator/dist/src/NodeParser/TypeReferenceNodeParser.js:30:70)
at ChainNodeParser.createType (file:///src/api/node_modules/ts-json-schema-generator/dist/src/ChainNodeParser.js:27:54)
at AnnotatedNodeParser.createType (file:///src/api/node_modules/ts-json-schema-generator/dist/src/NodeParser/AnnotatedNodeParser.js:25:47)
at file:///src/api/node_modules/ts-json-schema-generator/dist/src/NodeParser/TypeLiteralNodeParser.js:35:117
at Array.map (<anonymous>) {
msg: 'Invalid index "exoskeleton" in type "indexed-type-1777104669-59854-59949-1777104669-59841-59950-1777104669-59839-60229-1777104669-59543-60230-1777104669-0-108983<structure-1777104669-16731-16733-1777104669-16717-16746-1777104669-16680-16747-1777104669-0-108983,structure-1777104669-16734-16737-1777104669-16717-16746-1777104669-16680-16747-1777104669-0-108983,structure-1777104669-16738-16741-1777104669-16717-16746-1777104669-16680-16747-1777104669-0-108983,structure-1777104669-16742-16745-1777104669-16717-16746-1777104669-16680-16747-1777104669-0-108983>"'
}
Node.js v20.13.1
And to be honest, I have no clue about how to read and correct this at this point!
Do you guys have any clue on how to fix this ?
Thanks
Thanks for the report. Can you provide a minimal reproducible example that demonstrates the issue?
Yeah sorry, here is a little project I made up to reproduce this:
package.json
{
"name": "test",
"version": "1.0.0",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"author": "",
"license": "ISC",
"description": "",
"devDependencies": {
"@types/node": "^20.12.12",
"prisma": "^5.14.0",
"ts-json-schema-generator": "^2.2.0",
"ts-node": "^10.9.2",
"typescript": "^5.4.5"
},
"dependencies": {
"@prisma/client": "^5.14.0"
}
}
prisma/schema.prisma
generator client {
provider = "prisma-client-js"
}
datasource db {
provider = "sqlite"
url = env("DATABASE_URL")
}
model User {
id Int @id @default(autoincrement())
email String @unique
name String?
posts Post[]
}
model Post {
id Int @id @default(autoincrement())
title String
content String?
published Boolean @default(false)
author User @relation(fields: [authorId], references: [id])
authorId Int
}
types/index.ts
import { User } from '@prisma/client';
export interface UserTest extends User {
newField: string;
}
schemaGenerator.js
const fs = require("fs")
import("ts-json-schema-generator").then(async tsj => {
const config = {
path: "./types/user.ts",
tsconfig: "./tsconfig.json",
type: "*",
schemaId: "WdcTypes",
}
const outputPath = "./schemas"
const schema = tsj.createGenerator(config).createSchema(config.type)
const schemaString = JSON.stringify(schema, null, 2)
fs.writeFile(outputPath, schemaString, err => {
if (err) throw err
})
})
This example + my personnal tests seems to show that any import from the @prisma/client seems to make the generator crash.
That's not yet minimal if you can remove anything and the error state does not change. Oncer you identify the offending change, you can see how it's causing the issues you see.
Okay,
I edited my schema:
generator client {
provider = "prisma-client-js"
}
datasource db {
provider = "sqlite"
url = env("DATABASE_URL")
}
model User {
name String @unique
}
That make all my files as minimal as possible (not that the error also trigger with the CLI, without using my .js file). The error occur when I extends any Prisma type. The moment I remove Prisma imports, everything works, if I add a Prisma type, it triggers this error
This might be fixed by #1924
https://github.com/vega/ts-json-schema-generator/pull/343 could also help here
@navalex can you try with v2.3.0-next.2?
After https://github.com/vega/ts-json-schema-generator/pull/1963 added diagnostics, the error thrown will have more info about it.
Probably duplicate of #542
@navalex can you try with v2.3.0-next.2?
After #1963 added diagnostics, the error thrown will have more info about it.
Okay so, after testing, it does fix the issue on my basic exemple, but does not on my main project. I tried both 2.2.0-next.0 and 2.3.0-next.2, the last one give an enormous output that seems to dump both a ts-json-schema-generator file and probably my file that throw the error (the Prisma generated client, so a big one).
I don't know if I'll have enough time to do more tests this week, so here is at least the output error, may give you more infos: Here is the full log: https://logpaste.com/OQTlH3wj
I'll also let my package.json and prisma.schema
package.json:
{
"name": "eveapp-api-core",
"version": "1.0.1",
"description": "",
"scripts": {
"start:dev": "nodemon --exec 'ts-node -r tsconfig-paths/register' src/server.ts",
"start:prod": "node -r tsconfig-paths/register dist/server.js",
"build": "tsc && tsc-alias",
"test:watch": "jest --watchAll --collectCoverage",
"test:ci": "jest --collectCoverage",
"test:manual": "jest",
"format:check": "prettier --check \"src/**/*.ts\"",
"format:write": "prettier --write \"src/**/*.ts\"",
"lint:check": "eslint \"src/**/*.ts\"",
"lint:fix": "eslint --fix \"src/**/*.ts\"",
"schema:generate": "node bin/schemaGenerator.js"
},
"nodemonConfig": {
"watch": [
"src"
],
"ext": "ts",
"exec": "ts-node -r tsconfig-paths/register"
},
"author": "",
"license": "ISC",
"dependencies": {
"@fastify/cors": "^9.0.1",
"@fastify/formbody": "^7.4.0",
"@fastify/multipart": "^8.2.0",
"@fastify/sensible": "^5.6.0",
"@fastify/swagger": "^8.14.0",
"@fastify/swagger-ui": "^3.0.0",
"@prisma/client": "^5.14.0",
"fastify": "^4.27.0",
"pino-loki": "^2.3.0",
"pino-pretty": "^11.0.0",
"prom-client": "^15.1.2",
"socket.io": "^4.7.5",
"supertokens-node": "^17.1.2"
},
"devDependencies": {
"@types/jest": "^29.5.12",
"@types/node": "^20.12.12",
"eslint": "^9.3.0",
"eslint-config-prettier": "^9.1.0",
"jest": "^29.7.0",
"jest-mock-extended": "^3.0.7",
"nodemon": "^3.1.0",
"prettier": "^3.2.5",
"prisma": "^5.14.0",
"prisma-json-schema-generator": "5.1.1",
"prisma-json-types-generator": "^3.0.4",
"ts-jest": "^29.1.3",
"ts-json-schema-generator": "^2.3.0-next.2",
"ts-node": "^10.9.2",
"tsc-alias": "^1.8.10",
"tsconfig-paths": "^4.2.0",
"typescript": "^5.4.5"
}
}
prisma.schema:
// ############################################
// #
// # DATABASE DEFINITION
// #
// ############################################
datasource db {
provider = "postgresql"
url = env("API_POSTGRES_URL")
}
generator client {
provider = "prisma-client-js"
previewFeatures = ["fullTextSearch"]
}
generator jsonTypes {
provider = "prisma-json-types-generator"
}
generator jsonSchema {
provider = "prisma-json-schema-generator"
schemaId = "PrismaSchema"
forceAnyOf = true
}
// ############################################
// #
// # MODELS
// #
// ############################################
model User {
id String @id @default(uuid())
auth_id String @unique
firstname String
lastname String
data Json
activationToken String? @default(uuid())
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
following User[] @relation("Follow")
followers User[] @relation("Follow")
exoskeletons ExoskeletonAttribution[]
challenges Challenge[]
authoredChallenges Challenge[] @relation(name: "challengeAuthor")
surveys Survey[]
preferences Preferences?
}
model Preferences {
id String @id @default(uuid())
userId String @unique
user User @relation(fields: [userId], references: [id])
weekStart WeekStartDay @default(MONDAY)
darkMode Boolean @default(false)
unitType UnitType @default(METRIC)
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
}
model Exoskeleton {
serial String @id
version String?
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
attributions ExoskeletonAttribution[]
}
model ExoskeletonAttribution {
id String @id @default(uuid())
createdAt DateTime @default(now())
revokedAt DateTime?
exoskeletonId String
userId String
exoskeleton Exoskeleton @relation(fields: [exoskeletonId], references: [serial])
user User @relation(fields: [userId], references: [id])
sessions Session[]
}
model Session {
id String @id @default(uuid())
/// [SessionData]
data Json
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
attributionId String
attribution ExoskeletonAttribution @relation(fields: [attributionId], references: [id])
}
model Challenge {
id String @default(uuid())
targetValue Float
metric ChallengeMetric
frequency ChallengeFrequency
repeate Boolean @default(false)
weekRepetition Int?
createdAt DateTime @default(now())
archivedAt DateTime?
userId String
authorId String
user User @relation(fields: [userId], references: [id])
author User @relation(name: "challengeAuthor", fields: [authorId], references: [id])
@@id(name: "challengeId", [id, createdAt])
}
model ChallengeTemplate {
id String @id @default(uuid())
description String?
targetValue Float
metric ChallengeMetric
frequency ChallengeFrequency
}
model Survey {
id String @id @default(uuid())
type SurveyType
data Json
createdAt DateTime @default(now())
userId String
user User @relation(fields: [userId], references: [id])
}
// ############################################
// #
// # ENUMS
// #
// ############################################
enum ChallengeMetric {
STEP_COUNT
DISTANCE
VERTICAL_DURATION
WALK_DURATION
}
enum ChallengeFrequency {
DAILY
WEEKLY
}
enum SurveyType {
DAILY_MOOD
}
enum WeekStartDay {
MONDAY
SUNDAY
}
enum UnitType {
METRIC
IMPERIAL
}
Hey @navalex what about our latest release?
@arthurfiorette hello, thank you for your effort.
I create reproducible repository: https://github.com/imjuni/reproducible-prisma
sadly, ts-json-schema-generator cannot generate schema from mapped access type using prisma generated, like: https://github.com/imjuni/reproducible-prisma/blob/e2590cf2dff10f0d1eb7ad887a82656be6489faf/src/dto/ITagDto.ts#L6
I was tested 2.3.0-next.5 and 2.4.0-next.1.
Is there any progress on this issue? I tested it with the latest released version 2.4.0, but the same error still occurs.