feat: deno-first storage package with sqlite host and graph schemas
Scaffolded @alkdev/storage from @ade/storage_sqlite and @ade/core/graphs: - graphs/ module: TypeBox schema types + SchemaBuilder (from @ade/core/graphs) - sqlite/ module: Drizzle table defs, relations, injectable client (from @ade/storage_sqlite) - pg/ module: placeholder for Postgres host - deno.json configured for JSR with subpath exports (./graphs, ./sqlite, ./pg) - Imports swapped: @sinclair/typebox → @alkdev/typebox, drizzle-typebox → @alkdev/drizzlebox - Client is now injectable (no hardcoded env vars or module-level side effects) - no-slow-types lint excluded (Drizzle generics); --allow-slow-types on publish
This commit is contained in:
3
.gitignore
vendored
Normal file
3
.gitignore
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
node_modules/
|
||||
deno.lock
|
||||
.npmrc
|
||||
33
deno.json
Normal file
33
deno.json
Normal file
@@ -0,0 +1,33 @@
|
||||
{
|
||||
"name": "@alkdev/storage",
|
||||
"version": "0.1.0",
|
||||
"license": "MIT",
|
||||
"exports": {
|
||||
".": "./mod.ts",
|
||||
"./graphs": "./src/graphs/mod.ts",
|
||||
"./sqlite": "./src/sqlite/mod.ts",
|
||||
"./pg": "./src/pg/mod.ts"
|
||||
},
|
||||
"imports": {
|
||||
"@alkdev/typebox": "npm:@alkdev/typebox",
|
||||
"@alkdev/drizzlebox": "npm:@alkdev/drizzlebox",
|
||||
"drizzle-orm": "npm:drizzle-orm",
|
||||
"drizzle-orm/sqlite-core": "npm:drizzle-orm/sqlite-core",
|
||||
"drizzle-orm/pg-core": "npm:drizzle-orm/pg-core",
|
||||
"@libsql/client": "npm:@libsql/client",
|
||||
"postgres": "npm:postgres",
|
||||
"@std/assert": "jsr:@std/assert"
|
||||
},
|
||||
"lint": {
|
||||
"rules": {
|
||||
"exclude": ["no-slow-types"]
|
||||
}
|
||||
},
|
||||
"tasks": {
|
||||
"check": "deno check mod.ts src/graphs/mod.ts src/sqlite/mod.ts",
|
||||
"test": "deno test --allow-all test/",
|
||||
"lint": "deno lint",
|
||||
"fmt": "deno fmt",
|
||||
"publish:dry": "deno publish --allow-slow-types --dry-run"
|
||||
}
|
||||
}
|
||||
2
src/graphs/mod.ts
Normal file
2
src/graphs/mod.ts
Normal file
@@ -0,0 +1,2 @@
|
||||
export * from "./types.ts";
|
||||
export * from "./schemaBuilder.ts";
|
||||
63
src/graphs/schemaBuilder.ts
Normal file
63
src/graphs/schemaBuilder.ts
Normal file
@@ -0,0 +1,63 @@
|
||||
import { KindGuard, type TSchema } from "@alkdev/typebox";
|
||||
import { Value } from "@alkdev/typebox/value";
|
||||
import { assert } from "@std/assert";
|
||||
import { GraphSchema, GraphConfig, NodeType, EdgeType } from "./types.ts";
|
||||
|
||||
export class SchemaBuilder {
|
||||
private schema: {
|
||||
config: Record<string, unknown>;
|
||||
nodeTypes: Record<string, NodeType>;
|
||||
edgeTypes: Record<string, EdgeType>;
|
||||
} = {
|
||||
config: {},
|
||||
nodeTypes: {},
|
||||
edgeTypes: {},
|
||||
};
|
||||
|
||||
config(config: Partial<GraphConfig>): SchemaBuilder {
|
||||
const configObj = Value.Default(GraphConfig, config) as GraphConfig;
|
||||
this.check(GraphConfig, configObj);
|
||||
this.schema.config = configObj as Record<string, unknown>;
|
||||
return this;
|
||||
}
|
||||
|
||||
nodeType(name: string, schema: TSchema): SchemaBuilder {
|
||||
assert(KindGuard.IsSchema(schema), `type '${name}' is not a valid json schema.`);
|
||||
|
||||
if (!this.schema.nodeTypes) this.schema.nodeTypes = {};
|
||||
const nodeTypeObj: NodeType = { name, schema };
|
||||
|
||||
this.check(NodeType, nodeTypeObj);
|
||||
this.schema.nodeTypes[name] = nodeTypeObj;
|
||||
return this;
|
||||
}
|
||||
|
||||
edgeType(
|
||||
name: string,
|
||||
schema: TSchema,
|
||||
options?: { allowedSourceTypes?: string[]; allowedTargetTypes?: string[] },
|
||||
): SchemaBuilder {
|
||||
assert(KindGuard.IsSchema(schema), `type '${name}' is not a valid json schema.`);
|
||||
|
||||
if (!this.schema.edgeTypes) this.schema.edgeTypes = {};
|
||||
const edgeTypeObj: EdgeType = { name, schema, ...options };
|
||||
|
||||
this.check(EdgeType, edgeTypeObj);
|
||||
this.schema.edgeTypes[name] = edgeTypeObj;
|
||||
return this;
|
||||
}
|
||||
|
||||
check(schema: TSchema, value: unknown): void {
|
||||
if (!Value.Check(schema, value)) {
|
||||
const errors = [...Value.Errors(schema, value)];
|
||||
throw new Error(
|
||||
`Invalid schema structure: ${JSON.stringify(errors.map((e) => `${e.path}: ${e.message}`))}`,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
build(): GraphSchema {
|
||||
this.check(GraphSchema, this.schema);
|
||||
return this.schema as GraphSchema;
|
||||
}
|
||||
}
|
||||
70
src/graphs/types.ts
Normal file
70
src/graphs/types.ts
Normal file
@@ -0,0 +1,70 @@
|
||||
import { Type, type Static, type TSchema } from "@alkdev/typebox";
|
||||
|
||||
export const BaseNodeAttributes: TSchema = Type.Object({
|
||||
created: Type.Optional(Type.String({ format: "date-time" })),
|
||||
modified: Type.Optional(Type.String({ format: "date-time" })),
|
||||
metadata: Type.Optional(Type.Record(Type.String(), Type.Any())),
|
||||
});
|
||||
|
||||
export type BaseNodeAttributes = Static<typeof BaseNodeAttributes>;
|
||||
|
||||
export const BaseEdgeAttributes: TSchema = Type.Object({
|
||||
type: Type.String(),
|
||||
metadata: Type.Optional(Type.Record(Type.String(), Type.Any())),
|
||||
});
|
||||
|
||||
export type BaseEdgeAttributes = Static<typeof BaseEdgeAttributes>;
|
||||
|
||||
export const GraphConfig: TSchema = Type.Object({
|
||||
type: Type.Union([
|
||||
Type.Literal("directed"),
|
||||
Type.Literal("undirected"),
|
||||
Type.Literal("mixed"),
|
||||
], { default: "mixed" }),
|
||||
multi: Type.Boolean({ default: true }),
|
||||
allowSelfLoops: Type.Boolean({ default: true }),
|
||||
});
|
||||
|
||||
export type GraphConfig = Static<typeof GraphConfig>;
|
||||
|
||||
export const NodeType: TSchema = Type.Object({
|
||||
name: Type.String(),
|
||||
schema: Type.Any(),
|
||||
});
|
||||
|
||||
export type NodeType = Static<typeof NodeType>;
|
||||
|
||||
export const EdgeType: TSchema = Type.Object({
|
||||
name: Type.String(),
|
||||
schema: Type.Any(),
|
||||
allowedSourceTypes: Type.Optional(Type.Array(Type.String())),
|
||||
allowedTargetTypes: Type.Optional(Type.Array(Type.String())),
|
||||
});
|
||||
|
||||
export type EdgeType = Static<typeof EdgeType>;
|
||||
|
||||
export const GraphSchema: TSchema = Type.Object({
|
||||
config: GraphConfig,
|
||||
nodeTypes: Type.Record(Type.String(), NodeType),
|
||||
edgeTypes: Type.Record(Type.String(), EdgeType),
|
||||
});
|
||||
|
||||
export type GraphSchema = Static<typeof GraphSchema>;
|
||||
|
||||
export enum EnumGraphStatus {
|
||||
Active = "active",
|
||||
Archived = "archived",
|
||||
Draft = "draft",
|
||||
}
|
||||
|
||||
export type GraphStatus = Static<typeof GraphStatus>;
|
||||
export const GraphStatus: TSchema = Type.Enum(EnumGraphStatus);
|
||||
|
||||
export enum EnumGraphBaseType {
|
||||
Directed = "directed",
|
||||
Undirected = "undirected",
|
||||
Mixed = "mixed",
|
||||
}
|
||||
|
||||
export type GraphBaseType = Static<typeof GraphBaseType>;
|
||||
export const GraphBaseType: TSchema = Type.Enum(EnumGraphBaseType);
|
||||
3
src/pg/mod.ts
Normal file
3
src/pg/mod.ts
Normal file
@@ -0,0 +1,3 @@
|
||||
// Postgres host — not yet implemented
|
||||
// Will mirror sqlite/ structure with pgTable, jsonb(), timestamp(), pgEnum, etc.
|
||||
// Import pattern: import { ... } from "@alkdev/storage/pg"
|
||||
11
src/sqlite/client.ts
Normal file
11
src/sqlite/client.ts
Normal file
@@ -0,0 +1,11 @@
|
||||
import { drizzle, type LibSQLDatabase } from "drizzle-orm/libsql";
|
||||
import type { Client } from "@libsql/client";
|
||||
import * as schema from "./schema.ts";
|
||||
|
||||
export type SqliteSchema = typeof schema;
|
||||
|
||||
export type SqliteDatabase = LibSQLDatabase<SqliteSchema>;
|
||||
|
||||
export function createSqliteDatabase(client: Client): SqliteDatabase {
|
||||
return drizzle(client, { schema }) as SqliteDatabase;
|
||||
}
|
||||
2
src/sqlite/mod.ts
Normal file
2
src/sqlite/mod.ts
Normal file
@@ -0,0 +1,2 @@
|
||||
export * from "./schema.ts";
|
||||
export * from "./client.ts";
|
||||
68
src/sqlite/relations.ts
Normal file
68
src/sqlite/relations.ts
Normal file
@@ -0,0 +1,68 @@
|
||||
import { relations } from "drizzle-orm";
|
||||
import {
|
||||
graphTypes,
|
||||
nodeTypes,
|
||||
edgeTypes,
|
||||
graphs,
|
||||
nodes,
|
||||
edges,
|
||||
} from "./tables/index.ts";
|
||||
|
||||
export const graphTypeRelations = relations(graphTypes, ({ many }) => ({
|
||||
nodeTypes: many(nodeTypes),
|
||||
edgeTypes: many(edgeTypes),
|
||||
graphs: many(graphs),
|
||||
}));
|
||||
|
||||
export const nodeTypesRelations = relations(nodeTypes, ({ one }) => ({
|
||||
graphType: one(graphTypes, {
|
||||
fields: [nodeTypes.graphTypeId],
|
||||
references: [graphTypes.id],
|
||||
}),
|
||||
}));
|
||||
|
||||
export const edgeTypesRelations = relations(edgeTypes, ({ one }) => ({
|
||||
graphType: one(graphTypes, {
|
||||
fields: [edgeTypes.graphTypeId],
|
||||
references: [graphTypes.id],
|
||||
}),
|
||||
}));
|
||||
|
||||
export const graphsRelations = relations(graphs, ({ one, many }) => ({
|
||||
graphType: one(graphTypes, {
|
||||
fields: [graphs.graphTypeId],
|
||||
references: [graphTypes.id],
|
||||
}),
|
||||
nodes: many(nodes),
|
||||
edges: many(edges),
|
||||
}));
|
||||
|
||||
export const edgesRelations = relations(edges, ({ one }) => ({
|
||||
graph: one(graphs, {
|
||||
fields: [edges.graphId],
|
||||
references: [graphs.id],
|
||||
}),
|
||||
sourceNode: one(nodes, {
|
||||
fields: [edges.graphId, edges.sourceNodeKey],
|
||||
references: [nodes.graphId, nodes.key],
|
||||
relationName: "sourceNode",
|
||||
}),
|
||||
targetNode: one(nodes, {
|
||||
fields: [edges.graphId, edges.targetNodeKey],
|
||||
references: [nodes.graphId, nodes.key],
|
||||
relationName: "targetNode",
|
||||
}),
|
||||
}));
|
||||
|
||||
export const nodesRelations = relations(nodes, ({ one, many }) => ({
|
||||
graph: one(graphs, {
|
||||
fields: [nodes.graphId],
|
||||
references: [graphs.id],
|
||||
}),
|
||||
outgoingEdges: many(edges, {
|
||||
relationName: "sourceNode",
|
||||
}),
|
||||
incomingEdges: many(edges, {
|
||||
relationName: "targetNode",
|
||||
}),
|
||||
}));
|
||||
2
src/sqlite/schema.ts
Normal file
2
src/sqlite/schema.ts
Normal file
@@ -0,0 +1,2 @@
|
||||
export * from "./tables/index.ts";
|
||||
export * from "./relations.ts";
|
||||
30
src/sqlite/tables/actors.ts
Normal file
30
src/sqlite/tables/actors.ts
Normal file
@@ -0,0 +1,30 @@
|
||||
import { sqliteTable, text } from "drizzle-orm/sqlite-core";
|
||||
import { createInsertSchema, createSelectSchema } from "@alkdev/drizzlebox";
|
||||
import { Type, type Static } from "@alkdev/typebox";
|
||||
import { commonCols, ACTOR_TYPE } from "./common.ts";
|
||||
|
||||
export const actors = sqliteTable("actors", {
|
||||
...commonCols,
|
||||
name: text("name").notNull(),
|
||||
type: text("type", { enum: ["human", "llm", "agent"] }).notNull(),
|
||||
});
|
||||
|
||||
export const SelectActor = createSelectSchema(actors, {
|
||||
metadata: Type.Object({}, { additionalProperties: true }),
|
||||
createdAt: Type.Date(),
|
||||
updatedAt: Type.Date(),
|
||||
});
|
||||
|
||||
export type SelectActor = Static<typeof SelectActor>;
|
||||
|
||||
export const InsertActor = createInsertSchema(actors, {
|
||||
name: Type.String({ minLength: 1, maxLength: 255 }),
|
||||
type: Type.Union([
|
||||
Type.Literal(ACTOR_TYPE.Human),
|
||||
Type.Literal(ACTOR_TYPE.Llm),
|
||||
Type.Literal(ACTOR_TYPE.Agent),
|
||||
]),
|
||||
metadata: Type.Optional(Type.Object({}, { additionalProperties: true })),
|
||||
});
|
||||
|
||||
export type InsertActor = Static<typeof InsertActor>;
|
||||
21
src/sqlite/tables/common.ts
Normal file
21
src/sqlite/tables/common.ts
Normal file
@@ -0,0 +1,21 @@
|
||||
import { sql } from "drizzle-orm";
|
||||
import { text, integer } from "drizzle-orm/sqlite-core";
|
||||
|
||||
export const commonCols = {
|
||||
id: text("id").primaryKey(),
|
||||
metadata: text("metadata", { mode: "json" }).$type<Record<string, unknown>>().default({}),
|
||||
createdAt: integer("created_at", { mode: "timestamp" })
|
||||
.default(sql`(strftime('%s', 'now'))`)
|
||||
.notNull(),
|
||||
updatedAt: integer("updated_at", { mode: "timestamp" })
|
||||
.default(sql`(strftime('%s', 'now'))`)
|
||||
.notNull(),
|
||||
};
|
||||
|
||||
export const ACTOR_TYPE = {
|
||||
Human: "human",
|
||||
Llm: "llm",
|
||||
Agent: "agent",
|
||||
} as const;
|
||||
|
||||
export type EnumValues<T extends Record<string, string>> = T[keyof T];
|
||||
37
src/sqlite/tables/edgeTypes.ts
Normal file
37
src/sqlite/tables/edgeTypes.ts
Normal file
@@ -0,0 +1,37 @@
|
||||
import { sqliteTable, text, unique } from "drizzle-orm/sqlite-core";
|
||||
import { createInsertSchema, createSelectSchema } from "@alkdev/drizzlebox";
|
||||
import { Type, type Static } from "@alkdev/typebox";
|
||||
import { commonCols } from "./common.ts";
|
||||
import { graphTypes } from "./graphTypes.ts";
|
||||
|
||||
export const edgeTypes = sqliteTable("edge_types", {
|
||||
...commonCols,
|
||||
graphTypeId: text("graph_type_id").notNull().references(() => graphTypes.id, { onDelete: "cascade" }),
|
||||
name: text("name").notNull(),
|
||||
description: text("description").default(""),
|
||||
schema: text("schema", { mode: "json" }).$type<Record<string, unknown>>().notNull(),
|
||||
allowedSourceTypes: text("allowed_source_types", { mode: "json" }).$type<string[]>().default([]),
|
||||
allowedTargetTypes: text("allowed_target_types", { mode: "json" }).$type<string[]>().default([]),
|
||||
}, (table) => ({
|
||||
graphTypeNameIdx: unique().on(table.graphTypeId, table.name),
|
||||
}));
|
||||
|
||||
export const SelectEdgeType = createSelectSchema(edgeTypes, {
|
||||
schema: Type.Unknown(),
|
||||
allowedSourceTypes: Type.Array(Type.String()),
|
||||
allowedTargetTypes: Type.Array(Type.String()),
|
||||
metadata: Type.Object({}, { additionalProperties: true }),
|
||||
createdAt: Type.Date(),
|
||||
updatedAt: Type.Date(),
|
||||
});
|
||||
|
||||
export type SelectEdgeType = Static<typeof SelectEdgeType>;
|
||||
|
||||
export const InsertEdgeType = createInsertSchema(edgeTypes, {
|
||||
name: Type.String({ minLength: 2 }),
|
||||
schema: Type.Unknown(),
|
||||
allowedSourceTypes: Type.Optional(Type.Array(Type.String())),
|
||||
allowedTargetTypes: Type.Optional(Type.Array(Type.String())),
|
||||
});
|
||||
|
||||
export type InsertEdgeType = Static<typeof InsertEdgeType>;
|
||||
44
src/sqlite/tables/edges.ts
Normal file
44
src/sqlite/tables/edges.ts
Normal file
@@ -0,0 +1,44 @@
|
||||
import { sqliteTable, text, integer, unique, foreignKey } from "drizzle-orm/sqlite-core";
|
||||
import { createInsertSchema, createSelectSchema } from "@alkdev/drizzlebox";
|
||||
import { Type, type Static } from "@alkdev/typebox";
|
||||
import { commonCols } from "./common.ts";
|
||||
import { graphs } from "./graphs.ts";
|
||||
import { nodes } from "./nodes.ts";
|
||||
|
||||
const AttributesSchema = Type.Record(Type.String(), Type.Any());
|
||||
|
||||
export const edges = sqliteTable("edges", {
|
||||
...commonCols,
|
||||
graphId: text("graph_id").notNull().references(() => graphs.id, { onDelete: "cascade" }),
|
||||
key: text("key"),
|
||||
sourceNodeKey: text("source_node_key").notNull(),
|
||||
targetNodeKey: text("target_node_key").notNull(),
|
||||
attributes: text("attributes", { mode: "json" }).notNull().default({}),
|
||||
undirected: integer("undirected", { mode: "boolean" }).default(false),
|
||||
}, (table) => ({
|
||||
graphKeyIdx: unique().on(table.graphId, table.key),
|
||||
sourceFk: foreignKey({
|
||||
columns: [table.graphId, table.sourceNodeKey],
|
||||
foreignColumns: [nodes.graphId, nodes.key],
|
||||
}).onDelete("cascade"),
|
||||
targetFk: foreignKey({
|
||||
columns: [table.graphId, table.targetNodeKey],
|
||||
foreignColumns: [nodes.graphId, nodes.key],
|
||||
}).onDelete("cascade"),
|
||||
}));
|
||||
|
||||
export const SelectEdge = createSelectSchema(edges, {
|
||||
attributes: AttributesSchema,
|
||||
metadata: Type.Object({}, { additionalProperties: true }),
|
||||
createdAt: Type.Date(),
|
||||
updatedAt: Type.Date(),
|
||||
});
|
||||
|
||||
export type SelectEdge = Static<typeof SelectEdge>;
|
||||
|
||||
export const InsertEdge = createInsertSchema(edges, {
|
||||
key: Type.String({ minLength: 1 }),
|
||||
attributes: AttributesSchema,
|
||||
});
|
||||
|
||||
export type InsertEdge = Static<typeof InsertEdge>;
|
||||
38
src/sqlite/tables/graphTypes.ts
Normal file
38
src/sqlite/tables/graphTypes.ts
Normal file
@@ -0,0 +1,38 @@
|
||||
import { sqliteTable, text, integer } from "drizzle-orm/sqlite-core";
|
||||
import { createInsertSchema, createSelectSchema } from "@alkdev/drizzlebox";
|
||||
import { Type, type Static } from "@alkdev/typebox";
|
||||
import { commonCols } from "./common.ts";
|
||||
|
||||
|
||||
const ConfigSchema = Type.Object({
|
||||
type: Type.Union([
|
||||
Type.Literal("directed"),
|
||||
Type.Literal("undirected"),
|
||||
Type.Literal("mixed"),
|
||||
], { default: "mixed" }),
|
||||
multi: Type.Boolean({ default: true }),
|
||||
allowSelfLoops: Type.Boolean({ default: true }),
|
||||
});
|
||||
|
||||
export const graphTypes = sqliteTable("graph_types", {
|
||||
...commonCols,
|
||||
name: text("name").notNull().unique(),
|
||||
description: text("description").default(""),
|
||||
config: text("config", { mode: "json" }).$type<Static<typeof ConfigSchema>>().notNull(),
|
||||
version: integer("version").notNull().default(1),
|
||||
});
|
||||
|
||||
export const SelectGraphType = createSelectSchema(graphTypes, {
|
||||
metadata: Type.Object({}, { additionalProperties: true }),
|
||||
createdAt: Type.Date(),
|
||||
updatedAt: Type.Date(),
|
||||
});
|
||||
|
||||
export type SelectGraphType = Static<typeof SelectGraphType>;
|
||||
|
||||
export const InsertGraphType = createInsertSchema(graphTypes, {
|
||||
name: Type.String({ minLength: 2, maxLength: 255 }),
|
||||
description: Type.Optional(Type.String()),
|
||||
});
|
||||
|
||||
export type InsertGraphType = Static<typeof InsertGraphType>;
|
||||
35
src/sqlite/tables/graphs.ts
Normal file
35
src/sqlite/tables/graphs.ts
Normal file
@@ -0,0 +1,35 @@
|
||||
import { sqliteTable, text } from "drizzle-orm/sqlite-core";
|
||||
import { createInsertSchema, createSelectSchema } from "@alkdev/drizzlebox";
|
||||
import { Type, type Static } from "@alkdev/typebox";
|
||||
import { commonCols } from "./common.ts";
|
||||
import { graphTypes } from "./graphTypes.ts";
|
||||
import { EnumGraphStatus } from "../../graphs/types.ts";
|
||||
|
||||
export const graphs = sqliteTable("graphs", {
|
||||
...commonCols,
|
||||
graphTypeId: text("graph_type_id").references(() => graphTypes.id, { onDelete: "set null" }),
|
||||
name: text("name").notNull(),
|
||||
description: text("description").default(""),
|
||||
status: text("status", { enum: ["active", "archived", "draft"] })
|
||||
.default("draft")
|
||||
.notNull(),
|
||||
});
|
||||
|
||||
export const SelectGraph = createSelectSchema(graphs, {
|
||||
metadata: Type.Object({}, { additionalProperties: true }),
|
||||
createdAt: Type.Date(),
|
||||
updatedAt: Type.Date(),
|
||||
});
|
||||
|
||||
export type SelectGraph = Static<typeof SelectGraph>;
|
||||
|
||||
export const InsertGraph = createInsertSchema(graphs, {
|
||||
name: Type.String({ minLength: 2 }),
|
||||
status: Type.Optional(Type.Union([
|
||||
Type.Literal(EnumGraphStatus.Active),
|
||||
Type.Literal(EnumGraphStatus.Archived),
|
||||
Type.Literal(EnumGraphStatus.Draft),
|
||||
])),
|
||||
});
|
||||
|
||||
export type InsertGraph = Static<typeof InsertGraph>;
|
||||
23
src/sqlite/tables/index.ts
Normal file
23
src/sqlite/tables/index.ts
Normal file
@@ -0,0 +1,23 @@
|
||||
export { graphs } from "./graphs.ts";
|
||||
export type { SelectGraph, InsertGraph } from "./graphs.ts";
|
||||
export { SelectGraph as SelectGraphSchema, InsertGraph as InsertGraphSchema } from "./graphs.ts";
|
||||
export { nodes } from "./nodes.ts";
|
||||
export type { InsertNode } from "./nodes.ts";
|
||||
export { InsertNodeSchema } from "./nodes.ts";
|
||||
export { edges } from "./edges.ts";
|
||||
export type { SelectEdge, InsertEdge } from "./edges.ts";
|
||||
export { SelectEdge as SelectEdgeSchema, InsertEdge as InsertEdgeSchema } from "./edges.ts";
|
||||
export { graphTypes } from "./graphTypes.ts";
|
||||
export type { SelectGraphType, InsertGraphType } from "./graphTypes.ts";
|
||||
export { SelectGraphType as SelectGraphTypeSchema, InsertGraphType as InsertGraphTypeSchema } from "./graphTypes.ts";
|
||||
export { nodeTypes } from "./nodeTypes.ts";
|
||||
export type { SelectNodeType, InsertNodeType } from "./nodeTypes.ts";
|
||||
export { SelectNodeType as SelectNodeTypeSchema, InsertNodeType as InsertNodeTypeSchema } from "./nodeTypes.ts";
|
||||
export { edgeTypes } from "./edgeTypes.ts";
|
||||
export type { SelectEdgeType, InsertEdgeType } from "./edgeTypes.ts";
|
||||
export { SelectEdgeType as SelectEdgeTypeSchema, InsertEdgeType as InsertEdgeTypeSchema } from "./edgeTypes.ts";
|
||||
export { actors } from "./actors.ts";
|
||||
export type { SelectActor, InsertActor } from "./actors.ts";
|
||||
export { SelectActor as SelectActorSchema, InsertActor as InsertActorSchema } from "./actors.ts";
|
||||
export { commonCols, ACTOR_TYPE } from "./common.ts";
|
||||
export type { EnumValues } from "./common.ts";
|
||||
31
src/sqlite/tables/nodeTypes.ts
Normal file
31
src/sqlite/tables/nodeTypes.ts
Normal file
@@ -0,0 +1,31 @@
|
||||
import { sqliteTable, text, unique } from "drizzle-orm/sqlite-core";
|
||||
import { createInsertSchema, createSelectSchema } from "@alkdev/drizzlebox";
|
||||
import { Type, type Static } from "@alkdev/typebox";
|
||||
import { commonCols } from "./common.ts";
|
||||
import { graphTypes } from "./graphTypes.ts";
|
||||
|
||||
export const nodeTypes = sqliteTable("node_types", {
|
||||
...commonCols,
|
||||
graphTypeId: text("graph_type_id").notNull().references(() => graphTypes.id, { onDelete: "cascade" }),
|
||||
name: text("name").notNull(),
|
||||
description: text("description").default(""),
|
||||
schema: text("schema", { mode: "json" }).$type<Record<string, unknown>>().notNull(),
|
||||
}, (table) => ({
|
||||
graphTypeNameIdx: unique().on(table.graphTypeId, table.name),
|
||||
}));
|
||||
|
||||
export const SelectNodeType = createSelectSchema(nodeTypes, {
|
||||
schema: Type.Unknown(),
|
||||
metadata: Type.Object({}, { additionalProperties: true }),
|
||||
createdAt: Type.Date(),
|
||||
updatedAt: Type.Date(),
|
||||
});
|
||||
|
||||
export type SelectNodeType = Static<typeof SelectNodeType>;
|
||||
|
||||
export const InsertNodeType = createInsertSchema(nodeTypes, {
|
||||
name: Type.String({ minLength: 2 }),
|
||||
schema: Type.Unknown(),
|
||||
});
|
||||
|
||||
export type InsertNodeType = Static<typeof InsertNodeType>;
|
||||
23
src/sqlite/tables/nodes.ts
Normal file
23
src/sqlite/tables/nodes.ts
Normal file
@@ -0,0 +1,23 @@
|
||||
import { sqliteTable, text, unique } from "drizzle-orm/sqlite-core";
|
||||
import { createInsertSchema } from "@alkdev/drizzlebox";
|
||||
import { Type, type Static } from "@alkdev/typebox";
|
||||
import { commonCols } from "./common.ts";
|
||||
import { graphs } from "./graphs.ts";
|
||||
|
||||
const AttributesSchema = Type.Record(Type.String(), Type.Any());
|
||||
|
||||
export const nodes = sqliteTable("nodes", {
|
||||
...commonCols,
|
||||
graphId: text("graph_id").notNull().references(() => graphs.id, { onDelete: "cascade" }),
|
||||
key: text("key").notNull(),
|
||||
attributes: text("attributes", { mode: "json" }).notNull().default({}),
|
||||
}, (table) => ({
|
||||
graphKeyIdx: unique().on(table.graphId, table.key),
|
||||
}));
|
||||
|
||||
export const InsertNodeSchema = createInsertSchema(nodes, {
|
||||
key: Type.String({ minLength: 1 }),
|
||||
attributes: AttributesSchema,
|
||||
});
|
||||
|
||||
export type InsertNode = Static<typeof InsertNodeSchema>;
|
||||
Reference in New Issue
Block a user