Changed how data is stored quite a bit with nice query capabilities
This commit is contained in:
@@ -93,19 +93,19 @@ test("Run a Node sandbox", async () => {
|
||||
await plug.invoke("errorOut", []);
|
||||
expect(true).toBe(false);
|
||||
} catch (e: any) {
|
||||
expect(e.message).toBe("BOOM");
|
||||
expect(e.message).toContain("BOOM");
|
||||
}
|
||||
try {
|
||||
await plug.invoke("errorOutSys", []);
|
||||
expect(true).toBe(false);
|
||||
} catch (e: any) {
|
||||
expect(e.message).toBe("#fail");
|
||||
expect(e.message).toContain("#fail");
|
||||
}
|
||||
try {
|
||||
await plug.invoke("restrictedTest", []);
|
||||
expect(true).toBe(false);
|
||||
} catch (e: any) {
|
||||
expect(e.message).toBe(
|
||||
expect(e.message).toContain(
|
||||
"Missing permission 'restricted' for syscall restrictedSyscall"
|
||||
);
|
||||
}
|
||||
|
||||
@@ -15,7 +15,8 @@ test("Test store", async () => {
|
||||
});
|
||||
await ensureTable(db, "test_table");
|
||||
let system = new System("server");
|
||||
system.registerSyscalls([], storeSyscalls(db, "test_table"));
|
||||
let syscalls = storeSyscalls(db, "test_table");
|
||||
system.registerSyscalls([], syscalls);
|
||||
let plug = await system.load(
|
||||
{
|
||||
name: "test",
|
||||
@@ -36,5 +37,79 @@ test("Test store", async () => {
|
||||
);
|
||||
expect(await plug.invoke("test1", [])).toBe("Pete");
|
||||
await system.unloadAll();
|
||||
|
||||
let dummyCtx: any = {};
|
||||
|
||||
await syscalls["store.deleteAll"](dummyCtx);
|
||||
await syscalls["store.batchSet"](dummyCtx, [
|
||||
{
|
||||
key: "pete",
|
||||
value: {
|
||||
age: 20,
|
||||
firstName: "Pete",
|
||||
lastName: "Roberts",
|
||||
},
|
||||
},
|
||||
{
|
||||
key: "petejr",
|
||||
value: {
|
||||
age: 8,
|
||||
firstName: "Pete Jr",
|
||||
lastName: "Roberts",
|
||||
},
|
||||
},
|
||||
{
|
||||
key: "petesr",
|
||||
value: {
|
||||
age: 78,
|
||||
firstName: "Pete Sr",
|
||||
lastName: "Roberts",
|
||||
},
|
||||
},
|
||||
]);
|
||||
|
||||
let allRoberts = await syscalls["store.query"](dummyCtx, {
|
||||
filter: [{ op: "=", prop: "lastName", value: "Roberts" }],
|
||||
orderBy: "age",
|
||||
orderDesc: true,
|
||||
});
|
||||
|
||||
expect(allRoberts.length).toBe(3);
|
||||
expect(allRoberts[0].key).toBe("petesr");
|
||||
|
||||
allRoberts = await syscalls["store.query"](dummyCtx, {
|
||||
filter: [{ op: "=", prop: "lastName", value: "Roberts" }],
|
||||
orderBy: "age",
|
||||
limit: 1,
|
||||
});
|
||||
|
||||
expect(allRoberts.length).toBe(1);
|
||||
expect(allRoberts[0].key).toBe("petejr");
|
||||
|
||||
allRoberts = await syscalls["store.query"](dummyCtx, {
|
||||
filter: [
|
||||
{ op: ">", prop: "age", value: 10 },
|
||||
{ op: "<", prop: "age", value: 30 },
|
||||
],
|
||||
orderBy: "age",
|
||||
});
|
||||
|
||||
expect(allRoberts.length).toBe(1);
|
||||
expect(allRoberts[0].key).toBe("pete");
|
||||
|
||||
// Delete the middle one
|
||||
|
||||
await syscalls["store.deleteQuery"](dummyCtx, {
|
||||
filter: [
|
||||
{ op: ">", prop: "age", value: 10 },
|
||||
{ op: "<", prop: "age", value: 30 },
|
||||
],
|
||||
});
|
||||
|
||||
allRoberts = await syscalls["store.query"](dummyCtx, {});
|
||||
expect(allRoberts.length).toBe(2);
|
||||
|
||||
await db.destroy();
|
||||
|
||||
await fs.unlink("test.db");
|
||||
});
|
||||
|
||||
@@ -24,6 +24,45 @@ export async function ensureTable(db: Knex<any, unknown>, tableName: string) {
|
||||
}
|
||||
}
|
||||
|
||||
export type Query = {
|
||||
filter?: Filter[];
|
||||
orderBy?: string;
|
||||
orderDesc?: boolean;
|
||||
limit?: number;
|
||||
select?: string[];
|
||||
};
|
||||
|
||||
export type Filter = {
|
||||
op: string;
|
||||
prop: string;
|
||||
value: any;
|
||||
};
|
||||
|
||||
export function queryToKnex(
|
||||
queryBuilder: Knex.QueryBuilder<Item, any>,
|
||||
query: Query
|
||||
): Knex.QueryBuilder<Item, any> {
|
||||
if (query.filter) {
|
||||
for (let filter of query.filter) {
|
||||
queryBuilder = queryBuilder.andWhereRaw(
|
||||
`json_extract(value, '$.${filter.prop}') ${filter.op} ?`,
|
||||
[filter.value]
|
||||
);
|
||||
}
|
||||
}
|
||||
if (query.limit) {
|
||||
queryBuilder = queryBuilder.limit(query.limit);
|
||||
}
|
||||
if (query.orderBy) {
|
||||
queryBuilder = queryBuilder.orderByRaw(
|
||||
`json_extract(value, '$.${query.orderBy}') ${
|
||||
query.orderDesc ? "desc" : "asc"
|
||||
}`
|
||||
);
|
||||
}
|
||||
return queryBuilder;
|
||||
}
|
||||
|
||||
export function storeSyscalls(
|
||||
db: Knex<any, unknown>,
|
||||
tableName: string
|
||||
@@ -35,6 +74,9 @@ export function storeSyscalls(
|
||||
"store.deletePrefix": async (ctx, prefix: string) => {
|
||||
return db<Item>(tableName).andWhereLike("key", `${prefix}%`).del();
|
||||
},
|
||||
"store.deleteQuery": async (ctx, query: Query) => {
|
||||
await queryToKnex(db<Item>(tableName), query).del();
|
||||
},
|
||||
"store.deleteAll": async (ctx) => {
|
||||
await db<Item>(tableName).del();
|
||||
},
|
||||
@@ -78,6 +120,14 @@ export function storeSyscalls(
|
||||
value: JSON.parse(value),
|
||||
}));
|
||||
},
|
||||
"store.query": async (ctx, query: Query) => {
|
||||
return (
|
||||
await queryToKnex(db<Item>(tableName), query).select("key", "value")
|
||||
).map(({ key, value }: { key: string; value: string }) => ({
|
||||
key,
|
||||
value: JSON.parse(value),
|
||||
}));
|
||||
},
|
||||
};
|
||||
return apiObj;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user