Add support for geoPoint field (#128)

* add geoPoint field

* refactor dockerfile

* update snapshots

* fix integration tests

* fix output directory
This commit is contained in:
Patrick Moody
2025-04-28 09:07:26 +10:00
committed by GitHub
parent c14a19545b
commit 6a77cd0b73
17 changed files with 5247 additions and 6848 deletions

View File

@@ -16,17 +16,13 @@ jobs:
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Setup
run: npm ci
run: npm run build
- name: Run in docker
run: |
docker build . -t pocketbase-typegen:latest
docker run --name integration_test pocketbase-typegen:latest
mkdir -p output
docker cp integration_test:/app/output output
docker cp integration_test:/app/test/integration/output output
- name: Archive generated type results
uses: actions/upload-artifact@v4

View File

@@ -1,9 +1,8 @@
# Dockerfile to run e2e integration tests against a test PocketBase server
FROM node:16-alpine3.16
ARG POCKETBASE_VERSION=0.26.6
ARG POCKETBASE_VERSION=0.27.1
WORKDIR /app/output/
WORKDIR /app/
# Install the dependencies
@@ -14,20 +13,16 @@ RUN apk add --no-cache \
zip \
zlib-dev
# Build project
COPY . .
RUN npm ci
RUN npm run build
# Download Pocketbase and install it
ADD https://github.com/pocketbase/pocketbase/releases/download/v${POCKETBASE_VERSION}/pocketbase_${POCKETBASE_VERSION}_linux_amd64.zip /tmp/pocketbase.zip
RUN unzip /tmp/pocketbase.zip -d /app/
RUN unzip /tmp/pocketbase.zip -d /app/test/integration
# Install dependencies for the pocketbase-typegen package
COPY package.json package-lock.json ./
RUN npm ci
# Copy test files
COPY test/integration ./
COPY test/pocketbase-types-example.ts ./
COPY dist/index.js ./dist/index.js
RUN chmod +x ./pocketbase ./test.sh ./serve.sh
RUN chmod +x ./test/integration/pocketbase ./test/integration/test.sh ./test/integration/serve.sh
EXPOSE 8090
CMD [ "./test.sh" ]
CMD [ "./test/integration/test.sh" ]

View File

@@ -30,7 +30,7 @@
"prettier:fix": "npm run prettier -- --write",
"format": "npm run prettier:fix && npm run lint:fix",
"pocketbase:test": "docker build . -t pocketbase-typegen:latest && docker run --rm --name integration_test -p 8090:8090 pocketbase-typegen:latest",
"pocketbase:serve": "docker build . -t pocketbase-typegen:latest && docker run --rm --name integration_test -p 8090:8090 pocketbase-typegen:latest ./serve.sh"
"pocketbase:serve": "docker build . -t pocketbase-typegen:latest && docker run --rm --name pocketbase -p 8090:8090 pocketbase-typegen:latest ./test/integration/serve.sh"
},
"author": "@patmood",
"license": "ISC",

View File

@@ -11,6 +11,7 @@ export const EXPAND_GENERIC_NAME = "expand"
export const DATE_STRING_TYPE_NAME = `IsoDateString`
export const RECORD_ID_STRING_NAME = `RecordIdString`
export const HTML_STRING_NAME = `HTMLString`
export const GEOPOINT_TYPE_NAME = `GeoPoint`
export const ALIAS_TYPE_DEFINITIONS = `// Alias types for improved usability
export type ${DATE_STRING_TYPE_NAME} = string
export type ${RECORD_ID_STRING_NAME} = string
@@ -36,3 +37,8 @@ export const EXPAND_TYPE_DEFINITION = `type ExpandType<T> = unknown extends T
\t\t? { expand?: unknown }
\t\t: { expand: T }
\t: { expand: T }`
export const GEOPOINT_TYPE_DEFINITION = `export type ${GEOPOINT_TYPE_NAME} = {
\tlon: number
\tlat: number
}`

View File

@@ -1,5 +1,6 @@
import {
DATE_STRING_TYPE_NAME,
GEOPOINT_TYPE_NAME,
HTML_STRING_NAME,
RECORD_ID_STRING_NAME,
} from "./constants"
@@ -18,6 +19,7 @@ export const pbSchemaTypescriptMap = {
autodate: DATE_STRING_TYPE_NAME,
editor: HTML_STRING_NAME,
email: "string",
geoPoint: GEOPOINT_TYPE_NAME,
text: "string",
url: "string",
password: "string",

View File

@@ -10,6 +10,7 @@ import {
RESPONSE_TYPE_COMMENT,
IMPORTS,
EXPAND_TYPE_DEFINITION,
GEOPOINT_TYPE_DEFINITION,
} from "./constants"
import { CollectionRecord, FieldSchema } from "./types"
import {
@@ -23,7 +24,7 @@ import {
getGenericArgStringForRecord,
getGenericArgStringWithDefault,
} from "./generics"
import { getSystemFields, toPascalCase } from "./utils"
import { containsGeoPoint, getSystemFields, toPascalCase } from "./utils"
type GenerateOptions = {
sdk: boolean
@@ -47,12 +48,14 @@ export function generate(
}
})
const sortedCollectionNames = collectionNames
const includeGeoPoint = containsGeoPoint(results)
const fileParts = [
EXPORT_COMMENT,
options.sdk && IMPORTS,
createCollectionEnum(sortedCollectionNames),
ALIAS_TYPE_DEFINITIONS,
includeGeoPoint && GEOPOINT_TYPE_DEFINITION,
EXPAND_TYPE_DEFINITION,
BASE_SYSTEM_FIELDS_DEFINITION,
AUTH_SYSTEM_FIELDS_DEFINITION,

View File

@@ -28,6 +28,7 @@ export type FieldSchema = {
| "relation"
| "user"
| "editor"
| "geoPoint"
system: boolean
required: boolean
unique: boolean

View File

@@ -44,3 +44,9 @@ export function getOptionValues(field: FieldSchema) {
if (!values) return []
return values.filter((val, i) => values.indexOf(val) === i)
}
export function containsGeoPoint(collections: CollectionRecord[]) {
return collections.some((collection) =>
collection.fields.some((field) => field.type === "geoPoint")
)
}

View File

@@ -27,6 +27,11 @@ export type IsoDateString = string
export type RecordIdString = string
export type HTMLString = string
export type GeoPoint = {
lon: number
lat: number
}
type ExpandType<T> = unknown extends T
? T extends unknown
? { expand?: unknown }
@@ -133,6 +138,7 @@ export type EverythingRecord<Tanother_json_field = unknown, Tjson_field = unknow
date_field?: IsoDateString
email_field?: string
file_field?: string
geopoint_field?: GeoPoint
id: string
json_field?: null | Tjson_field
number_field?: number

View File

@@ -2,26 +2,26 @@ import assert from "node:assert"
import fs from "fs/promises"
// Known good types from repo
const controlTypes = await fs.readFile("pocketbase-types-example.ts", {
const controlTypes = await fs.readFile("../pocketbase-types-example.ts", {
encoding: "utf8",
})
async function testCreateFromUrl() {
const typesFromUrl = await fs.readFile("output/pocketbase-types-url.ts", {
const typesFromUrl = await fs.readFile("./output/pocketbase-types-url.ts", {
encoding: "utf8",
})
assert.equal(typesFromUrl, controlTypes)
}
async function testCreateFromEnv() {
const typesFromEnv = await fs.readFile("output/pocketbase-types-env.ts", {
const typesFromEnv = await fs.readFile("./output/pocketbase-types-env.ts", {
encoding: "utf8",
})
assert.equal(typesFromEnv, controlTypes)
}
async function testCreateFromDb() {
const typesFromDb = await fs.readFile("output/pocketbase-types-db.ts", {
const typesFromDb = await fs.readFile("./output/pocketbase-types-db.ts", {
encoding: "utf8",
})
assert.equal(typesFromDb, controlTypes)

Binary file not shown.

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,24 @@
/// <reference path="../pb_data/types.d.ts" />
migrate((app) => {
const collection = app.findCollectionByNameOrId("pbc_4226991559")
// add field
collection.fields.addAt(17, new Field({
"hidden": false,
"id": "geoPoint3807818301",
"name": "geopoint_field",
"presentable": false,
"required": false,
"system": false,
"type": "geoPoint"
}))
return app.save(collection)
}, (app) => {
const collection = app.findCollectionByNameOrId("pbc_4226991559")
// remove field
collection.fields.removeById("geoPoint3807818301")
return app.save(collection)
})

View File

@@ -2,4 +2,4 @@
echo "Starting pocketbase server. Username: test@test.com, Password: testpassword"
# Start pocketbase server
/app/pocketbase serve --http=0.0.0.0:8090
/app/test/integration/pocketbase serve --http=0.0.0.0:8090

View File

@@ -1,15 +1,17 @@
#!/bin/sh
echo "Starting integration test."
cd /app/test/integration
mkdir -p output
# Start pocketbase server
/app/pocketbase serve --http=0.0.0.0:8090 &
./pocketbase serve --http=0.0.0.0:8090 &
echo "Waiting for server to start."
while ! nc -z localhost 8090 </dev/null; do sleep 1; done
node ./dist/index.js --url http://0.0.0.0:8090 --email test@test.com --password testpassword --out output/pocketbase-types-url.ts
node ./dist/index.js --db pb_data/data.db --out output/pocketbase-types-db.ts
node ./dist/index.js --env --out output/pocketbase-types-env.ts
node ../../dist/index.js --url http://0.0.0.0:8090 --email test@test.com --password testpassword --out ./output/pocketbase-types-url.ts
node ../../dist/index.js --db pb_data/data.db --out ./output/pocketbase-types-db.ts
node ../../dist/index.js --env --out ./output/pocketbase-types-env.ts
node integration.js
exit_status=$?

View File

@@ -125,9 +125,7 @@
},
"passwordAuth": {
"enabled": true,
"identityFields": [
"email"
]
"identityFields": ["email"]
},
"mfa": {
"enabled": false,
@@ -312,9 +310,7 @@
},
"passwordAuth": {
"enabled": true,
"identityFields": [
"email"
]
"identityFields": ["email"]
},
"mfa": {
"enabled": false,
@@ -519,9 +515,7 @@
},
"passwordAuth": {
"enabled": true,
"identityFields": [
"email"
]
"identityFields": ["email"]
},
"mfa": {
"enabled": false,
@@ -1020,9 +1014,7 @@
"type": "autodate"
}
],
"indexes": [
"CREATE INDEX `idx_77jkB2zihL` ON `base` (`created`)"
],
"indexes": ["CREATE INDEX `idx_77jkB2zihL` ON `base` (`created`)"],
"system": false
},
{
@@ -1248,6 +1240,15 @@
"system": false,
"type": "relation"
},
{
"hidden": false,
"id": "geoPoint3807818301",
"name": "geopoint_field",
"presentable": false,
"required": false,
"system": false,
"type": "geoPoint"
},
{
"hidden": false,
"id": "autodate2990389176",
@@ -1372,7 +1373,7 @@
"max": 0,
"min": 0,
"name": "id",
"pattern": "",
"pattern": "^[a-z0-9]+$",
"presentable": false,
"primaryKey": true,
"required": true,
@@ -1383,7 +1384,7 @@
"cascadeDelete": false,
"collectionId": "pbc_1125843985",
"hidden": false,
"id": "_clone_jKWX",
"id": "_clone_sKQA",
"maxSelect": 1,
"minSelect": 0,
"name": "post_relation_field",
@@ -1395,7 +1396,7 @@
{
"autogeneratePattern": "",
"hidden": false,
"id": "_clone_T8dY",
"id": "_clone_LIwJ",
"max": 0,
"min": 0,
"name": "text_field",
@@ -1408,7 +1409,7 @@
},
{
"hidden": false,
"id": "_clone_vEtC",
"id": "_clone_wOsb",
"maxSize": 2000000,
"name": "json_field",
"presentable": false,
@@ -1421,4 +1422,4 @@
"system": false,
"viewQuery": "select id, post_relation_field, text_field, json_field from everything"
}
]
]

View File

@@ -24,6 +24,11 @@ export type IsoDateString = string
export type RecordIdString = string
export type HTMLString = string
export type GeoPoint = {
lon: number
lat: number
}
type ExpandType<T> = unknown extends T
? T extends unknown
? { expand?: unknown }
@@ -130,6 +135,7 @@ export type EverythingRecord<Tanother_json_field = unknown, Tjson_field = unknow
date_field?: IsoDateString
email_field?: string
file_field?: string
geopoint_field?: GeoPoint
id: string
json_field?: null | Tjson_field
number_field?: number