blade
Version:
React at the edge.
397 lines (393 loc) • 12.1 kB
JavaScript
import "../../remote-storage-CThzVgzV.js";
import { _ as getTriggerName, p as TRIGGER_TYPES } from "../../utils-BeDKhSpT.js";
import { a as getQuerySymbol, i as QUERY_TYPES, r as QUERY_SYMBOLS } from "../../dist-C7NzDGd9.js";
import { n as getSyntaxProxy } from "../../queries-CO8sEzJ9.js";
//#region ../blade-syntax/dist/schema.js
/**
* Generates a model definition and adds default fields to the provided model.
*
* @example
* ```ts
* const Account = model({
* slug: 'account',
* pluralSlug: 'accounts',
* fields: {
* name: string()
* },
* });
* ```
*
* @template T - A generic type representing the model structure, which contains a slug
* and fields.
* @param model - An object containing the slug and fields of the model.
*
* @returns The generated model definition.
*/
const model = (model$1) => {
return getSyntaxProxy({
modelType: true,
chaining: false
})(model$1);
};
/**
* Creates a primitive field definition returning an object that includes the field type
* and attributes.
*
* @param type - The field type.
*
* @returns A field of the provided type with the specified attributes.
*/
const primitive = (type) => {
return (initialAttributes = {}) => {
return getSyntaxProxy({ propertyValue: true })({
...initialAttributes,
type
});
};
};
/**
* Creates a string field definition returning an object that includes the field type
* ("string") and attributes.
*
* @example
* ```ts
* import { model, string } from 'blade/schema';
*
* const User = model({
* slug: 'user',
*
* fields: {
* name: string(),
* email: string({ required: true, unique: true })
* },
* });
* ```
*
* @param attributes - Optional field attributes.
*
* @returns A field of type "string" with the specified attributes.
*/
const string = primitive("string");
/**
* Creates a number field definition returning an object that includes the field type
* ("number") and attributes.
*
* @example
* ```ts
* import { model, number } from 'blade/schema';
*
* const User = model({
* slug: 'user',
*
* fields: {
* points: number(),
* numReferrals: number({ defaultValue: 0 })
* },
* });
* ```
*
* @param attributes - Optional field attributes.
*
* @returns A field of type "number" with the specified attributes.
*/
const number = primitive("number");
/**
* Creates a link field definition returning an object that includes the field type
* ("link") and attributes.
*
* @example
* ```ts
* import { model, link } from 'blade/schema';
*
* const User = model({
* slug: 'user',
*
* fields: {
* account: link({ target: 'account' }),
* posts: link({ target: 'post', kind: 'many', required: true })
* },
* });
* ```
*
* @param attributes - Optional field attributes.
*
* @returns A field of type "link" with the specified attributes.
*/
const link = primitive("link");
/**
* Creates a JSON field definition returning an object that includes the field type
* ("json") and attributes.
*
* @example
* ```ts
* import { model, json } from 'blade/schema';
*
* const User = model({
* slug: 'user',
*
* fields: {
* settings: json()
* },
* });
* ```
*
* @param attributes - Optional field attributes.
*
* @returns A field of type "json" with the specified attributes.
*/
const json = primitive("json");
/**
* Creates a date field definition returning an object that includes the field type
* ("date") and attributes.
*
* @example
* ```ts
* import { model, date } from 'blade/schema';
*
* const User = model({
* slug: 'user',
*
* fields: {
* lastActiveAt: date(),
* deactivatedAt: date({ defaultValue: null })
* },
* });
* ```
*
* @param attributes - Optional field attributes.
*
* @returns A field of type "date" with the specified attributes.
*/
const date = primitive("date");
/**
* Creates a boolean field definition returning an object that includes the field type
* ("boolean") and attributes.
*
* @example
* ```ts
* import { model, boolean } from 'blade/schema';
*
* const User = model({
* slug: 'user',
*
* fields: {
* earlyAccess: boolean(),
* isVerified: boolean({ defaultValue: false, required: true })
* },
* });
* ```
*
* @param attributes - Optional field attributes.
*
* @returns A field of type "boolean" with the specified attributes.
*/
const boolean = primitive("boolean");
/**
* Creates a blob field definition returning an object that includes the field type
* ("blob") and attributes.
*
* @example
* ```ts
* import { model, blob } from 'blade/schema';
*
* const User = model({
* slug: 'user',
*
* fields: {
* avatar: blob(),
* contents: blob({ required: true })
* },
* });
* ```
*
* @param attributes - Optional field attributes.
*
* @returns A field of type "blob" with the specified attributes.
*/
const blob = primitive("blob");
/**
* Creates a query expression object that can be processed by the compiler.
*
* @param expression - The expression string to wrap in a query symbol.
*
* @returns An object containing the expression wrapped in a query symbol.
*/
const expression = (expression$1) => ({ [QUERY_SYMBOLS.EXPRESSION]: expression$1 });
/**
* Creates a binary operation expression with type safety for operands.
*
* @param left - The left operand.
* @param operator - The operator to use (string concatenation or arithmetic).
* @param right - The right operand (must match type of left operand).
*
* @returns The formatted binary operation expression.
*/
const op = (left, operator, right) => {
let leftValue = left;
if (typeof left === "object" && QUERY_SYMBOLS.EXPRESSION in left) leftValue = left[QUERY_SYMBOLS.EXPRESSION];
let rightValue = right;
if (typeof right === "object" && QUERY_SYMBOLS.EXPRESSION in right) rightValue = right[QUERY_SYMBOLS.EXPRESSION];
let wrappedLeft = leftValue;
if (typeof leftValue === "string" && !(typeof left === "object" && (QUERY_SYMBOLS.EXPRESSION in left || QUERY_SYMBOLS.FIELD in left))) wrappedLeft = `'${leftValue}'`;
let wrappedRight = rightValue;
if (typeof rightValue === "string" && !(typeof right === "object" && (QUERY_SYMBOLS.EXPRESSION in right || QUERY_SYMBOLS.FIELD in right))) wrappedRight = `'${rightValue}'`;
return expression(`(${wrappedLeft} ${operator} ${wrappedRight})`);
};
/**
* Wraps a raw SQL expression as-is.
* Use with caution as this bypasses SQL injection protection.
*
* @param expressions - The raw SQL expression to use.
*
* @returns The wrapped SQL expression
*/
const sql = (expressions) => expression(expressions);
/**
* Generates a pseudo-random integer between -9223372036854775808 and +9223372036854775807.
*
* @returns SQL expression that evaluates to a random number.
*/
const random = () => expression("random()");
/**
* Calculates the absolute value of a number.
*
* @param value - The number to get absolute value of.
*
* @returns SQL expression that evaluates to the absolute value.
*/
const abs = (value$1) => {
return expression(`abs(${typeof value$1 === "object" && QUERY_SYMBOLS.EXPRESSION in value$1 ? value$1[QUERY_SYMBOLS.EXPRESSION] : value$1})`);
};
/**
* Formats a timestamp according to the specified format string.
*
* @param format - The format string (e.g. '%Y-%m-%d').
* @param timestamp - The timestamp to format, or 'now' for current time.
*
* @returns SQL expression that evaluates to the formatted timestamp.
*/
const strftime = (format, timestamp) => expression(`strftime('${format}', '${timestamp}')`);
/**
* Extracts a value from a JSON document at the specified path.
*
* @param json - The JSON document to extract from.
* @param path - The path to extract the value from.
*
* @returns SQL expression that evaluates to the extracted value.
*/
const json_extract = (json$1, path) => expression(`json_extract('${json$1}', '${path}')`);
/**
* Applies a JSON patch operation to a JSON document.
*
* @param patch - The JSON patch document defining the modifications.
* @param input - The JSON document to patch.
*
* @returns SQL expression that evaluates to the patched JSON document.
*/
const json_patch = (patch, input) => expression(`json_patch('${patch}', '${input}')`);
/**
* Sets a value in a JSON document at the specified path.
* Creates the path if it doesn't exist and overwrites if it does.
*
* @param json - The JSON document to modify.
* @param path - The path to set the value at.
* @param value - The value to set.
*
* @returns SQL expression that evaluates to the modified JSON document.
*/
const json_set = (json$1, path, value$1) => expression(`json_set('${json$1}', '${path}', '${value$1}')`);
/**
* Replaces a value in a JSON document at the specified path.
* Only modifies existing paths, will not create new ones.
*
* @param json - The JSON document to modify.
* @param path - The path to replace the value at.
* @param value - The new value.
*
* @returns SQL expression that evaluates to the modified JSON document.
*/
const json_replace = (json$1, path, value$1) => expression(`json_replace('${json$1}', '${path}', '${value$1}')`);
/**
* Inserts a value into a JSON document at the specified path.
* Only creates new paths, will not modify existing ones.
*
* @param json - The JSON document to modify.
* @param path - The path to insert the value at.
* @param value - The value to insert.
*
* @returns SQL expression that evaluates to the modified JSON document.
*/
const json_insert = (json$1, path, value$1) => expression(`json_insert('${json$1}', '${path}', '${value$1}')`);
/**
* Concatenates a list of strings together.
*
* @param values - The list of strings to concatenate.
*
* @returns An expression representing the concatenated string.
*/
const concat = (...values) => {
return expression(`concat(${values.map((value$1) => {
const symbol = getQuerySymbol(value$1);
return symbol?.type === "expression" ? symbol.value : `'${value$1}'`;
}).join(", ")})`);
};
/**
* Replaces all occurrences of a substring within a string with a replacement value.
*
* @param input - The string to perform replacements on.
* @param search - The substring to search for.
* @param replacement - The string to replace matches with.
*
* @returns SQL expression that evaluates to the modified string.
*/
const replace = (input, search, replacement) => expression(`replace('${input}', '${search}', '${replacement}')`);
//#endregion
//#region private/universal/triggers.ts
const triggers = (...list$1) => {
const final = {};
for (const triggerType of TRIGGER_TYPES) for (const queryType of QUERY_TYPES) {
const method = getTriggerName(triggerType, queryType);
for (const group of list$1) {
const addedFunction = group[method];
if (!addedFunction) continue;
const existingFunction = final[method];
if (!existingFunction) {
final[method] = addedFunction;
continue;
}
if (triggerType === "before" || triggerType === "after") {
final[method] = async (options) => {
const existing = await existingFunction(options);
const added = await addedFunction(options);
return [...typeof existing === "function" ? existing() : existing, ...typeof added === "function" ? added() : added];
};
continue;
}
if (triggerType === "during") final[method] = async (options) => {
const existing = await existingFunction(options);
return addedFunction({
...options,
query: existing
});
};
if (triggerType === "following") final[method] = async (options) => {
await Promise.all([existingFunction(options), addedFunction(options)]);
};
}
}
return final;
};
//#endregion
//#region public/universal/schema.ts
const value = (queryType) => ({ root: `${QUERY_SYMBOLS.QUERY}.${queryType}` });
const get = getSyntaxProxy(value("get"));
const set = getSyntaxProxy(value("set"));
const add = getSyntaxProxy(value("add"));
const remove = getSyntaxProxy(value("remove"));
const count = getSyntaxProxy(value("count"));
const list = getSyntaxProxy(value("list"));
const create = getSyntaxProxy(value("create"));
const alter = getSyntaxProxy(value("alter"));
const drop = getSyntaxProxy(value("drop"));
//#endregion
export { abs, add, alter, blob, boolean, concat, count, create, date, drop, get, json, json_extract, json_insert, json_patch, json_replace, json_set, link, list, model, number, op, random, remove, replace, set, sql, strftime, string, triggers };