flint-orm
Version:
Type-safe SQLite ORM for JavaScript
444 lines (442 loc) • 12.4 kB
JavaScript
// @bun
var __create = Object.create;
var __getProtoOf = Object.getPrototypeOf;
var __defProp = Object.defineProperty;
var __getOwnPropNames = Object.getOwnPropertyNames;
var __hasOwnProp = Object.prototype.hasOwnProperty;
function __accessProp(key) {
return this[key];
}
var __toESMCache_node;
var __toESMCache_esm;
var __toESM = (mod, isNodeMode, target) => {
var canCache = mod != null && typeof mod === "object";
if (canCache) {
var cache = isNodeMode ? __toESMCache_node ??= new WeakMap : __toESMCache_esm ??= new WeakMap;
var cached = cache.get(mod);
if (cached)
return cached;
}
target = mod != null ? __create(__getProtoOf(mod)) : {};
const to = isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target;
for (let key of __getOwnPropNames(mod))
if (!__hasOwnProp.call(to, key))
__defProp(to, key, {
get: __accessProp.bind(mod, key),
enumerable: true
});
if (canCache)
cache.set(mod, to);
return to;
};
var __commonJS = (cb, mod) => () => (mod || cb((mod = { exports: {} }).exports, mod), mod.exports);
var __returnValue = (v) => v;
function __exportSetter(name, newValue) {
this[name] = __returnValue.bind(null, newValue);
}
var __export = (target, all) => {
for (var name in all)
__defProp(target, name, {
get: all[name],
enumerable: true,
configurable: true,
set: __exportSetter.bind(all, name)
});
};
var __esm = (fn, res) => () => (fn && (res = fn(fn = 0)), res);
var __require = import.meta.require;
// src/schema/columns.ts
function nullCast() {
return null;
}
function makeColumn(config) {
const base = {
name: config.name,
__internal: {
_type: undefined,
sqlType: config.sqlType,
isPrimaryKey: false,
isNotNull: false,
isUnique: false,
hasDefault: false,
defaultValue: undefined,
defaultFn: undefined,
isAutoIncrement: false,
hasDefaultNow: false,
hasOnUpdate: false,
referencesTable: null,
referencesColumn: null,
onDelete: null,
onUpdate: null,
encode: config.encode,
decode: config.decode,
tableName: null
}
};
const col = {
...base,
primaryKey() {
return { ...this, __internal: { ...this.__internal, isPrimaryKey: true } };
},
notNull() {
return { ...this, __internal: { ...this.__internal, isNotNull: true } };
},
unique() {
return { ...this, __internal: { ...this.__internal, isUnique: true } };
},
default(value) {
return { ...this, __internal: { ...this.__internal, hasDefault: true, defaultValue: value } };
},
defaultFn(fn) {
return { ...this, __internal: { ...this.__internal, hasDefault: true, defaultFn: fn } };
},
references(target) {
return {
...this,
__internal: {
...this.__internal,
referencesTable: target.__internal.tableName,
referencesColumn: target.name
}
};
},
onDelete(action) {
return { ...this, __internal: { ...this.__internal, onDelete: action } };
},
onUpdate(action) {
return { ...this, __internal: { ...this.__internal, onUpdate: action } };
}
};
return col;
}
function text(name) {
return makeColumn({
name: name ?? "",
sqlType: "text",
encode: (v) => v,
decode: (v) => v == null ? nullCast() : v
});
}
function integer(name) {
const base = makeColumn({
name: name ?? "",
sqlType: "integer",
encode: (v) => v,
decode: (v) => v == null ? nullCast() : Number(v)
});
const intCol = {
...base,
primaryKey() {
return {
...this,
__internal: { ...this.__internal, isPrimaryKey: true }
};
},
notNull() {
return {
...this,
__internal: { ...this.__internal, isNotNull: true }
};
},
unique() {
return {
...this,
__internal: { ...this.__internal, isUnique: true }
};
},
default(value) {
return {
...this,
__internal: { ...this.__internal, hasDefault: true, defaultValue: value }
};
},
defaultFn(fn) {
return {
...this,
__internal: { ...this.__internal, hasDefault: true, defaultFn: fn }
};
},
autoIncrement() {
return {
...this,
__internal: { ...this.__internal, isAutoIncrement: true }
};
}
};
return intCol;
}
function boolean(name) {
return makeColumn({
name: name ?? "",
sqlType: "integer",
encode: (v) => v ? 1 : 0,
decode: (v) => v == null ? nullCast() : Boolean(v)
});
}
function json(name) {
return makeColumn({
name: name ?? "",
sqlType: "text",
encode: (v) => v == null ? null : JSON.stringify(v),
decode: (v) => v == null ? nullCast() : JSON.parse(v)
});
}
function date(name) {
const base = makeColumn({
name: name ?? "",
sqlType: "integer",
encode: (v) => v == null ? null : v.getTime(),
decode: (v) => v == null ? nullCast() : new Date(v)
});
const dateCol = {
...base,
primaryKey() {
return { ...this, __internal: { ...this.__internal, isPrimaryKey: true } };
},
notNull() {
return { ...this, __internal: { ...this.__internal, isNotNull: true } };
},
unique() {
return { ...this, __internal: { ...this.__internal, isUnique: true } };
},
default(value) {
return { ...this, __internal: { ...this.__internal, hasDefault: true, defaultValue: value } };
},
defaultFn(fn) {
return { ...this, __internal: { ...this.__internal, hasDefault: true, defaultFn: fn } };
},
defaultNow() {
return { ...this, __internal: { ...this.__internal, hasDefaultNow: true } };
},
onUpdateTimestamp() {
return { ...this, __internal: { ...this.__internal, hasOnUpdate: true } };
}
};
return dateCol;
}
function real(name) {
return makeColumn({
name: name ?? "",
sqlType: "real",
encode: (v) => v,
decode: (v) => v == null ? nullCast() : Number(v)
});
}
// src/schema/table.ts
function table(name, columns, indexFn) {
const stamped = Object.create(null);
for (const [key, col] of Object.entries(columns)) {
const columnName = col.name || key;
const stampedInternal = { ...col.__internal, name: columnName, tableName: name };
const stampedCol = {
name: columnName,
__internal: stampedInternal,
primaryKey() {
return { ...this, __internal: { ...stampedInternal, isPrimaryKey: true } };
},
notNull() {
return { ...this, __internal: { ...stampedInternal, isNotNull: true } };
},
unique() {
return { ...this, __internal: { ...stampedInternal, isUnique: true } };
},
default(value) {
return {
...this,
__internal: { ...stampedInternal, hasDefault: true, defaultValue: value }
};
},
defaultFn(fn) {
return { ...this, __internal: { ...stampedInternal, hasDefault: true, defaultFn: fn } };
},
references(target) {
return {
...this,
__internal: {
...stampedInternal,
referencesTable: target.__internal.tableName,
referencesColumn: target.name
}
};
},
onDelete(action) {
return { ...this, __internal: { ...stampedInternal, onDelete: action } };
},
onUpdate(action) {
return { ...this, __internal: { ...stampedInternal, onUpdate: action } };
}
};
if ("autoIncrement" in col) {
stampedCol.autoIncrement = function() {
return { ...this, __internal: { ...stampedInternal, isAutoIncrement: true } };
};
}
if ("defaultNow" in col) {
stampedCol.defaultNow = function() {
return { ...this, __internal: { ...stampedInternal, hasDefaultNow: true } };
};
}
if ("onUpdateTimestamp" in col) {
stampedCol.onUpdateTimestamp = function() {
return { ...this, __internal: { ...stampedInternal, hasOnUpdate: true } };
};
}
stamped[key] = stampedCol;
}
const result = Object.assign(stamped, {
_: { name }
});
if (indexFn) {
const raw = indexFn(result);
if (raw.length > 0) {
const tableObj = result;
const indexes = [];
let primaryKeyDef;
for (const item of raw) {
if (item && typeof item === "object" && "_type" in item) {
if (item._type === "primaryKey") {
primaryKeyDef = item.build();
} else {
indexes.push(item.build());
}
}
}
if (primaryKeyDef) {
for (const [key, col] of Object.entries(columns)) {
if (col.__internal.isPrimaryKey) {
throw new Error(`Column "${key}" has primaryKey() but table "${name}" also defines a composite primaryKey(). Use one or the other.`);
}
}
tableObj.__primaryKey = primaryKeyDef;
}
if (indexes.length > 0) {
tableObj.__indexes = indexes;
}
}
}
return result;
}
function toSnakeCase(str) {
return str.replace(/[A-Z]/g, (letter) => `_${letter.toLowerCase()}`);
}
function snakeCaseTable(tableName, columns, indexFn) {
const converted = {};
for (const [key, col] of Object.entries(columns)) {
const sqlName = toSnakeCase(key);
const columnName = col.name || sqlName;
const stampedInternal = { ...col.__internal, name: columnName, tableName };
const stampedCol = {
name: columnName,
__internal: stampedInternal,
primaryKey() {
return { ...this, __internal: { ...stampedInternal, isPrimaryKey: true } };
},
notNull() {
return { ...this, __internal: { ...stampedInternal, isNotNull: true } };
},
unique() {
return { ...this, __internal: { ...stampedInternal, isUnique: true } };
},
default(value) {
return {
...this,
__internal: { ...stampedInternal, hasDefault: true, defaultValue: value }
};
},
defaultFn(fn) {
return { ...this, __internal: { ...stampedInternal, hasDefault: true, defaultFn: fn } };
},
references(target) {
return {
...this,
__internal: {
...stampedInternal,
referencesTable: target.__internal.tableName,
referencesColumn: target.name
}
};
},
onDelete(action) {
return { ...this, __internal: { ...stampedInternal, onDelete: action } };
},
onUpdate(action) {
return { ...this, __internal: { ...stampedInternal, onUpdate: action } };
}
};
if ("autoIncrement" in col) {
stampedCol.autoIncrement = function() {
return { ...this, __internal: { ...stampedInternal, isAutoIncrement: true } };
};
}
if ("defaultNow" in col) {
stampedCol.defaultNow = function() {
return { ...this, __internal: { ...stampedInternal, hasDefaultNow: true } };
};
}
if ("onUpdateTimestamp" in col) {
stampedCol.onUpdateTimestamp = function() {
return { ...this, __internal: { ...stampedInternal, hasOnUpdate: true } };
};
}
converted[key] = stampedCol;
}
return table(tableName, converted, indexFn);
}
var snakeCase = {
table: snakeCaseTable
};
function primaryKey() {
let columns = [];
const builder = {
_type: "primaryKey",
on(...cols) {
columns = cols;
return builder;
},
build() {
if (columns.length === 0) {
throw new Error("primaryKey() has no columns \u2014 call .on() before returning");
}
return { columns: columns.map((c) => c.name) };
}
};
return builder;
}
function index(name) {
let columns = [];
let isUnique = false;
const builder = {
_type: "index",
on(...cols) {
columns = cols;
return builder;
},
unique() {
isUnique = true;
return builder;
},
build() {
if (columns.length === 0) {
throw new Error(`Index "${name}" has no columns \u2014 call .on() before returning`);
}
return {
name,
columns: columns.map((c) => c.name),
unique: isUnique
};
}
};
return builder;
}
export {
text,
table,
snakeCase,
real,
primaryKey,
json,
integer,
index,
date,
boolean
};