pocketbase-import/utils/pocketbase.ts
michal-kapala df56216609 update to v0.23.1
+ package version bump to 0.22.0
+ support for PB v0.23.1 collections
2024-11-26 17:39:41 +01:00

196 lines
4.5 KiB
TypeScript

import { RawCsvRow } from "../types/csv.ts";
import { RawJsonRow } from "../types/json.ts";
import {
POCKETBASE_TYPE,
PocketbaseRowSchema,
PocketbaseType,
SchemaField,
BoolField,
NumberField,
TextField,
EmailField,
JsonField,
DateField,
UrlField
} from "../types/pocketbase.ts";
import { addSchemaField as addCsvSchemaField } from "./csv.ts";
import { addSchemaField as addJsonSchemaField } from "./json.ts";
/**
* Finds column's type in the schema.
* @param column Column name.
* @param schema PocketBase collection schema.
* @returns
*/
export function getSchemaType(
column: string,
schema: SchemaField[],
): PocketbaseType {
const schemaField = schema.find((field) => field.name === column);
// if somehow the data got structured wrong
if (schemaField === undefined) {
console.error(
`%cSchemaError: Supplied column '${column}' not found in collection schema`,
"color: red",
);
Deno.exit(-1);
return "text";
}
if (schemaField.type == null) {
console.error(
`%cSchemaError: Column type missing for '${column}'`,
"color: red",
);
Deno.exit(-1);
return "text";
}
return schemaField.type;
}
/**
* Builds a `SchemaField` object based on data type.
* @param name Column name.
* @param type PocketBase type.
* @returns
*/
export function createSchemaField(
name: string,
type: PocketbaseType,
): SchemaField {
switch (type) {
case POCKETBASE_TYPE.BOOL:
return {
hidden: false,
name,
presentable: false,
required: false,
system: false,
type,
} as BoolField;
case POCKETBASE_TYPE.NUMBER:
return {
hidden: false,
max: undefined,
min: undefined,
name,
onlyInt: false,
presentable: false,
required: false,
system: false,
type,
} as NumberField;
case POCKETBASE_TYPE.PLAIN_TEXT:
return {
autogeneratePattern: "",
hidden: false,
max: 0,
min: 0,
name,
pattern: "",
presentable: false,
primaryKey: false,
required: false,
system: false,
type,
} as TextField;
case POCKETBASE_TYPE.EMAIL:
return {
exceptDomains: undefined,
hidden: false,
name,
onlyDomains: undefined,
presentable: false,
required: false,
system: false,
type,
} as EmailField;
case POCKETBASE_TYPE.JSON:
return {
hidden: false,
maxSize: 0,
name,
presentable: false,
required: false,
system: false,
type,
} as JsonField;
case POCKETBASE_TYPE.DATETIME:
return {
hidden: false,
max: "",
min: "",
name,
presentable: false,
required: false,
system: false,
type,
} as DateField;
case POCKETBASE_TYPE.URL:
return {
hidden: false,
exceptDomains: undefined,
name,
onlyDomains: undefined,
presentable: false,
required: false,
system: false,
type,
} as UrlField;
}
}
/**
* Creates a row object schema from PocketBase collection schema.
* @param schema PocketBase collection schema.
* @returns
*/
export function generateRowSchema(schema: SchemaField[]): PocketbaseRowSchema {
let instance: PocketbaseRowSchema = {};
let fieldType: PocketbaseType;
schema.forEach((field) => {
fieldType = getSchemaType(field.name, schema);
instance = { ...instance, [field.name]: fieldType };
});
return instance;
}
/**
* Parses raw objects into PocketBase collection schema fields.
* @param data Raw input data.
* @returns
*/
// deno-lint-ignore no-explicit-any
export function createSchema(
data: { [key: string]: any },
stringifyId: boolean,
inputFormat: "csv" | "json",
) {
const schema: SchemaField[] = [];
// Seeks patterns in up to 1k records to avoid poor performance on large datasets
if (data.length > 1000) {
data = data.slice(0, 1000);
}
// Analyzes each column, deducts a type and creates a schema field
for (const prop in data[0]) {
// respect --id option
if (stringifyId && prop.toLowerCase() === "id") {
schema.push(createSchemaField(`_${prop}`, "text"));
} else {
schema.push(
inputFormat === "csv"
? addCsvSchemaField(data as RawCsvRow[], prop)
: addJsonSchemaField(data as RawJsonRow[], prop),
);
}
}
return schema;
}