@lucidcms/core
Version:
The core of the Lucid CMS. It's responsible for spinning up the API and serving the CMS.
596 lines (580 loc) • 22.5 kB
JavaScript
import {
logging_default,
lucid_error_default,
translations_default
} from "./chunk-ZMWDUGJW.js";
// src/libs/db/adapters/postgres/index.ts
import pg from "pg";
import { PostgresDialect } from "kysely";
// src/libs/db/adapter.ts
import {
Kysely,
Migrator
} from "kysely";
import { jsonArrayFrom } from "kysely/helpers/sqlite";
// src/libs/db/migrations/00000001-locales.ts
import { sql as sql2 } from "kysely";
// src/libs/db/kysely/column-helpers.ts
import { sql } from "kysely";
var defaultTimestamp = (col, adapter) => {
switch (adapter) {
case 0 /* SQLITE */:
return col.defaultTo(sql`CURRENT_TIMESTAMP`);
case 1 /* POSTGRES */:
return col.defaultTo(sql`NOW()`);
case 2 /* LIBSQL */:
return col.defaultTo(sql`CURRENT_TIMESTAMP`);
}
};
var primaryKeyColumnType = (adapter) => {
switch (adapter) {
case 0 /* SQLITE */:
return "integer";
case 1 /* POSTGRES */:
return "serial";
case 2 /* LIBSQL */:
return "integer";
}
};
var primaryKeyColumn = (col, adapter) => {
switch (adapter) {
case 0 /* SQLITE */:
return col.primaryKey().autoIncrement();
case 1 /* POSTGRES */:
return col.primaryKey();
case 2 /* LIBSQL */:
return col.primaryKey().autoIncrement();
}
};
// src/libs/db/migrations/00000001-locales.ts
var Migration00000001 = (adapter) => {
return {
async up(db) {
if (adapter === 1 /* POSTGRES */) {
await sql2`CREATE EXTENSION IF NOT EXISTS pg_trgm`.execute(db);
}
await db.schema.createTable("lucid_locales").addColumn("code", "text", (col) => col.primaryKey()).addColumn("is_deleted", "integer", (col) => col.defaultTo(0)).addColumn("is_deleted_at", "timestamp", (col) => col.defaultTo(null)).addColumn(
"created_at",
"timestamp",
(col) => defaultTimestamp(col, adapter)
).addColumn(
"updated_at",
"timestamp",
(col) => defaultTimestamp(col, adapter)
).execute();
},
async down(db) {
}
};
};
var locales_default = Migration00000001;
// src/libs/db/migrations/00000002-translations.ts
var Migration00000002 = (adapter) => {
return {
async up(db) {
await db.schema.createTable("lucid_translation_keys").addColumn(
"id",
primaryKeyColumnType(adapter),
(col) => primaryKeyColumn(col, adapter)
).addColumn("created_at", "timestamp", (col) => col.notNull()).execute();
await db.schema.createTable("lucid_translations").addColumn(
"id",
primaryKeyColumnType(adapter),
(col) => primaryKeyColumn(col, adapter)
).addColumn(
"translation_key_id",
"integer",
(col) => col.references("lucid_translation_keys.id").notNull().onDelete("cascade").onUpdate("cascade")
).addColumn(
"locale_code",
"text",
(col) => col.references("lucid_locales.code").notNull().onDelete("cascade").onUpdate("cascade")
).addColumn("value", "text").addUniqueConstraint(
"lucid_translations_translation_key_id_locale_code_unique",
["translation_key_id", "locale_code"]
).execute();
await db.schema.createIndex("idx_translation_key_locale").on("lucid_translations").columns(["translation_key_id", "locale_code"]).execute();
},
async down(db) {
}
};
};
var translations_default2 = Migration00000002;
// src/libs/db/migrations/00000003-options.ts
var Migration00000003 = (adapter) => {
return {
async up(db) {
await db.schema.createTable("lucid_options").addColumn("name", "text", (col) => col.unique().notNull().primaryKey()).addColumn("value_int", "integer").addColumn("value_text", "text").addColumn("value_bool", "integer").execute();
},
async down(db) {
}
};
};
var options_default = Migration00000003;
// src/libs/db/migrations/00000004-users-and-permissions.ts
var Migration00000004 = (adapter) => {
return {
async up(db) {
await db.schema.createTable("lucid_users").addColumn(
"id",
primaryKeyColumnType(adapter),
(col) => primaryKeyColumn(col, adapter)
).addColumn(
"super_admin",
"integer",
(col) => col.defaultTo(0).notNull()
).addColumn("email", "text", (col) => col.notNull().unique()).addColumn("username", "text", (col) => col.notNull().unique()).addColumn("first_name", "text").addColumn("last_name", "text").addColumn("password", "text").addColumn("secret", "text", (col) => col.notNull()).addColumn(
"triggered_password_reset",
"integer",
(col) => col.defaultTo(0)
).addColumn("is_deleted", "integer", (col) => col.defaultTo(0)).addColumn("is_deleted_at", "timestamp").addColumn(
"deleted_by",
"integer",
(col) => col.references("lucid_users.id").onDelete("set null")
).addColumn(
"created_at",
"timestamp",
(col) => defaultTimestamp(col, adapter)
).addColumn(
"updated_at",
"timestamp",
(col) => defaultTimestamp(col, adapter)
).execute();
await db.schema.createTable("lucid_roles").addColumn(
"id",
primaryKeyColumnType(adapter),
(col) => primaryKeyColumn(col, adapter)
).addColumn("name", "text", (col) => col.notNull().unique()).addColumn("description", "text").addColumn(
"created_at",
"timestamp",
(col) => defaultTimestamp(col, adapter)
).addColumn(
"updated_at",
"timestamp",
(col) => defaultTimestamp(col, adapter)
).execute();
await db.schema.createTable("lucid_role_permissions").addColumn(
"id",
primaryKeyColumnType(adapter),
(col) => primaryKeyColumn(col, adapter)
).addColumn(
"role_id",
"integer",
(col) => col.references("lucid_roles.id").onDelete("cascade")
).addColumn("permission", "text", (col) => col.notNull()).addColumn(
"created_at",
"timestamp",
(col) => defaultTimestamp(col, adapter)
).addColumn(
"updated_at",
"timestamp",
(col) => defaultTimestamp(col, adapter)
).execute();
await db.schema.createTable("lucid_user_roles").addColumn(
"id",
primaryKeyColumnType(adapter),
(col) => primaryKeyColumn(col, adapter)
).addColumn(
"user_id",
"integer",
(col) => col.references("lucid_users.id").onDelete("cascade")
).addColumn(
"role_id",
"integer",
(col) => col.references("lucid_roles.id").onDelete("cascade")
).addColumn(
"created_at",
"timestamp",
(col) => defaultTimestamp(col, adapter)
).addColumn(
"updated_at",
"timestamp",
(col) => defaultTimestamp(col, adapter)
).execute();
await db.schema.createTable("lucid_user_tokens").addColumn(
"id",
primaryKeyColumnType(adapter),
(col) => primaryKeyColumn(col, adapter)
).addColumn(
"user_id",
"integer",
(col) => col.references("lucid_users.id").onDelete("cascade")
).addColumn("token_type", "varchar(255)").addColumn("token", "varchar(255)", (col) => col.notNull().unique()).addColumn(
"created_at",
"timestamp",
(col) => defaultTimestamp(col, adapter)
).addColumn("expiry_date", "timestamp", (col) => col.notNull()).execute();
},
async down(db) {
}
};
};
var users_and_permissions_default = Migration00000004;
// src/libs/db/migrations/00000005-emails.ts
var Migration00000005 = (adapter) => {
return {
async up(db) {
await db.schema.createTable("lucid_emails").addColumn(
"id",
primaryKeyColumnType(adapter),
(col) => primaryKeyColumn(col, adapter)
).addColumn("email_hash", "char(64)", (col) => col.unique().notNull()).addColumn("from_address", "text", (col) => col.notNull()).addColumn("from_name", "text", (col) => col.notNull()).addColumn("to_address", "text", (col) => col.notNull()).addColumn("subject", "text", (col) => col.notNull()).addColumn("cc", "text").addColumn("bcc", "text").addColumn("delivery_status", "text", (col) => col.notNull()).addColumn("template", "text", (col) => col.notNull()).addColumn("data", "text").addColumn("type", "text", (col) => col.notNull()).addColumn("sent_count", "integer", (col) => col.notNull().defaultTo(0)).addColumn(
"error_count",
"integer",
(col) => col.notNull().defaultTo(0)
).addColumn("last_error_message", "text").addColumn(
"last_attempt_at",
"timestamp",
(col) => defaultTimestamp(col, adapter)
).addColumn("last_success_at", "timestamp").addColumn(
"created_at",
"timestamp",
(col) => defaultTimestamp(col, adapter)
).execute();
},
async down(db) {
}
};
};
var emails_default = Migration00000005;
// src/libs/db/migrations/00000006-media.ts
var Migration00000006 = (adapter) => {
return {
async up(db) {
await db.schema.createTable("lucid_media").addColumn(
"id",
primaryKeyColumnType(adapter),
(col) => primaryKeyColumn(col, adapter)
).addColumn("key", "text", (col) => col.unique().notNull()).addColumn("e_tag", "text").addColumn("visible", "integer", (col) => col.notNull().defaultTo(1)).addColumn("type", "text", (col) => col.notNull()).addColumn("mime_type", "text", (col) => col.notNull()).addColumn("file_extension", "text", (col) => col.notNull()).addColumn("file_size", "integer", (col) => col.notNull()).addColumn("width", "integer").addColumn("height", "integer").addColumn("blur_hash", "text").addColumn("average_colour", "text").addColumn("is_dark", "integer").addColumn("is_light", "integer").addColumn(
"title_translation_key_id",
"integer",
(col) => col.references("lucid_translation_keys.id").onDelete("set null").onUpdate("cascade")
).addColumn(
"alt_translation_key_id",
"integer",
(col) => col.references("lucid_translation_keys.id").onDelete("set null").onUpdate("cascade")
).addColumn("custom_meta", "text").addColumn(
"created_at",
"timestamp",
(col) => defaultTimestamp(col, adapter)
).addColumn(
"updated_at",
"timestamp",
(col) => defaultTimestamp(col, adapter)
).execute();
await db.schema.createIndex("idx_lucid_media_key").on("lucid_media").column("key").execute();
await db.schema.createTable("lucid_media_awaiting_sync").addColumn("key", "text", (col) => col.primaryKey()).addColumn("timestamp", "timestamp", (col) => col.notNull()).execute();
await db.schema.createTable("lucid_processed_images").addColumn("key", "text", (col) => col.primaryKey()).addColumn(
"media_key",
"text",
(col) => col.references("lucid_media.key").onDelete("cascade").onUpdate("cascade")
).addColumn("file_size", "integer", (col) => col.notNull()).execute();
await db.schema.createIndex("idx_processed_images_media_key").on("lucid_processed_images").column("media_key").execute();
},
async down(db) {
}
};
};
var media_default = Migration00000006;
// src/libs/db/migrations/00000007-collections.ts
var Migration00000007 = (adapter) => {
return {
async up(db) {
await db.schema.createTable("lucid_collection_documents").addColumn(
"id",
primaryKeyColumnType(adapter),
(col) => primaryKeyColumn(col, adapter)
).addColumn("collection_key", "text", (col) => col.notNull()).addColumn("is_deleted", "integer", (col) => col.defaultTo(0)).addColumn("is_deleted_at", "timestamp").addColumn(
"deleted_by",
"integer",
(col) => col.references("lucid_users.id").onDelete("set null")
).addColumn(
"created_by",
"integer",
(col) => col.references("lucid_users.id").onDelete("set null")
).addColumn(
"updated_by",
"integer",
(col) => col.references("lucid_users.id").onDelete("set null")
).addColumn(
"created_at",
"timestamp",
(col) => defaultTimestamp(col, adapter)
).addColumn(
"updated_at",
"timestamp",
(col) => defaultTimestamp(col, adapter)
).execute();
await db.schema.createTable("lucid_collection_document_versions").addColumn(
"id",
primaryKeyColumnType(adapter),
(col) => primaryKeyColumn(col, adapter)
).addColumn(
"document_id",
"integer",
(col) => col.references("lucid_collection_documents.id").onDelete("cascade").notNull()
).addColumn("version_type", "text", (col) => col.notNull()).addColumn(
"promoted_from",
"integer",
(col) => col.references("lucid_collection_document_versions.id").onDelete("set null")
).addColumn(
"created_at",
"timestamp",
(col) => defaultTimestamp(col, adapter)
).addColumn(
"created_by",
"integer",
(col) => col.references("lucid_users.id").onDelete("set null")
).execute();
await db.schema.createIndex("idx_document_versions_document_id").on("lucid_collection_document_versions").column("document_id").execute();
await db.schema.createTable("lucid_collection_document_bricks").addColumn(
"id",
primaryKeyColumnType(adapter),
(col) => primaryKeyColumn(col, adapter)
).addColumn(
"collection_document_version_id",
"integer",
(col) => col.references("lucid_collection_document_versions.id").onDelete("cascade").notNull()
).addColumn("brick_type", "text", (col) => col.notNull()).addColumn("brick_key", "text").addColumn("brick_order", "integer").addColumn("brick_open", "integer", (col) => col.defaultTo(0)).execute();
await db.schema.createTable("lucid_collection_document_groups").addColumn(
"group_id",
primaryKeyColumnType(adapter),
(col) => primaryKeyColumn(col, adapter)
).addColumn(
"collection_document_version_id",
"integer",
(col) => col.references("lucid_collection_document_versions.id").onDelete("cascade").notNull()
).addColumn(
"collection_document_id",
"integer",
(col) => col.references("lucid_collection_documents.id").onDelete("cascade").notNull()
).addColumn(
"collection_brick_id",
"integer",
(col) => col.references("lucid_collection_document_bricks.id").onDelete("cascade").notNull()
).addColumn(
"parent_group_id",
"integer",
(col) => col.references("lucid_collection_document_groups.group_id").onDelete("cascade")
).addColumn("group_open", "integer", (col) => col.defaultTo(0)).addColumn("repeater_key", "text", (col) => col.notNull()).addColumn("group_order", "integer", (col) => col.notNull()).addColumn("ref", "text").execute();
await db.schema.createIndex("idx_lucid_groups_collection_brick_id").on("lucid_collection_document_groups").column("collection_brick_id").execute();
await db.schema.createIndex("idx_lucid_groups_parent_group_id").on("lucid_collection_document_groups").column("parent_group_id").execute();
await db.schema.createTable("lucid_collection_document_fields").addColumn(
"fields_id",
primaryKeyColumnType(adapter),
(col) => primaryKeyColumn(col, adapter)
).addColumn(
"collection_document_version_id",
"integer",
(col) => col.references("lucid_collection_document_versions.id").onDelete("cascade").notNull()
).addColumn(
"collection_document_id",
"integer",
(col) => col.references("lucid_collection_documents.id").onDelete("cascade").notNull()
).addColumn(
"collection_brick_id",
"integer",
(col) => col.references("lucid_collection_document_bricks.id").onDelete("cascade").notNull()
).addColumn(
"group_id",
"integer",
(col) => col.references("lucid_collection_document_groups.group_id").onDelete("cascade")
).addColumn(
"locale_code",
"text",
(col) => col.references("lucid_locales.code").onDelete("cascade").notNull()
).addColumn("key", "text", (col) => col.notNull()).addColumn("type", "text", (col) => col.notNull()).addColumn("text_value", "text").addColumn("int_value", "integer").addColumn("bool_value", "integer").addColumn("json_value", "text").addColumn(
"media_id",
"integer",
(col) => col.references("lucid_media.id").onDelete("set null")
).addColumn(
"document_id",
"integer",
(col) => col.references("lucid_collection_documents.id").onDelete("set null")
).addColumn(
"user_id",
"integer",
(col) => col.references("lucid_users.id").onDelete("set null")
).execute();
await db.schema.createIndex("idx_lucid_fields_locale_code").on("lucid_collection_document_fields").column("locale_code").execute();
await db.schema.createIndex("idx_lucid_fields_collection_brick_id").on("lucid_collection_document_fields").column("collection_brick_id").execute();
await db.schema.createIndex("idx_lucid_fields_group_id").on("lucid_collection_document_fields").column("group_id").execute();
},
async down(_db) {
}
};
};
var collections_default = Migration00000007;
// src/libs/db/migrations/00000008-integrations.ts
var Migration00000008 = (adapter) => {
return {
async up(db) {
await db.schema.createTable("lucid_client_integrations").addColumn(
"id",
primaryKeyColumnType(adapter),
(col) => primaryKeyColumn(col, adapter)
).addColumn("name", "text", (col) => col.notNull()).addColumn("description", "text").addColumn("enabled", "integer", (col) => col.notNull()).addColumn("key", "text", (col) => col.notNull().unique()).addColumn("api_key", "text", (col) => col.notNull()).addColumn("secret", "text", (col) => col.notNull()).addColumn(
"created_at",
"timestamp",
(col) => defaultTimestamp(col, adapter)
).addColumn(
"updated_at",
"timestamp",
(col) => defaultTimestamp(col, adapter)
).execute();
await db.schema.createIndex("idx_lucid_client_integrations_key").on("lucid_client_integrations").column("key").execute();
await db.schema.createIndex("idx_lucid_client_integrations_api_key").on("lucid_client_integrations").column("api_key").execute();
await db.schema.createIndex("idx_lucid_client_integrations_secret").on("lucid_client_integrations").column("secret").execute();
},
async down(db) {
}
};
};
var integrations_default = Migration00000008;
// src/libs/db/adapter.ts
var DatabaseAdapter = class {
db;
adapter;
constructor(config) {
this.adapter = config.adapter;
this.db = new Kysely({
dialect: config.dialect,
plugins: config.plugins
});
}
// Public methods
async migrateToLatest() {
const migrator = this.migrator;
const { error, results } = await migrator.migrateToLatest();
if (results) {
for (const it of results) {
if (it.status === "Success") {
logging_default("info", {
message: `"${it.migrationName}" was executed successfully`,
scope: "migration"
});
} else if (it.status === "Error") {
logging_default("error", {
message: `failed to execute migration "${it.migrationName}"`,
scope: "migration"
});
}
}
}
if (error) {
throw new lucid_error_default({
// @ts-expect-error
message: error?.message || translations_default("db_migration_failed"),
// @ts-expect-error
data: error.errors,
kill: true
});
}
}
// getters
get client() {
if (!this.db) {
throw new lucid_error_default({
message: translations_default("db_connection_error")
});
}
return this.db;
}
get jsonArrayFrom() {
return jsonArrayFrom;
}
get fuzzOperator() {
return "like";
}
get migrations() {
return {
"00000001-locales": locales_default(this.adapter),
"00000002-translations": translations_default2(this.adapter),
"00000003-options": options_default(this.adapter),
"00000004-users-and-permissions": users_and_permissions_default(this.adapter),
"00000005-emails": emails_default(this.adapter),
"00000006-media": media_default(this.adapter),
"00000007-collections": collections_default(this.adapter),
"00000008-integrations": integrations_default(this.adapter)
};
}
get migrator() {
const m = this.migrations;
return new Migrator({
db: this.client,
provider: {
async getMigrations() {
return m;
}
}
});
}
};
// src/libs/db/adapters/postgres/index.ts
import { jsonArrayFrom as jsonArrayFrom2 } from "kysely/helpers/postgres";
var { Pool } = pg;
var PostgresAdapter = class extends DatabaseAdapter {
constructor(config) {
super({
adapter: 1 /* POSTGRES */,
dialect: new PostgresDialect({
pool: new Pool(config)
})
});
}
// Getters
get jsonArrayFrom() {
return jsonArrayFrom2;
}
get fuzzOperator() {
return "%";
}
};
// src/libs/db/adapters/libsql/index.ts
import { LibsqlDialect } from "@libsql/kysely-libsql";
import { ParseJSONResultsPlugin } from "kysely";
import { jsonArrayFrom as jsonArrayFrom3 } from "kysely/helpers/sqlite";
var LibsqlAdapter = class extends DatabaseAdapter {
constructor(config) {
super({
adapter: 2 /* LIBSQL */,
dialect: new LibsqlDialect(config),
plugins: [new ParseJSONResultsPlugin()]
});
}
// Getters
get jsonArrayFrom() {
return jsonArrayFrom3;
}
get fuzzOperator() {
return "like";
}
};
// src/libs/db/adapters/sqlite/index.ts
import {
SqliteDialect,
ParseJSONResultsPlugin as ParseJSONResultsPlugin2
} from "kysely";
import { jsonArrayFrom as jsonArrayFrom4 } from "kysely/helpers/sqlite";
var SqliteAdapter = class extends DatabaseAdapter {
constructor(config) {
super({
adapter: 0 /* SQLITE */,
dialect: new SqliteDialect(config),
plugins: [new ParseJSONResultsPlugin2()]
});
}
// Getters
get jsonArrayFrom() {
return jsonArrayFrom4;
}
get fuzzOperator() {
return "like";
}
};
export {
LibsqlAdapter as LibSQLAdapter,
PostgresAdapter,
SqliteAdapter as SQLiteAdapter
};
//# sourceMappingURL=adapters.js.map