prepare for client/server split

This commit is contained in:
Morten Olsen
2024-12-11 12:32:23 +01:00
parent 02614d216c
commit 99248e98b5
51 changed files with 409 additions and 1500 deletions

View File

@@ -6,6 +6,17 @@
"files": [
"dist"
],
"exports": {
".": {
"import": "./dist/exports.js"
},
"./manifest": {
"import": "./dist/manifest.js"
},
"./plugin": {
"import": "./dist/plugin.js"
}
},
"scripts": {
"build": "tsc --build"
},

View File

@@ -1,89 +0,0 @@
import { createActionApiRoute, type Database, Plugin, z } from '@plainidx/plainidx';
import { migrations } from './migrations/migrations.js';
class CorePlugin extends Plugin {
#db?: Promise<Database>;
public readonly name = '@builtin/core';
public actions = {
setTags: createActionApiRoute({
input: z.object({
document: z.string(),
tags: z.array(z.string()),
}),
output: z.undefined(),
handle: async ({ document, tags }) => {
await this.setTags(document, tags);
return undefined;
},
}),
getTags: createActionApiRoute({
output: z.array(
z.object({
name: z.string(),
count: z.number(),
}),
),
handle: async () => {
return this.getTags();
},
}),
setTitle: createActionApiRoute({
input: z.object({
document: z.string(),
title: z.string(),
}),
output: z.undefined(),
handle: async ({ document, title }) => {
await this.setTitle(document, title);
return undefined;
},
}),
getTitles: createActionApiRoute({
output: z.array(
z.object({
document: z.string(),
title: z.string(),
}),
),
handle: async () => {
return this.getTitles();
},
}),
};
#getDatabase = async () => {
if (!this.#db) {
this.#db = this.getDB('data', migrations);
}
return this.#db;
};
public getTags = async () => {
const db = await this.#getDatabase();
return db('tags')
.select([db.raw('tag as name'), db.raw('count(document) as count')])
.groupBy('tag');
};
public setTags = async (document: string, tags: string[]) => {
const db = await this.#getDatabase();
await db('tags').where({ document }).delete();
if (tags.length) {
await db('tags').insert(tags.map((tag) => ({ tag, document })));
}
};
public setTitle = async (document: string, title: string) => {
const db = await this.#getDatabase();
await db('titles').where({ document }).insert({ document, title }).onConflict('document').merge();
};
public getTitles = async () => {
const db = await this.#getDatabase();
return await db('titles').select('*');
};
}
export { CorePlugin };

View File

@@ -1 +1,2 @@
export { CorePlugin } from './core.js';
export { core } from './plugin.js';
export { CorePlugin } from './manifest.js';

View File

@@ -0,0 +1,31 @@
import { Manifest, z } from '@plainidx/plainidx';
const CorePlugin = {
id: 'buildin-core',
name: 'Core Plugin',
version: '0.0.1',
config: z.any(),
backend: {
main: './dist/plugin.js',
actions: {
getTitles: {
input: z.object({}),
output: z.array(z.object({ location: z.string(), title: z.string() })),
},
getTags: {
input: z.object({}),
output: z.array(z.string()),
},
setData: {
input: z.object({
location: z.string(),
title: z.string(),
tags: z.array(z.string()),
}),
output: z.any(),
},
},
},
} satisfies Manifest;
export { CorePlugin };

View File

@@ -5,15 +5,15 @@ const migrations: DatabaseMigration[] = [
name: 'init',
up: async (db) => {
await db.schema.createTable('tags', (table) => {
table.string('tag').notNullable();
table.string('document').notNullable();
table.primary(['tag', 'document']);
table.index('document');
table.index('tag');
table.string('name').notNullable();
table.string('location').notNullable();
table.primary(['name', 'location']);
table.index('location');
table.index('name');
});
await db.schema.createTable('titles', (table) => {
table.string('document').primary().notNullable();
table.string('location').primary().notNullable();
table.string('title').notNullable();
});
},

View File

@@ -0,0 +1,39 @@
import { createPlugin } from '@plainidx/plainidx';
import { CorePlugin } from './manifest.js';
import { migrations } from './migrations/migrations.js';
const core = createPlugin(CorePlugin, ({ getDb }) => {
const dbPromise = getDb('data', migrations);
return {
backend: true,
actions: {
getTitles: async () => {
const db = await dbPromise;
const results = await db('titles').select(['location', 'title']);
return results;
},
getTags: async () => {
const db = await dbPromise;
const results = await db('tags')
.select(['name', db.raw('count(*) as count')])
.groupBy('name');
return results;
},
setData: async ({ location, title, tags }) => {
const db = await dbPromise;
const currentTitle = await db('titles').select('title').where({ location }).first();
await db.transaction(async (trx) => {
await trx('tags').delete().where({ location });
await trx('tags').insert(tags.map((tag) => ({ name: tag, location })));
if (currentTitle) {
await trx('titles').update({ title }).where({ location });
} else {
await trx('titles').insert({ location, title });
}
});
},
},
};
});
export { core };