Replies: 4 comments
-
I, too, would be interested in how to use lucid outside adonisJS. |
Beta Was this translation helpful? Give feedback.
-
The core of Lucid is decoupled from AdonisJS. However, the commands are not and for that we will have refactor a lot of internals and make sure that we ship commands that can run without relying on I have plans to refactor Lucid internals and make commands agnostic as well. However, all this will be part of my Insiders program. |
Beta Was this translation helpful? Give feedback.
-
#POC using bun needs more testing and improvements! This is just a proof of concept ok! Instal packagesbun add @adonisjs/lucid mysql2 Create files# src/lucid/index.ts
import type { DatabaseConfig } from "@adonisjs/lucid/types/database";
import { Database } from "@adonisjs/lucid/database";
import { BaseModel } from "@adonisjs/lucid/orm";
import { Logger } from "@adonisjs/logger";
import { Emitter } from "./emitter";
import { Adapter } from "./adapter";
export function isObject(value: any) {
return value !== null && typeof value === "object" && !Array.isArray(value);
}
let db: Database;
let logger: Logger;
let emitter: Emitter;
export async function defineConfig(config: DatabaseConfig) {
logger = new Logger({});
emitter = new Emitter();
//@ts-ignore
db = new Database(config, logger, emitter);
BaseModel.$adapter = new Adapter(db);
return new Promise((r) => setTimeout(r, 100));
}
export { db, logger, emitter }; The original "emitter" needs an Application instance! I wrote a fake emitter for this POC! # src/lucid/emitter.ts
export class Emitter {
constructor() {}
onError() {}
listen() {}
on() {}
once() {}
onAny() {}
emit() {}
emitSerial() {}
off() {}
offAny() {}
clearListener() {}
clearListeners() {}
clearAllListeners() {}
listenerCount() {}
hasListeners() {}
fake() {}
restore() {}
} For some reason, I can't import the "Adapter" from "import { Adapter } from '@adonis/src/orm/adapter/index.js'" and that's why I ported the Adapter to this POC! # src/lucid/adapter.ts
import { Exception } from "@poppinss/utils";
import type { QueryClientContract } from "@adonisjs/lucid/types/database";
import { Database } from "@adonisjs/lucid/database";
import type {
AdapterContract,
LucidModel,
LucidRow,
ModelAdapterOptions,
} from "@adonisjs/lucid/types/model";
export function isObject(value: any) {
return value !== null && typeof value === "object" && !Array.isArray(value);
}
export class Adapter implements AdapterContract {
db;
constructor(db: Database) {
this.db = db;
}
getPrimaryKeyColumnName(Model: LucidModel) {
return Model.$keys.attributesToColumns.get(
Model.primaryKey,
Model.primaryKey
);
}
modelConstructorClient(
modelConstructor: LucidModel,
options?: ModelAdapterOptions
): QueryClientContract {
if (options && options.client) {
return options.client;
}
const connection =
(options && options.connection) || modelConstructor.connection;
return this.db.connection(connection);
}
query(modelConstructor: LucidModel, options?: ModelAdapterOptions): any {
const client = this.modelConstructorClient(modelConstructor, options);
return client.modelQuery(modelConstructor);
}
modelClient(instance: LucidRow): any {
const modelConstructor = instance.constructor as LucidModel;
return instance.$trx
? instance.$trx
: this.modelConstructorClient(modelConstructor, instance.$options);
}
async insert(instance: LucidRow, attributes: any): Promise<void> {
const query = instance.$getQueryFor(
"insert",
this.modelClient(instance)
);
const Model = instance.constructor as LucidModel;
const result = await query
.insert(attributes)
.reporterData({ model: Model.name });
if (!Model.selfAssignPrimaryKey && Array.isArray(result) && result[0]) {
if (isObject(result[0])) {
instance.$consumeAdapterResult(result[0]);
} else {
const primaryKeyColumnName =
this.getPrimaryKeyColumnName(Model);
instance.$consumeAdapterResult({
[primaryKeyColumnName]: result[0],
});
}
}
}
async update(instance: LucidRow, dirty: any): Promise<void> {
await instance
.$getQueryFor("update", this.modelClient(instance))
.update(dirty);
}
async delete(instance: LucidRow): Promise<void> {
await instance.$getQueryFor("delete", this.modelClient(instance)).del();
}
async refresh(instance: LucidRow): Promise<void> {
const Model = instance.constructor as LucidModel;
const primaryKeyColumnName = this.getPrimaryKeyColumnName(Model);
const freshModelInstance = await instance
.$getQueryFor("refresh", this.modelClient(instance))
.first();
if (!freshModelInstance) {
throw new Exception(
[
'"Model.refresh" failed. ',
`Unable to lookup "${Model.table}" table where "${primaryKeyColumnName}" = ${instance.$primaryKeyValue}`,
].join("")
);
}
instance.fill(freshModelInstance.$attributes);
instance.$hydrateOriginals();
}
} Create model# src/models/document.ts
import { BaseModel, column } from "@adonisjs/lucid/orm";
export default class Document extends BaseModel {
public static connection = "app";
public static table = "documents";
@column()
declare account: string;
@column()
declare brand: string;
@column()
declare bank: string;
@column()
declare agent: string;
// another columns
@column()
declare synced_at: string;
@column({
consume(value) {
if (typeof value === "object") return value;
return value ? JSON.parse(value) : null;
},
prepare(value) {
return value ? JSON.stringify(value) : null;
},
})
declare service_response: object | string;
} Create index# src/index.ts
import { defineConfig, db } from "./lucid";
import Document from "./models/document";
let DB_APP_HOST = process.env.DB_APP_HOST || "localhost";
let DB_APP_PORT = process.env.DB_APP_PORT || "3306";
let DB_APP_USER = process.env.DB_APP_USER || "none";
let DB_APP_PASS = process.env.DB_APP_PASS || "none";
let DB_APP_BASE = process.env.DB_APP_BASE || "none";
await defineConfig({
connection: "app",
connections: {
app: {
client: "mysql2",
healthCheck: false,
debug: false,
useNullAsDefault: true,
connection: {
host: DB_APP_HOST,
port: parseInt(DB_APP_PORT || "3306"),
user: DB_APP_USER,
password: DB_APP_PASS,
database: DB_APP_BASE,
charset: "utf8mb4",
},
}
},
});
const doc = await Document.first();
console.log({ doc }); Run and praybun run src/index.ts result{
doc: {
account: "...",
brand: "...",
bank: "...",
agent: "...",
syncedAt: 2023-10-01T23:41:28.000Z,
serviceResponse: {...}
}
} |
Beta Was this translation helpful? Give feedback.
-
thanks cgslivre I have created a PR #1030 to export adapter and once it's merged will try to wrap all the functionality as a package for easy usage. |
Beta Was this translation helpful? Give feedback.
-
Hello,
I recently started a personal project from scratch using Express, and I'm in search of a type-safe ORM/query builder. I've been working with Adonis for a few years and really like how Lucid works. I would like to use Lucid in this project.
I was looking at the documentation, and at first, I got the impression that it would be possible, but I got stuck during installation because of Ace. Many of the commands used in configuration and migrations depend on Ace. I searched for a standalone Ace package, but from what I understand, it is part of the core of Adonis.
Is it possible?
Beta Was this translation helpful? Give feedback.
All reactions