mirror of
https://github.com/pockethost/pockethost.git
synced 2025-07-04 03:42:29 +00:00
chore: REST refactor
This commit is contained in:
parent
881c42ddcb
commit
e09e80fa4f
@ -100,13 +100,13 @@ export const createPocketbaseClient = (config: PocketbaseClientConfig) => {
|
||||
|
||||
const createInstance = mkRest<CreateInstancePayload, CreateInstanceResult>(
|
||||
RestCommands.Instance,
|
||||
RestMethods.Create,
|
||||
RestMethods.Post,
|
||||
CreateInstancePayloadSchema,
|
||||
)
|
||||
|
||||
const updateInstance = mkRest<UpdateInstancePayload, UpdateInstanceResult>(
|
||||
RestCommands.Instance,
|
||||
RestMethods.Update,
|
||||
RestMethods.Put,
|
||||
UpdateInstancePayloadSchema,
|
||||
)
|
||||
|
||||
|
@ -14,7 +14,7 @@
|
||||
const isChecked = target.checked
|
||||
|
||||
// Update the database with the new value
|
||||
updateInstance({ instanceId: id, fields: { maintenance: isChecked } }).then(
|
||||
updateInstance({ id, fields: { maintenance: isChecked } }).then(
|
||||
() => 'saved',
|
||||
)
|
||||
}
|
||||
|
@ -40,7 +40,7 @@
|
||||
// If they select yes, then update the version in pocketbase
|
||||
if (confirmVersionChange) {
|
||||
updateInstance({
|
||||
instanceId: id,
|
||||
id,
|
||||
fields: {
|
||||
subdomain: instanceNameValidation,
|
||||
},
|
||||
|
@ -39,7 +39,7 @@
|
||||
errorMessage = ''
|
||||
client()
|
||||
.updateInstance({
|
||||
instanceId: id,
|
||||
id,
|
||||
fields: { version: selectedVersion },
|
||||
})
|
||||
.then(() => {
|
||||
|
@ -44,7 +44,7 @@
|
||||
// Save to the database
|
||||
items.upsert({ name: secretKey, value: secretValue })
|
||||
await client().updateInstance({
|
||||
instanceId: $instance.id,
|
||||
id: $instance.id,
|
||||
fields: {
|
||||
secrets: reduce(
|
||||
$items,
|
||||
|
@ -2,7 +2,7 @@
|
||||
|
||||
/*
|
||||
{
|
||||
"instanceId": "kz4ngg77eaw1ho0",
|
||||
"id": "kz4ngg77eaw1ho0",
|
||||
"fields": {
|
||||
"maintenance": true
|
||||
"name": '',
|
||||
@ -12,12 +12,11 @@
|
||||
*/
|
||||
routerAdd(
|
||||
'PUT',
|
||||
'/api/instance',
|
||||
'/api/instance/:id',
|
||||
(c) => {
|
||||
console.log(`***TOP OF PUt`)
|
||||
console.log(`***TOP OF PUT`)
|
||||
let data = new DynamicModel({
|
||||
// describe the shape of the fields to read (used also as initial values)
|
||||
instanceId: '',
|
||||
id: '',
|
||||
fields: {
|
||||
maintenance: null,
|
||||
name: null,
|
||||
@ -27,21 +26,28 @@ routerAdd(
|
||||
})
|
||||
|
||||
c.bind(data)
|
||||
console.log(`***After bind`)
|
||||
|
||||
// This is necessary for destructuring to work correctly
|
||||
data = JSON.parse(JSON.stringify(data))
|
||||
|
||||
const id = c.pathParam('id')
|
||||
const {
|
||||
instanceId,
|
||||
fields: { maintenance, name, version, secrets },
|
||||
} = data
|
||||
|
||||
console.log(
|
||||
`***vars`,
|
||||
JSON.stringify({ instanceId, maintenance, name, version, secrets }),
|
||||
JSON.stringify({
|
||||
id,
|
||||
maintenance,
|
||||
name,
|
||||
version,
|
||||
secrets,
|
||||
}),
|
||||
)
|
||||
|
||||
const record = $app.dao().findRecordById('instances', instanceId)
|
||||
const record = $app.dao().findRecordById('instances', id)
|
||||
const authRecord = c.get('authRecord') // empty if not authenticated as regular auth record
|
||||
console.log(`***authRecord`, JSON.stringify(authRecord))
|
||||
|
||||
@ -53,22 +59,23 @@ routerAdd(
|
||||
}
|
||||
|
||||
function cleanObject(obj) {
|
||||
return Object.entries(obj).reduce((acc, [key, value]) => {
|
||||
console.log(`***original`, JSON.stringify(obj))
|
||||
const sanitized = Object.entries(obj).reduce((acc, [key, value]) => {
|
||||
if (value !== null && value !== undefined) {
|
||||
acc[key] = value
|
||||
}
|
||||
return acc
|
||||
}, {})
|
||||
console.log(`***sanitized`, JSON.stringify(sanitized))
|
||||
return sanitized
|
||||
}
|
||||
|
||||
console.log(`***original`, JSON.stringify(data))
|
||||
const sanitized = cleanObject({
|
||||
subdomain: name,
|
||||
version,
|
||||
maintenance,
|
||||
secrets,
|
||||
})
|
||||
console.log(`***sanitized`, JSON.stringify(sanitized))
|
||||
|
||||
const form = new RecordUpsertForm($app, record)
|
||||
form.loadData(sanitized)
|
||||
|
@ -1,5 +1,6 @@
|
||||
import Ajv, { JSONSchemaType } from 'ajv'
|
||||
import type pocketbaseEs from 'pocketbase'
|
||||
import { ClientResponseError } from 'pocketbase'
|
||||
import type { JsonObject } from 'type-fest'
|
||||
import { LoggerService } from '../Logger'
|
||||
import { RestCommands, RestMethods } from '../schema'
|
||||
@ -28,13 +29,41 @@ export const createRestHelper = (config: RestHelperConfig) => {
|
||||
if (!validator(payload)) {
|
||||
throw new Error(`Invalid REST payload: ${validator.errors}`)
|
||||
}
|
||||
const _payload = { ...payload }
|
||||
|
||||
const res = await client.send(`/api/${cmd}`, {
|
||||
method: method,
|
||||
body: payload,
|
||||
const url = `/api/${cmd}${
|
||||
method === RestMethods.Post ? '' : '/:id'
|
||||
}`.replace(/:([a-zA-Z]+)/g, (_, key) => {
|
||||
if (!(key in _payload)) {
|
||||
throw new Error(`Payload must include '${key}`)
|
||||
}
|
||||
const value = _payload[key]!
|
||||
delete _payload[key]
|
||||
return encodeURIComponent(value.toString())
|
||||
})
|
||||
|
||||
const options: any = {
|
||||
method: method,
|
||||
}
|
||||
|
||||
if (method !== RestMethods.Get) {
|
||||
options.body = _payload
|
||||
}
|
||||
|
||||
dbg({ url, options })
|
||||
|
||||
try {
|
||||
const res = await client.send(url, options)
|
||||
dbg(res)
|
||||
return res
|
||||
} catch (e) {
|
||||
if (e instanceof ClientResponseError) {
|
||||
error(`REST error: ${e.originalError}`)
|
||||
throw e.originalError
|
||||
}
|
||||
error(`REST error: ${e}`)
|
||||
throw e
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,16 +1,15 @@
|
||||
import { JSONSchemaType } from 'ajv'
|
||||
import { InstanceId, Semver } from '../types'
|
||||
import { InstanceFields } from '../Instance'
|
||||
import { InstanceId } from '../types'
|
||||
|
||||
export type UpdateInstancePayload = {
|
||||
instanceId: InstanceId
|
||||
fields: {
|
||||
subdomain?: string
|
||||
maintenance?: boolean
|
||||
version?: Semver
|
||||
secrets?: {
|
||||
[_: string]: string
|
||||
}
|
||||
}
|
||||
id: InstanceId
|
||||
fields: Partial<
|
||||
Pick<
|
||||
InstanceFields,
|
||||
'maintenance' | 'secrets' | 'subdomain' | 'syncAdmin' | 'version'
|
||||
>
|
||||
>
|
||||
}
|
||||
|
||||
export const SECRET_KEY_REGEX = /^[A-Z][A-Z0-9_]*$/
|
||||
@ -24,10 +23,11 @@ export const UpdateInstancePayloadSchema: JSONSchemaType<UpdateInstancePayload>
|
||||
{
|
||||
type: 'object',
|
||||
properties: {
|
||||
instanceId: { type: 'string' },
|
||||
id: { type: 'string' },
|
||||
fields: {
|
||||
type: 'object',
|
||||
properties: {
|
||||
syncAdmin: { type: 'boolean', nullable: true },
|
||||
subdomain: { type: 'string', nullable: true },
|
||||
maintenance: { type: 'boolean', nullable: true },
|
||||
version: {
|
||||
@ -47,6 +47,6 @@ export const UpdateInstancePayloadSchema: JSONSchemaType<UpdateInstancePayload>
|
||||
},
|
||||
},
|
||||
},
|
||||
required: ['instanceId', 'fields'],
|
||||
required: ['id', 'fields'],
|
||||
additionalProperties: false,
|
||||
}
|
||||
|
@ -2,8 +2,9 @@ import Ajv from 'ajv'
|
||||
import { JsonObject } from 'type-fest'
|
||||
|
||||
export enum RestMethods {
|
||||
Create = 'POST',
|
||||
Update = 'PUT',
|
||||
Get = 'GET',
|
||||
Post = 'POST',
|
||||
Put = 'PUT',
|
||||
}
|
||||
|
||||
export enum RestCommands {
|
||||
@ -16,4 +17,3 @@ export const ajv = new Ajv()
|
||||
|
||||
export * from './CreateInstance'
|
||||
export * from './UpdateInstance'
|
||||
// gen:export
|
||||
|
Loading…
x
Reference in New Issue
Block a user