UNPKG

blade

Version:
397 lines (393 loc) • 12.1 kB
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 };