@apex-stack/data 0.1.2 → 0.1.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,9 +1,28 @@
1
1
  {
2
2
  "name": "@apex-stack/data",
3
- "version": "0.1.2",
3
+ "version": "0.1.4",
4
4
  "description": "Data layer for Apex JS — Drizzle-backed resources that are REST + MCP by default",
5
5
  "type": "module",
6
6
  "license": "MIT",
7
+ "author": "Andre Corugda",
8
+ "repository": {
9
+ "type": "git",
10
+ "url": "git+https://github.com/andrecorugda/apexjs.git",
11
+ "directory": "packages/data"
12
+ },
13
+ "homepage": "https://apexjs.site",
14
+ "bugs": {
15
+ "url": "https://github.com/andrecorugda/apexjs/issues"
16
+ },
17
+ "keywords": [
18
+ "alpine",
19
+ "alpinejs",
20
+ "drizzle",
21
+ "orm",
22
+ "mcp",
23
+ "apex",
24
+ "apexjs"
25
+ ],
7
26
  "exports": {
8
27
  ".": {
9
28
  "types": "./dist/index.d.ts",
@@ -15,18 +34,32 @@
15
34
  "dist"
16
35
  ],
17
36
  "dependencies": {
18
- "@libsql/client": "^0.17.4",
19
- "better-sqlite3": "^11.0.0",
20
- "drizzle-orm": "^0.38.0",
37
+ "drizzle-orm": "^0.45.2",
21
38
  "zod": "^4.4.3",
22
- "@apex-stack/core": "0.1.3"
39
+ "@apex-stack/core": "0.1.19"
40
+ },
41
+ "peerDependencies": {
42
+ "@electric-sql/pglite": "^0.5.0",
43
+ "@libsql/client": "^0.17.0",
44
+ "postgres": "^3.4.0"
45
+ },
46
+ "peerDependenciesMeta": {
47
+ "@libsql/client": {
48
+ "optional": true
49
+ },
50
+ "postgres": {
51
+ "optional": true
52
+ },
53
+ "@electric-sql/pglite": {
54
+ "optional": true
55
+ }
23
56
  },
24
57
  "engines": {
25
58
  "node": ">=20.19"
26
59
  },
27
60
  "devDependencies": {
28
61
  "@electric-sql/pglite": "^0.5.4",
29
- "@types/better-sqlite3": "^7.6.13",
62
+ "@libsql/client": "^0.17.4",
30
63
  "postgres": "^3.4.9"
31
64
  },
32
65
  "scripts": {
package/dist/index.d.ts DELETED
@@ -1,53 +0,0 @@
1
- import { ApexResource } from '@apex-stack/core';
2
- import { ZodRawShape } from 'zod';
3
-
4
- type Dialect = 'sqlite' | 'postgres';
5
- /** A driver-agnostic database handle. `db` is a Drizzle instance (async API). */
6
- interface ApexDbHandle {
7
- db: any;
8
- dialect: Dialect;
9
- /** Run raw SQL (one or more statements). */
10
- exec(sql: string): Promise<void>;
11
- /** Run a query and return rows. */
12
- query(sql: string): Promise<Array<Record<string, unknown>>>;
13
- close(): Promise<void>;
14
- }
15
- type CreateDbConfig = string | {
16
- driver: 'sqlite' | 'libsql';
17
- url: string;
18
- } | {
19
- driver: 'postgres';
20
- url: string;
21
- } | {
22
- driver: 'pglite';
23
- dir?: string;
24
- };
25
- /**
26
- * Open a database and wrap it with Drizzle behind a driver-agnostic handle.
27
- * All drivers use Drizzle's async query API, so `defineResource` works unchanged
28
- * across SQLite (libSQL/Turso), Postgres (Supabase/Neon) and embedded PGlite.
29
- * Postgres/PGlite drivers are loaded on demand — install only what you use.
30
- */
31
- declare function createDb(config: CreateDbConfig): Promise<ApexDbHandle>;
32
- /**
33
- * Apply pending `*.sql` migrations from `dir`, tracked in `_apex_migrations`.
34
- * Idempotent; runs each file once in filename order. Works on any dialect.
35
- */
36
- declare function applyMigrations(handle: ApexDbHandle, dir: string): Promise<string[]>;
37
- interface DefineResourceOptions {
38
- db: any;
39
- /** A Drizzle table (from `drizzle-orm/sqlite-core` or `…/pg-core`). */
40
- table: any;
41
- /** Zod raw shape validating the create payload. */
42
- insert: ZodRawShape;
43
- /** Primary-key column name. Defaults to `id`. */
44
- pk?: string;
45
- }
46
- /**
47
- * Turn one table into a REST + MCP resource (list/get/create/update/delete),
48
- * each also an MCP tool. Dialect-agnostic — the same definition works whether
49
- * `db` is backed by SQLite, Turso, Supabase, Neon, or embedded PGlite.
50
- */
51
- declare function defineResource(name: string, opts: DefineResourceOptions): ApexResource;
52
-
53
- export { type ApexDbHandle, type CreateDbConfig, type DefineResourceOptions, type Dialect, applyMigrations, createDb, defineResource };
package/dist/index.js DELETED
@@ -1,156 +0,0 @@
1
- // src/index.ts
2
- import { existsSync, readdirSync, readFileSync } from "fs";
3
- import { join } from "path";
4
- import { defineApexRoute } from "@apex-stack/core";
5
- import { eq } from "drizzle-orm";
6
- import { z } from "zod";
7
- function libsqlUrl(pathOrUrl) {
8
- return /^(file:|libsql:|https?:|:memory:)/.test(pathOrUrl) ? pathOrUrl : `file:${pathOrUrl}`;
9
- }
10
- async function createDb(config) {
11
- const cfg = typeof config === "string" ? { driver: "libsql", url: config } : config;
12
- if (cfg.driver === "sqlite" || cfg.driver === "libsql") {
13
- const { createClient } = await import("@libsql/client");
14
- const { drizzle: drizzle2 } = await import("drizzle-orm/libsql");
15
- const client2 = createClient({ url: libsqlUrl(cfg.url) });
16
- return {
17
- db: drizzle2(client2),
18
- dialect: "sqlite",
19
- exec: async (sql) => {
20
- await client2.executeMultiple(sql);
21
- },
22
- query: async (sql) => (await client2.execute(sql)).rows,
23
- close: async () => {
24
- client2.close();
25
- }
26
- };
27
- }
28
- if (cfg.driver === "postgres") {
29
- const postgres = (await import("postgres")).default;
30
- const { drizzle: drizzle2 } = await import("drizzle-orm/postgres-js");
31
- const client2 = postgres(cfg.url);
32
- return {
33
- db: drizzle2(client2),
34
- dialect: "postgres",
35
- exec: async (sql) => {
36
- await client2.unsafe(sql);
37
- },
38
- query: async (sql) => await client2.unsafe(sql),
39
- close: async () => {
40
- await client2.end();
41
- }
42
- };
43
- }
44
- const { PGlite } = await import("@electric-sql/pglite");
45
- const { drizzle } = await import("drizzle-orm/pglite");
46
- const client = new PGlite(cfg.dir ?? "memory://");
47
- return {
48
- db: drizzle(client),
49
- dialect: "postgres",
50
- exec: async (sql) => {
51
- await client.exec(sql);
52
- },
53
- query: async (sql) => (await client.query(sql)).rows,
54
- close: async () => {
55
- await client.close();
56
- }
57
- };
58
- }
59
- async function applyMigrations(handle, dir) {
60
- if (!existsSync(dir)) return [];
61
- await handle.exec(
62
- "CREATE TABLE IF NOT EXISTS _apex_migrations (name TEXT PRIMARY KEY, applied_at TEXT NOT NULL)"
63
- );
64
- const applied = new Set(
65
- (await handle.query("SELECT name FROM _apex_migrations")).map((r) => r.name)
66
- );
67
- const done = [];
68
- for (const file of readdirSync(dir).filter((f) => f.endsWith(".sql")).sort()) {
69
- if (applied.has(file)) continue;
70
- await handle.exec(readFileSync(join(dir, file), "utf8"));
71
- const at = (/* @__PURE__ */ new Date()).toISOString();
72
- await handle.exec(
73
- `INSERT INTO _apex_migrations (name, applied_at) VALUES ('${file.replace(/'/g, "''")}', '${at}')`
74
- );
75
- done.push(file);
76
- }
77
- return done;
78
- }
79
- function defineResource(name, opts) {
80
- const { db, table, insert, pk = "id" } = opts;
81
- const pkCol = table[pk];
82
- const updateShape = { id: z.coerce.number() };
83
- for (const [key, schema] of Object.entries(
84
- insert
85
- )) {
86
- updateShape[key] = schema.optional();
87
- }
88
- return {
89
- __apexResource: true,
90
- name,
91
- routes: [
92
- {
93
- pathSuffix: "",
94
- mcpName: `${name}_list`,
95
- route: defineApexRoute({
96
- method: "GET",
97
- description: `List all ${name}`,
98
- mcp: true,
99
- handler: async () => await db.select().from(table)
100
- })
101
- },
102
- {
103
- pathSuffix: "/:id",
104
- mcpName: `${name}_get`,
105
- route: defineApexRoute({
106
- method: "GET",
107
- description: `Get a single ${name} by id`,
108
- input: { id: z.coerce.number() },
109
- mcp: true,
110
- handler: async ({ input }) => (await db.select().from(table).where(eq(pkCol, input.id)))[0] ?? null
111
- })
112
- },
113
- {
114
- pathSuffix: "",
115
- mcpName: `${name}_create`,
116
- route: defineApexRoute({
117
- method: "POST",
118
- description: `Create a ${name}`,
119
- input: insert,
120
- mcp: true,
121
- handler: async ({ input }) => (await db.insert(table).values(input).returning())[0]
122
- })
123
- },
124
- {
125
- pathSuffix: "/:id",
126
- mcpName: `${name}_update`,
127
- route: defineApexRoute({
128
- method: "PATCH",
129
- description: `Update a ${name} by id (partial)`,
130
- input: updateShape,
131
- mcp: true,
132
- handler: async ({ input }) => {
133
- const { id, ...fields } = input;
134
- return (await db.update(table).set(fields).where(eq(pkCol, id)).returning())[0] ?? null;
135
- }
136
- })
137
- },
138
- {
139
- pathSuffix: "/:id",
140
- mcpName: `${name}_delete`,
141
- route: defineApexRoute({
142
- method: "DELETE",
143
- description: `Delete a ${name} by id`,
144
- input: { id: z.coerce.number() },
145
- mcp: true,
146
- handler: async ({ input }) => (await db.delete(table).where(eq(pkCol, input.id)).returning())[0] ?? null
147
- })
148
- }
149
- ]
150
- };
151
- }
152
- export {
153
- applyMigrations,
154
- createDb,
155
- defineResource
156
- };