@astrojs/db 0.1.0

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.
Files changed (56) hide show
  1. package/LICENSE +59 -0
  2. package/components/Renderer.astro +14 -0
  3. package/components/astro-env.d.ts +1 -0
  4. package/components/index.ts +2 -0
  5. package/components/tsconfig.json +7 -0
  6. package/config-augment.d.ts +4 -0
  7. package/dist/cli/commands/push/index.d.ts +6 -0
  8. package/dist/cli/commands/push/index.js +144 -0
  9. package/dist/cli/commands/sync/index.d.ts +6 -0
  10. package/dist/cli/commands/sync/index.js +45 -0
  11. package/dist/cli/commands/verify/index.d.ts +6 -0
  12. package/dist/cli/commands/verify/index.js +25 -0
  13. package/dist/cli/index.d.ts +6 -0
  14. package/dist/cli/index.js +24 -0
  15. package/dist/cli/queries.d.ts +19 -0
  16. package/dist/cli/queries.js +453 -0
  17. package/dist/cli/seed.d.ts +6 -0
  18. package/dist/cli/sync/admin.d.ts +33 -0
  19. package/dist/cli/sync/index.d.ts +1 -0
  20. package/dist/cli/sync/index.js +0 -0
  21. package/dist/cli/sync/migrate.d.ts +1 -0
  22. package/dist/cli/sync/migrate.js +0 -0
  23. package/dist/cli/sync/queries.d.ts +19 -0
  24. package/dist/cli/sync/remote-db.d.ts +1 -0
  25. package/dist/config.d.ts +1149 -0
  26. package/dist/config.js +53 -0
  27. package/dist/consts.d.ts +6 -0
  28. package/dist/consts.js +19 -0
  29. package/dist/error-map.d.ts +6 -0
  30. package/dist/error-map.js +79 -0
  31. package/dist/errors.d.ts +3 -0
  32. package/dist/errors.js +15 -0
  33. package/dist/index.d.ts +3 -0
  34. package/dist/index.js +10 -0
  35. package/dist/integration.d.ts +2 -0
  36. package/dist/integration.js +68 -0
  37. package/dist/internal-drizzle.d.ts +1 -0
  38. package/dist/internal-drizzle.js +48 -0
  39. package/dist/internal.d.ts +50 -0
  40. package/dist/internal.js +250 -0
  41. package/dist/load-astro-config.d.ts +6 -0
  42. package/dist/load-astro-config.js +79 -0
  43. package/dist/migrations.d.ts +9 -0
  44. package/dist/migrations.js +41 -0
  45. package/dist/typegen.d.ts +5 -0
  46. package/dist/typegen.js +57 -0
  47. package/dist/types.d.ts +1367 -0
  48. package/dist/types.js +58 -0
  49. package/dist/utils.d.ts +59 -0
  50. package/dist/utils.js +84 -0
  51. package/dist/vite-plugin-db.d.ts +19 -0
  52. package/dist/vite-plugin-db.js +66 -0
  53. package/dist/vite-plugin-inject-env-ts.d.ts +9 -0
  54. package/dist/vite-plugin-inject-env-ts.js +49 -0
  55. package/index.d.ts +3 -0
  56. package/package.json +72 -0
package/dist/types.js ADDED
@@ -0,0 +1,58 @@
1
+ import { z } from "zod";
2
+ const baseFieldSchema = z.object({
3
+ label: z.string().optional(),
4
+ optional: z.boolean().optional(),
5
+ unique: z.boolean().optional()
6
+ });
7
+ const booleanFieldSchema = baseFieldSchema.extend({
8
+ type: z.literal("boolean"),
9
+ default: z.boolean().optional()
10
+ });
11
+ const numberFieldSchema = baseFieldSchema.extend({
12
+ type: z.literal("number"),
13
+ default: z.number().optional()
14
+ });
15
+ const textFieldSchema = baseFieldSchema.extend({
16
+ type: z.literal("text"),
17
+ multiline: z.boolean().optional(),
18
+ default: z.string().optional()
19
+ });
20
+ const dateFieldSchema = baseFieldSchema.extend({
21
+ type: z.literal("date"),
22
+ default: z.union([
23
+ z.literal("now"),
24
+ // allow date-like defaults in user config,
25
+ // transform to ISO string for D1 storage
26
+ z.coerce.date().transform((d) => d.toISOString())
27
+ ]).optional()
28
+ });
29
+ const jsonFieldSchema = baseFieldSchema.extend({
30
+ type: z.literal("json"),
31
+ default: z.unknown().optional()
32
+ });
33
+ const fieldSchema = z.union([
34
+ booleanFieldSchema,
35
+ numberFieldSchema,
36
+ textFieldSchema,
37
+ dateFieldSchema,
38
+ jsonFieldSchema
39
+ ]);
40
+ const fieldsSchema = z.record(fieldSchema);
41
+ const readableCollectionSchema = z.object({
42
+ fields: fieldsSchema,
43
+ data: z.function().returns(z.array(z.record(z.unknown()))).optional(),
44
+ writable: z.literal(false)
45
+ });
46
+ const writableCollectionSchema = z.object({
47
+ fields: fieldsSchema,
48
+ seed: z.function().returns(z.array(z.record(z.unknown()))).optional(),
49
+ writable: z.literal(true)
50
+ });
51
+ const collectionSchema = z.union([readableCollectionSchema, writableCollectionSchema]);
52
+ const collectionsSchema = z.record(collectionSchema);
53
+ export {
54
+ collectionSchema,
55
+ collectionsSchema,
56
+ readableCollectionSchema,
57
+ writableCollectionSchema
58
+ };
@@ -0,0 +1,59 @@
1
+ import type { AstroConfig } from 'astro';
2
+ export type VitePlugin = Required<AstroConfig['vite']>['plugins'][number];
3
+ export declare const STUDIO_ADMIN_TABLE = "ReservedAstroStudioAdmin";
4
+ export declare const STUDIO_ADMIN_TABLE_ROW_ID = "admin";
5
+ export declare const adminTable: import("drizzle-orm/sqlite-core").SQLiteTableWithColumns<{
6
+ name: "ReservedAstroStudioAdmin";
7
+ schema: undefined;
8
+ columns: {
9
+ id: import("drizzle-orm/sqlite-core").SQLiteColumn<{
10
+ name: "id";
11
+ tableName: "ReservedAstroStudioAdmin";
12
+ dataType: "string";
13
+ columnType: "SQLiteText";
14
+ data: string;
15
+ driverParam: string;
16
+ notNull: true;
17
+ hasDefault: false;
18
+ enumValues: [string, ...string[]];
19
+ baseColumn: never;
20
+ }, object>;
21
+ collections: import("drizzle-orm/sqlite-core").SQLiteColumn<{
22
+ name: "collections";
23
+ tableName: "ReservedAstroStudioAdmin";
24
+ dataType: "string";
25
+ columnType: "SQLiteText";
26
+ data: string;
27
+ driverParam: string;
28
+ notNull: true;
29
+ hasDefault: false;
30
+ enumValues: [string, ...string[]];
31
+ baseColumn: never;
32
+ }, object>;
33
+ };
34
+ dialect: "sqlite";
35
+ }>;
36
+ export declare const STUDIO_MIGRATIONS_TABLE = "ReservedAstroStudioMigrations";
37
+ export declare const migrationsTable: import("drizzle-orm/sqlite-core").SQLiteTableWithColumns<{
38
+ name: "ReservedAstroStudioMigrations";
39
+ schema: undefined;
40
+ columns: {
41
+ name: import("drizzle-orm/sqlite-core").SQLiteColumn<{
42
+ name: "name";
43
+ tableName: "ReservedAstroStudioMigrations";
44
+ dataType: "string";
45
+ columnType: "SQLiteText";
46
+ data: string;
47
+ driverParam: string;
48
+ notNull: true;
49
+ hasDefault: false;
50
+ enumValues: [string, ...string[]];
51
+ baseColumn: never;
52
+ }, object>;
53
+ };
54
+ dialect: "sqlite";
55
+ }>;
56
+ export declare function getAstroStudioEnv(envMode?: string): Record<`ASTRO_STUDIO_${string}`, string>;
57
+ export declare function getStudioUrl(): string;
58
+ export declare function getRemoteDatabaseUrl(): string;
59
+ export declare function createRemoteDatabaseClient(appToken: string): import("drizzle-orm/sqlite-proxy").SqliteRemoteDatabase<Record<string, never>>;
package/dist/utils.js ADDED
@@ -0,0 +1,84 @@
1
+ import { sqliteTable, text, integer } from "drizzle-orm/sqlite-core";
2
+ import { drizzle } from "drizzle-orm/sqlite-proxy";
3
+ import { loadEnv } from "vite";
4
+ import { z } from "zod";
5
+ const STUDIO_ADMIN_TABLE = "ReservedAstroStudioAdmin";
6
+ const STUDIO_ADMIN_TABLE_ROW_ID = "admin";
7
+ const adminTable = sqliteTable(STUDIO_ADMIN_TABLE, {
8
+ id: text("id").primaryKey(),
9
+ collections: text("collections").notNull()
10
+ });
11
+ const STUDIO_MIGRATIONS_TABLE = "ReservedAstroStudioMigrations";
12
+ const migrationsTable = sqliteTable(STUDIO_MIGRATIONS_TABLE, {
13
+ name: text("name").primaryKey()
14
+ });
15
+ function getAstroStudioEnv(envMode = "") {
16
+ const env = loadEnv(envMode, process.cwd(), "ASTRO_STUDIO_");
17
+ return env;
18
+ }
19
+ function getStudioUrl() {
20
+ const env = getAstroStudioEnv();
21
+ return env.ASTRO_STUDIO_BASE_URL;
22
+ }
23
+ function getRemoteDatabaseUrl() {
24
+ const env = getAstroStudioEnv();
25
+ return env.ASTRO_STUDIO_REMOTE_DB_URL;
26
+ }
27
+ function createRemoteDatabaseClient(appToken) {
28
+ const url = new URL("./db/query/", getRemoteDatabaseUrl());
29
+ const db = drizzle(async (sql, parameters, method) => {
30
+ const requestBody = { sql, args: parameters };
31
+ console.info(JSON.stringify(requestBody));
32
+ const res = await fetch(url, {
33
+ method: "POST",
34
+ headers: {
35
+ Authorization: `Bearer ${appToken}`,
36
+ "Content-Type": "application/json"
37
+ },
38
+ body: JSON.stringify(requestBody)
39
+ });
40
+ if (!res.ok) {
41
+ throw new Error(
42
+ `Failed to execute query.
43
+ Query: ${sql}
44
+ Full error: ${res.status} ${await res.text()}}`
45
+ );
46
+ }
47
+ const queryResultSchema = z.object({
48
+ rows: z.array(z.unknown())
49
+ });
50
+ let rows;
51
+ try {
52
+ const json = await res.json();
53
+ rows = queryResultSchema.parse(json).rows;
54
+ } catch (e) {
55
+ throw new Error(
56
+ `Failed to execute query.
57
+ Query: ${sql}
58
+ Full error: Unexpected JSON response. ${e instanceof Error ? e.message : String(e)}`
59
+ );
60
+ }
61
+ const rowValues = [];
62
+ for (const row of rows) {
63
+ if (row != null && typeof row === "object") {
64
+ rowValues.push(Object.values(row));
65
+ }
66
+ }
67
+ if (method === "get") {
68
+ return { rows: rowValues[0] };
69
+ }
70
+ return { rows: rowValues };
71
+ });
72
+ return db;
73
+ }
74
+ export {
75
+ STUDIO_ADMIN_TABLE,
76
+ STUDIO_ADMIN_TABLE_ROW_ID,
77
+ STUDIO_MIGRATIONS_TABLE,
78
+ adminTable,
79
+ createRemoteDatabaseClient,
80
+ getAstroStudioEnv,
81
+ getRemoteDatabaseUrl,
82
+ getStudioUrl,
83
+ migrationsTable
84
+ };
@@ -0,0 +1,19 @@
1
+ import type { DBCollections } from './types.js';
2
+ import type { VitePlugin } from './utils.js';
3
+ export declare function vitePluginDb(params: {
4
+ connectToStudio: false;
5
+ collections: DBCollections;
6
+ dbUrl: string;
7
+ } | {
8
+ connectToStudio: true;
9
+ collections: DBCollections;
10
+ appToken: string;
11
+ }): VitePlugin;
12
+ export declare function getVirtualModContents({ collections, dbUrl, }: {
13
+ collections: DBCollections;
14
+ dbUrl: string;
15
+ }): string;
16
+ export declare function getStudioVirtualModContents({ collections, appToken, }: {
17
+ collections: DBCollections;
18
+ appToken: string;
19
+ }): string;
@@ -0,0 +1,66 @@
1
+ import { DRIZZLE_MOD_IMPORT, INTERNAL_MOD_IMPORT, VIRTUAL_MODULE_ID } from "./consts.js";
2
+ const resolvedVirtualModuleId = "\0" + VIRTUAL_MODULE_ID;
3
+ function vitePluginDb(params) {
4
+ return {
5
+ name: "astro:db",
6
+ enforce: "pre",
7
+ resolveId(id) {
8
+ if (id === VIRTUAL_MODULE_ID) {
9
+ return resolvedVirtualModuleId;
10
+ }
11
+ },
12
+ load(id) {
13
+ if (id !== resolvedVirtualModuleId)
14
+ return;
15
+ if (params.connectToStudio) {
16
+ return getStudioVirtualModContents(params);
17
+ }
18
+ return getVirtualModContents(params);
19
+ }
20
+ };
21
+ }
22
+ function getVirtualModContents({
23
+ collections,
24
+ dbUrl
25
+ }) {
26
+ return `
27
+ import { collectionToTable, createLocalDatabaseClient } from ${INTERNAL_MOD_IMPORT};
28
+
29
+ export const db = await createLocalDatabaseClient(${JSON.stringify({
30
+ collections,
31
+ dbUrl,
32
+ seeding: false
33
+ })});
34
+
35
+ export * from ${DRIZZLE_MOD_IMPORT};
36
+
37
+ ${getStringifiedCollectionExports(collections)}
38
+ `;
39
+ }
40
+ function getStudioVirtualModContents({
41
+ collections,
42
+ appToken
43
+ }) {
44
+ return `
45
+ import {collectionToTable, createRemoteDatabaseClient} from ${INTERNAL_MOD_IMPORT};
46
+
47
+ export const db = await createRemoteDatabaseClient(${JSON.stringify({
48
+ appToken
49
+ })});
50
+ export * from ${DRIZZLE_MOD_IMPORT};
51
+
52
+ ${getStringifiedCollectionExports(collections)}
53
+ `;
54
+ }
55
+ function getStringifiedCollectionExports(collections) {
56
+ return Object.entries(collections).map(
57
+ ([name, collection]) => `export const ${name} = collectionToTable(${JSON.stringify(name)}, ${JSON.stringify(
58
+ collection
59
+ )}, false)`
60
+ ).join("\n");
61
+ }
62
+ export {
63
+ getStudioVirtualModContents,
64
+ getVirtualModContents,
65
+ vitePluginDb
66
+ };
@@ -0,0 +1,9 @@
1
+ import type { VitePlugin } from './utils.js';
2
+ export declare function vitePluginInjectEnvTs({ srcDir, root }: {
3
+ srcDir: URL;
4
+ root: URL;
5
+ }): VitePlugin;
6
+ export declare function setUpEnvTs({ srcDir, root }: {
7
+ srcDir: URL;
8
+ root: URL;
9
+ }): Promise<void>;
@@ -0,0 +1,49 @@
1
+ import { existsSync } from "node:fs";
2
+ import { readFile, writeFile } from "node:fs/promises";
3
+ import path from "node:path";
4
+ import { fileURLToPath } from "node:url";
5
+ import { bold, cyan } from "kleur/colors";
6
+ import { normalizePath } from "vite";
7
+ import { DB_TYPES_FILE } from "./consts.js";
8
+ function vitePluginInjectEnvTs({ srcDir, root }) {
9
+ return {
10
+ name: "db-inject-env-ts",
11
+ enforce: "post",
12
+ async config() {
13
+ await setUpEnvTs({ srcDir, root });
14
+ }
15
+ };
16
+ }
17
+ async function setUpEnvTs({ srcDir, root }) {
18
+ const envTsPath = getEnvTsPath({ srcDir });
19
+ const envTsPathRelativetoRoot = normalizePath(
20
+ path.relative(fileURLToPath(root), fileURLToPath(envTsPath))
21
+ );
22
+ if (existsSync(envTsPath)) {
23
+ let typesEnvContents = await readFile(envTsPath, "utf-8");
24
+ const dotAstroDir = new URL(".astro/", root);
25
+ if (!existsSync(dotAstroDir))
26
+ return;
27
+ const dbTypeReference = getDBTypeReference({ srcDir, dotAstroDir });
28
+ if (!typesEnvContents.includes(dbTypeReference)) {
29
+ typesEnvContents = `${dbTypeReference}
30
+ ${typesEnvContents}`;
31
+ await writeFile(envTsPath, typesEnvContents, "utf-8");
32
+ console.info(`${cyan(bold("[astro:db]"))} Added ${bold(envTsPathRelativetoRoot)} types`);
33
+ }
34
+ }
35
+ }
36
+ function getDBTypeReference({ srcDir, dotAstroDir }) {
37
+ const dbTypesFile = new URL(DB_TYPES_FILE, dotAstroDir);
38
+ const contentTypesRelativeToSrcDir = normalizePath(
39
+ path.relative(fileURLToPath(srcDir), fileURLToPath(dbTypesFile))
40
+ );
41
+ return `/// <reference path=${JSON.stringify(contentTypesRelativeToSrcDir)} />`;
42
+ }
43
+ function getEnvTsPath({ srcDir }) {
44
+ return new URL("env.d.ts", srcDir);
45
+ }
46
+ export {
47
+ setUpEnvTs,
48
+ vitePluginInjectEnvTs
49
+ };
package/index.d.ts ADDED
@@ -0,0 +1,3 @@
1
+ /// <reference types="./config-augment.d.ts" />
2
+ export * from './dist/index.js';
3
+ export { default } from './dist/index.js';
package/package.json ADDED
@@ -0,0 +1,72 @@
1
+ {
2
+ "name": "@astrojs/db",
3
+ "version": "0.1.0",
4
+ "description": "",
5
+ "license": "MIT",
6
+ "type": "module",
7
+ "types": "./index.d.ts",
8
+ "author": "withastro",
9
+ "exports": {
10
+ ".": {
11
+ "types": "./index.d.ts",
12
+ "import": "./dist/index.js"
13
+ },
14
+ "./components": "./components/index.ts",
15
+ "./internal": {
16
+ "types": "./dist/internal.d.ts",
17
+ "import": "./dist/internal.js"
18
+ },
19
+ "./internal-drizzle": {
20
+ "types": "./dist/internal-drizzle.d.ts",
21
+ "import": "./dist/internal-drizzle.js"
22
+ }
23
+ },
24
+ "typesVersions": {
25
+ "*": {
26
+ ".": [
27
+ "./index.d.ts"
28
+ ],
29
+ "internal": [
30
+ "./dist/internal.d.ts"
31
+ ]
32
+ }
33
+ },
34
+ "files": [
35
+ "index.d.ts",
36
+ "config-augment.d.ts",
37
+ "dist",
38
+ "components"
39
+ ],
40
+ "dependencies": {
41
+ "@libsql/client": "0.4.0-pre.5",
42
+ "deep-diff": "^1.0.2",
43
+ "drizzle-orm": "^0.28.6",
44
+ "kleur": "^4.1.5",
45
+ "nanoid": "^5.0.1",
46
+ "prompts": "^2.4.2",
47
+ "yargs-parser": "^21.1.1",
48
+ "zod": "^3.22.4"
49
+ },
50
+ "devDependencies": {
51
+ "@types/deep-diff": "^1.0.5",
52
+ "@types/diff": "^5.0.8",
53
+ "@types/yargs-parser": "^21.0.3",
54
+ "@types/chai": "^4.3.6",
55
+ "@types/mocha": "^10.0.2",
56
+ "@types/prompts": "^2.4.8",
57
+ "chai": "^4.3.10",
58
+ "cheerio": "1.0.0-rc.12",
59
+ "mocha": "^10.2.0",
60
+ "typescript": "^5.2.2",
61
+ "vite": "^4.4.11",
62
+ "astro": "4.2.1",
63
+ "astro-scripts": "0.0.14"
64
+ },
65
+ "scripts": {
66
+ "build": "astro-scripts build \"src/**/*.ts\" && tsc",
67
+ "build:ci": "astro-scripts build \"src/**/*.ts\"",
68
+ "dev": "astro-scripts dev \"src/**/*.ts\"",
69
+ "test": "mocha --exit --timeout 20000",
70
+ "test:match": "mocha --timeout 20000 -g"
71
+ }
72
+ }