add sort-keys linting (#34)

This commit is contained in:
Patrick Moody
2023-02-07 20:49:18 -08:00
committed by GitHub
parent fbc9142ae2
commit 1cdbec1f35
10 changed files with 198 additions and 91 deletions

View File

@@ -14,9 +14,10 @@
"ecmaVersion": "latest",
"sourceType": "module"
},
"plugins": ["@typescript-eslint"],
"plugins": ["@typescript-eslint", "sort-keys-fix"],
"rules": {
"@typescript-eslint/no-explicit-any": "off",
"@typescript-eslint/ban-ts-comment": "off"
"@typescript-eslint/ban-ts-comment": "off",
"sort-keys-fix/sort-keys-fix": "warn"
}
}

107
package-lock.json generated
View File

@@ -1,12 +1,12 @@
{
"name": "pocketbase-typegen",
"version": "1.1.0",
"version": "1.1.3",
"lockfileVersion": 2,
"requires": true,
"packages": {
"": {
"name": "pocketbase-typegen",
"version": "1.1.0",
"version": "1.1.3",
"license": "ISC",
"dependencies": {
"commander": "^9.4.1",
@@ -27,6 +27,7 @@
"esbuild-node-externals": "^1.5.0",
"eslint": "^8.27.0",
"eslint-config-prettier": "^8.5.0",
"eslint-plugin-sort-keys-fix": "^1.1.2",
"jest": "^29.1.2",
"prettier": "^2.7.1",
"ts-jest": "^29.0.3",
@@ -2786,6 +2787,56 @@
"eslint": ">=7.0.0"
}
},
"node_modules/eslint-plugin-sort-keys-fix": {
"version": "1.1.2",
"resolved": "https://registry.npmjs.org/eslint-plugin-sort-keys-fix/-/eslint-plugin-sort-keys-fix-1.1.2.tgz",
"integrity": "sha512-DNPHFGCA0/hZIsfODbeLZqaGY/+q3vgtshF85r+YWDNCQ2apd9PNs/zL6ttKm0nD1IFwvxyg3YOTI7FHl4unrw==",
"dev": true,
"dependencies": {
"espree": "^6.1.2",
"esutils": "^2.0.2",
"natural-compare": "^1.4.0",
"requireindex": "~1.2.0"
},
"engines": {
"node": ">=0.10.0"
}
},
"node_modules/eslint-plugin-sort-keys-fix/node_modules/acorn": {
"version": "7.4.1",
"resolved": "https://registry.npmjs.org/acorn/-/acorn-7.4.1.tgz",
"integrity": "sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A==",
"dev": true,
"bin": {
"acorn": "bin/acorn"
},
"engines": {
"node": ">=0.4.0"
}
},
"node_modules/eslint-plugin-sort-keys-fix/node_modules/eslint-visitor-keys": {
"version": "1.3.0",
"resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.3.0.tgz",
"integrity": "sha512-6J72N8UNa462wa/KFODt/PJ3IU60SDpC3QXC1Hjc1BXXpfL2C9R5+AU7jhe0F6GREqVMh4Juu+NY7xn+6dipUQ==",
"dev": true,
"engines": {
"node": ">=4"
}
},
"node_modules/eslint-plugin-sort-keys-fix/node_modules/espree": {
"version": "6.2.1",
"resolved": "https://registry.npmjs.org/espree/-/espree-6.2.1.tgz",
"integrity": "sha512-ysCxRQY3WaXJz9tdbWOwuWr5Y/XrPTGX9Kiz3yoUXwW0VZ4w30HTkQLaGx/+ttFjF8i+ACbArnB4ce68a9m5hw==",
"dev": true,
"dependencies": {
"acorn": "^7.1.1",
"acorn-jsx": "^5.2.0",
"eslint-visitor-keys": "^1.1.0"
},
"engines": {
"node": ">=6.0.0"
}
},
"node_modules/eslint-scope": {
"version": "5.1.1",
"resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz",
@@ -5242,6 +5293,15 @@
"node": ">=0.10.0"
}
},
"node_modules/requireindex": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/requireindex/-/requireindex-1.2.0.tgz",
"integrity": "sha512-L9jEkOi3ASd9PYit2cwRfyppc9NoABujTP8/5gFcbERmo5jUoAKovIC3fsF17pkTnGsrByysqX+Kxd2OTNI1ww==",
"dev": true,
"engines": {
"node": ">=0.10.5"
}
},
"node_modules/resolve": {
"version": "1.22.1",
"resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.1.tgz",
@@ -8135,6 +8195,43 @@
"dev": true,
"requires": {}
},
"eslint-plugin-sort-keys-fix": {
"version": "1.1.2",
"resolved": "https://registry.npmjs.org/eslint-plugin-sort-keys-fix/-/eslint-plugin-sort-keys-fix-1.1.2.tgz",
"integrity": "sha512-DNPHFGCA0/hZIsfODbeLZqaGY/+q3vgtshF85r+YWDNCQ2apd9PNs/zL6ttKm0nD1IFwvxyg3YOTI7FHl4unrw==",
"dev": true,
"requires": {
"espree": "^6.1.2",
"esutils": "^2.0.2",
"natural-compare": "^1.4.0",
"requireindex": "~1.2.0"
},
"dependencies": {
"acorn": {
"version": "7.4.1",
"resolved": "https://registry.npmjs.org/acorn/-/acorn-7.4.1.tgz",
"integrity": "sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A==",
"dev": true
},
"eslint-visitor-keys": {
"version": "1.3.0",
"resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.3.0.tgz",
"integrity": "sha512-6J72N8UNa462wa/KFODt/PJ3IU60SDpC3QXC1Hjc1BXXpfL2C9R5+AU7jhe0F6GREqVMh4Juu+NY7xn+6dipUQ==",
"dev": true
},
"espree": {
"version": "6.2.1",
"resolved": "https://registry.npmjs.org/espree/-/espree-6.2.1.tgz",
"integrity": "sha512-ysCxRQY3WaXJz9tdbWOwuWr5Y/XrPTGX9Kiz3yoUXwW0VZ4w30HTkQLaGx/+ttFjF8i+ACbArnB4ce68a9m5hw==",
"dev": true,
"requires": {
"acorn": "^7.1.1",
"acorn-jsx": "^5.2.0",
"eslint-visitor-keys": "^1.1.0"
}
}
}
},
"eslint-scope": {
"version": "5.1.1",
"resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz",
@@ -9884,6 +9981,12 @@
"integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==",
"dev": true
},
"requireindex": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/requireindex/-/requireindex-1.2.0.tgz",
"integrity": "sha512-L9jEkOi3ASd9PYit2cwRfyppc9NoABujTP8/5gFcbERmo5jUoAKovIC3fsF17pkTnGsrByysqX+Kxd2OTNI1ww==",
"dev": true
},
"resolve": {
"version": "1.22.1",
"resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.1.tgz",

View File

@@ -48,6 +48,7 @@
"esbuild-node-externals": "^1.5.0",
"eslint": "^8.27.0",
"eslint-config-prettier": "^8.5.0",
"eslint-plugin-sort-keys-fix": "^1.1.2",
"jest": "^29.1.2",
"prettier": "^2.7.1",
"ts-jest": "^29.0.3",

View File

@@ -25,12 +25,21 @@ import {
} from "./utils"
const pbSchemaTypescriptMap = {
text: "string",
number: "number",
bool: "boolean",
email: "string",
url: "string",
date: DATE_STRING_TYPE_NAME,
editor: "string",
email: "string",
file: (fieldSchema: FieldSchema) =>
fieldSchema.options.maxSelect && fieldSchema.options.maxSelect > 1
? "string[]"
: "string",
json: (fieldSchema: FieldSchema) =>
`null | ${fieldNameToGeneric(fieldSchema.name)}`,
number: "number",
relation: (fieldSchema: FieldSchema) =>
fieldSchema.options.maxSelect && fieldSchema.options.maxSelect === 1
? RECORD_ID_STRING_NAME
: `${RECORD_ID_STRING_NAME}[]`,
select: (fieldSchema: FieldSchema, collectionName: string) => {
// pocketbase v0.8+ values are required
const valueType = fieldSchema.options.values
@@ -40,22 +49,14 @@ const pbSchemaTypescriptMap = {
? `${valueType}[]`
: valueType
},
json: (fieldSchema: FieldSchema) =>
`null | ${fieldNameToGeneric(fieldSchema.name)}`,
file: (fieldSchema: FieldSchema) =>
fieldSchema.options.maxSelect && fieldSchema.options.maxSelect > 1
? "string[]"
: "string",
relation: (fieldSchema: FieldSchema) =>
fieldSchema.options.maxSelect && fieldSchema.options.maxSelect === 1
? RECORD_ID_STRING_NAME
: `${RECORD_ID_STRING_NAME}[]`,
text: "string",
url: "string",
// DEPRECATED: PocketBase v0.8 does not have a dedicated user relation
user: (fieldSchema: FieldSchema) =>
fieldSchema.options.maxSelect && fieldSchema.options.maxSelect > 1
? `${RECORD_ID_STRING_NAME}[]`
: RECORD_ID_STRING_NAME,
editor: "string"
}
export function generate(results: Array<CollectionRecord>) {

View File

@@ -9,8 +9,8 @@ export async function fromDatabase(
dbPath: string
): Promise<Array<CollectionRecord>> {
const db = await open({
filename: dbPath,
driver: sqlite3.Database,
filename: dbPath,
})
const result = await db.all("SELECT * FROM _collections")
return result.map((collection) => ({
@@ -35,9 +35,10 @@ export async function fromURL(
// Login
const { token } = await fetch(`${url}/api/admins/auth-with-password`, {
method: "post",
// @ts-ignore
body: formData,
body: formData,
method: "post",
}).then((res) => res.json())
// Get the collection

View File

@@ -5,8 +5,8 @@ import path from "path"
it("creates a type file from json schema", async () => {
const out = path.resolve(__dirname, "pocketbase-types-example.ts")
const result = await main({
out,
json: path.resolve(__dirname, "pb_schema.json"),
out,
})
const fileOutput = await fs.readFile(out, { encoding: "utf-8" })

View File

@@ -9,39 +9,39 @@ import { FieldSchema } from "../src/types"
const textField: FieldSchema = {
id: "1",
system: false,
unique: false,
options: {},
name: "field1",
options: {},
required: true,
system: false,
type: "text",
unique: false,
}
const jsonField1: FieldSchema = {
id: "2",
system: false,
unique: false,
options: {},
name: "data1",
options: {},
required: true,
system: false,
type: "json",
unique: false,
}
const jsonField2: FieldSchema = {
id: "3",
system: false,
unique: false,
options: {},
name: "data2",
options: {},
required: true,
system: false,
type: "json",
unique: false,
}
const expandField: FieldSchema = {
id: "4",
system: false,
unique: false,
options: {},
name: "post_relation_field",
options: {},
required: true,
system: false,
type: "relation",
unique: false,
}
describe("getGenericArgList", () => {

View File

@@ -11,38 +11,38 @@ import {
const defaultFieldSchema: FieldSchema = {
id: "abc",
system: false,
unique: false,
options: {},
name: "defaultName",
options: {},
required: true,
system: false,
type: "text",
unique: false,
}
describe("generate", () => {
it("generates correct output given db input", () => {
const collections: Array<CollectionRecord> = [
{
name: "books",
id: "123",
type: "base",
system: false,
listRule: null,
viewRule: null,
createRule: null,
updateRule: null,
deleteRule: null,
id: "123",
listRule: null,
name: "books",
schema: [
{
name: "title",
type: "text",
required: false,
id: "xyz",
system: false,
unique: false,
name: "title",
options: {},
required: false,
system: false,
type: "text",
unique: false,
},
],
system: false,
type: "base",
updateRule: null,
viewRule: null,
},
]
const result = generate(collections)
@@ -69,13 +69,13 @@ describe("createRecordType", () => {
const name = "books"
const schema: FieldSchema[] = [
{
system: false,
id: "hhnwjkke",
name: "title",
type: "text",
options: { max: null, min: null, pattern: "" },
required: false,
system: false,
type: "text",
unique: false,
options: { min: null, max: null, pattern: "" },
},
]
const result = createRecordType(name, schema)
@@ -86,13 +86,13 @@ describe("createRecordType", () => {
const name = "books"
const schema: FieldSchema[] = [
{
system: false,
id: "hhnwjkke",
name: "avatars",
type: "file",
required: false,
unique: false,
options: { maxSelect: 2 },
required: false,
system: false,
type: "file",
unique: false,
},
]
const result = createRecordType(name, schema)
@@ -103,26 +103,26 @@ describe("createRecordType", () => {
describe("createResponseType", () => {
it("creates type definition for a response", () => {
const row: CollectionRecord = {
type: "base",
id: "123",
system: false,
listRule: null,
viewRule: null,
createRule: null,
updateRule: null,
deleteRule: null,
id: "123",
listRule: null,
name: "books",
schema: [
{
system: false,
id: "hhnwjkke",
name: "title",
type: "text",
options: { max: null, min: null, pattern: "" },
required: false,
system: false,
type: "text",
unique: false,
options: { min: null, max: null, pattern: "" },
},
],
system: false,
type: "base",
updateRule: null,
viewRule: null,
}
const result = createResponseType(row)
@@ -133,13 +133,13 @@ describe("createResponseType", () => {
const name = "books"
const schema: FieldSchema[] = [
{
system: false,
id: "hhnwjkke",
name: "avatars",
type: "file",
required: false,
unique: false,
options: { maxSelect: 2 },
required: false,
system: false,
type: "file",
unique: false,
},
]
const result = createRecordType(name, schema)
@@ -242,10 +242,10 @@ describe("createTypeField", () => {
createTypeField("test_collection", {
...defaultFieldSchema,
name: "selectFieldWithOpts",
type: "select",
options: {
values: ["one", "two", "three"],
},
type: "select",
})
).toEqual(`\tselectFieldWithOpts: TestCollectionSelectFieldWithOptsOptions`)
})
@@ -255,10 +255,10 @@ describe("createTypeField", () => {
createTypeField("test_collection", {
...defaultFieldSchema,
name: "selectField",
type: "select",
options: {
maxSelect: 2,
},
type: "select",
})
).toEqual("\tselectField: string[]")
})
@@ -268,11 +268,11 @@ describe("createTypeField", () => {
createTypeField("test_collection", {
...defaultFieldSchema,
name: "selectFieldWithOpts",
type: "select",
options: {
values: ["one", "two", "three"],
maxSelect: 2,
values: ["one", "two", "three"],
},
type: "select",
})
).toEqual(
`\tselectFieldWithOpts: TestCollectionSelectFieldWithOptsOptions[]`
@@ -304,10 +304,10 @@ describe("createTypeField", () => {
createTypeField("test_collection", {
...defaultFieldSchema,
name: "fileField",
type: "file",
options: {
maxSelect: 3,
},
type: "file",
})
).toEqual("\tfileField: string[]")
})
@@ -327,10 +327,10 @@ describe("createTypeField", () => {
createTypeField("test_collection", {
...defaultFieldSchema,
name: "relationFieldMany",
type: "relation",
options: {
maxSelect: 3,
},
type: "relation",
})
).toEqual("\trelationFieldMany: RecordIdString[]")
})
@@ -340,10 +340,10 @@ describe("createTypeField", () => {
createTypeField("test_collection", {
...defaultFieldSchema,
name: "relationFieldMany",
type: "relation",
options: {
maxSelect: null,
},
type: "relation",
})
).toEqual("\trelationFieldMany: RecordIdString[]")
})
@@ -375,13 +375,13 @@ describe("createSelectOptions", () => {
const name = "choose"
const schema: FieldSchema[] = [
{
system: false,
id: "hhnwjkke",
name: "title",
type: "select",
required: false,
unique: false,
options: { values: ["one", "one", "two", "space space", "$@#*(&#%"] },
required: false,
system: false,
type: "select",
unique: false,
},
]
const result = createSelectOptions(name, schema)

View File

@@ -23,16 +23,16 @@ const thing = getOne(Collections.Everything, "a")
// Works when passing in JSON generic
const everythingRecordWithGeneric: EverythingRecord<{ a: "some string" }> = {
bool_field: true,
json_field: { a: "some string" },
number_field: 1,
bool_field: true,
}
// Works without passing in JSON generic
const everythingRecordWithoutGeneric: EverythingRecord = {
bool_field: true,
json_field: { a: "some string" },
number_field: 1,
bool_field: true,
}
// Test select option enums

View File

@@ -52,11 +52,11 @@ describe("getOptionValues", () => {
const fieldWithoutValues: FieldSchema = {
id: "1",
name: "myfield",
type: "text",
system: false,
required: false,
unique: false,
options: {},
required: false,
system: false,
type: "text",
unique: false,
}
expect(getOptionValues(fieldWithoutValues)).toEqual([])
})
@@ -65,13 +65,13 @@ describe("getOptionValues", () => {
const fieldWithValues: FieldSchema = {
id: "1",
name: "myfield",
type: "text",
system: false,
required: false,
unique: false,
options: {
values: ["one", "one", "one", "two"],
},
required: false,
system: false,
type: "text",
unique: false,
}
expect(getOptionValues(fieldWithValues)).toEqual(["one", "two"])
})