DBNova registers some type information with the TypeScript language service of the Monaco editor to provide better code completion and type checking.
The Monaco editor supports only a single global TypeScript language service instance. Since DBNova needs to support SQL, MongoDB, and Redis, interaction logic is implemented in separate entry functions.
mongoshell<IMongoDBTypes>((db) => {
db.status();
db.collection("users").find();
});
redisshell((cli) => {
cli.scan(0).stream();
});
sqlshell<ISQLTypes>((ctx, db) => {
sql`select ${params.int("a")} + ${params.int("b")}`.export(ctx);
// mysql
db.manycols.select({}).export(ctx);
// postgresql
db.public.datatypetest.select({}).export(ctx);
});TIP
Entry functions are automatically populated when opening the editor and do not need to be manually entered.
You can also customize the initial code in the database settings.
TIP
Functions may also be asynchronous.
Defining Parameters
In TypeScript, you can define parameters through methods of the params object.
WARNING
Corresponding type values are not actually returned, so parameters cannot be used for calculations.
// This is incorrect; parameters cannot be directly used in calculations
const pa = params.int("a") * 2;
// Use `valmap` to implement calculations
const pa = params.int("a", { valmap: (v) => v * 2 });For more parameter options, refer to Feats-Params.
MongoDB
declare class MongoDB<T extends Record<string, any>> {
mkcmd(cmd: Record<string, any>, opts?: IMakeCmdOpts): ICommand;
aggregate(pipeline: IDoc[], opts?: IAggregateOptions): ICommand;
collection<K extends keyof T & string>(name: K): MongoCollection<T[K]>;
...
stats(opts?: IDBStatusOptions): ICommand;
}
declare class MongoCollection<T> {
insertOne(doc: T): ICommand;
insertMany(docs: T[], opts?: ICommonOptions): ICommand;
...
dropIndex(name: string): ICommand;
stats(): ICommand;
}Users can also call the db.mkcmd method to register arbitrary commands.
Redis
declare class RedisClient {
mkcmd(cmd: string, ...args: (string | number)[]): ICommand;
bitcount(key: string, opts?: BitCountOptions): ICommand;
...
ping(message?: string): ICommand;
}Users can also call the cli.mkcmd method to register arbitrary commands.
SQL
DBNova has open-sourced its built-in SQL Generator aghsorm,which you can use to generate SQL statements.
Support for user-defined SQL Generators will be added in the future.
sqlshell<IDBTypes>((ctx, db) => {
// raw sql
sql`select ${params.int("a")} + ${params.int("b")}`.export(ctx);
// select
db.article
.select({ id: params.int("id") }, { exclude: ["content"] })
.export(ctx);
// delete
db.article.delete({ id: params.int("id") }).export(ctx);
// insert
db.article
.insert({
id: params.int("id"),
title: params.string("title"),
content: params.string("content"),
})
.export(ctx);
// update
db.article
.update(
{ read_count: db.article.field("read_count").plus(1) },
{ id: params.int("id") },
)
.export(ctx);
});SQL Export
Each SQL statement must explicitly call export(ctx).
For column rendering options, refer to Feats-ColRender.
Database Type Inference
To prevent database lag during index data processing from affecting normal business operations, DBNova's indexing is manual. Currently, this feature supports SQL and MongoDB.
All field names that do not comply with JavaScript variable name rules will be converted to valid names.
MongoDB
Use collection.aggregate([{$sample: {size: 50}}]) to obtain sample documents; you can change the sample size in the settings.
For heterogeneous fields, a union based on first-level fields is generated. For example:
[
{ a: 1, b: { c: 122 } },
{ a: 2, b: { d: false } },
];
// The following types will be generated:
// The names of these sub-types are currently meaningless hashes
interface Ixxxxxxxxxxxxxxxx {
c: number;
}
interface Iyyyyyyyyyyyyyyyy {
d: boolean;
}
interface ICollection {
a: number;
b: Ixxxxxxxxxxxxxxxx | Iyyyyyyyyyyyyyyyy;
}For method calls such as find and updateOne, corresponding field prompts and checks are provided. (However, this is far less robust than VSCode; improvements may be made through a separately implemented LSP in the future.)
SQL
Special type conversions:
- 64-bit and larger integer types are inferred as
bigint. - decimal types are inferred as
Decimal. - Time-related types are inferred as
Date. - Binary types are inferred as
Binary.
Schema concepts in databases such as PostgreSQL are also supported, with each schema being a separate namespace.
Additional TypeScript Types and APIs
declare class Base64 {
static encode(input: Uint8Array): string;
static decode(input: string): Uint8Array;
}
declare interface IHTTPOptions {
query?: { [k: string]: string[] | string };
headers?: { [k: string]: string[] | string };
body?: ["file", string] | Uint8Array | string | any;
timeouts?: number;
proxy?: "app" | string;
}
declare interface IHttpResponse {
code: number;
message: string;
headers: { [k: string]: string[] };
body: Uint8Array;
json<T>(): T;
text(): string;
}
declare function http(
method: "get" | "post" | "put" | "head" | "delete" | "options" | "patch",
url: string,
opts?: IHTTPOptions,
): Promise<IHttpResponse>;
declare namespace bson {
class ObjectID {}
class Long {}
class Timestamp {}
class UUID {}
class Decimal128 {}
class Binary {}
class MinKey {}
class MaxKey {}
}
declare const Binary: typeof bson.Binary;
declare const Decimal: typeof bson.Decimal128;