Skip to content

Commit

Permalink
feat: add durable storage MVP
Browse files Browse the repository at this point in the history
  • Loading branch information
MasterPtato committed May 16, 2024
1 parent 911da30 commit c6d5e6e
Show file tree
Hide file tree
Showing 25 changed files with 828 additions and 73 deletions.
2 changes: 1 addition & 1 deletion artifacts/module_schema.json
Original file line number Diff line number Diff line change
@@ -1 +1 @@
{"type":"object","properties":{"status":{"enum":["beta","end_of_life","maintenance","preview","stable"],"type":"string"},"name":{"description":"The human readable name of the module.","type":"string"},"description":{"description":"A short description of the module.","type":"string"},"icon":{"description":"The [Font Awesome](https://fontawesome.com/icons) icon name of the module.","type":"string"},"tags":{"description":"The tags associated with this module.","type":"array","items":{"type":"string"}},"authors":{"description":"The GitHub handle of the authors of the module.","type":"array","items":{"type":"string"}},"scripts":{"type":"object","additionalProperties":{"$ref":"#/definitions/ScriptConfig"}},"errors":{"type":"object","additionalProperties":{"$ref":"#/definitions/ErrorConfig"}},"dependencies":{"type":"object","additionalProperties":{"$ref":"#/definitions/DependencyConfig"}}},"additionalProperties":false,"required":["errors","scripts"],"definitions":{"ScriptConfig":{"type":"object","properties":{"name":{"description":"The human readable name of the script.","type":"string"},"description":{"description":"A short description of the script.","type":"string"},"public":{"description":"If the script can be called from the public HTTP interface.\n\nIf enabled, ensure that authentication & rate limits are configured for\nthis endpoints. See the `user` and `rate_limit` modules.","default":false,"type":"boolean"}},"additionalProperties":false},"ErrorConfig":{"type":"object","properties":{"name":{"description":"The human readable name of the error.","type":"string"},"description":{"description":"A short description of the error.","type":"string"}},"additionalProperties":false},"DependencyConfig":{"type":"object","additionalProperties":false}},"$schema":"http://json-schema.org/draft-07/schema#"}
{"type":"object","properties":{"status":{"enum":["beta","end_of_life","maintenance","preview","stable"],"type":"string"},"name":{"description":"The human readable name of the module.","type":"string"},"description":{"description":"A short description of the module.","type":"string"},"icon":{"description":"The [Font Awesome](https://fontawesome.com/icons) icon name of the module.","type":"string"},"tags":{"description":"The tags associated with this module.","type":"array","items":{"type":"string"}},"authors":{"description":"The GitHub handle of the authors of the module.","type":"array","items":{"type":"string"}},"scripts":{"type":"object","additionalProperties":{"$ref":"#/definitions/ScriptConfig"}},"actors":{"type":"object","additionalProperties":{"$ref":"#/definitions/ActorConfig"}},"errors":{"type":"object","additionalProperties":{"$ref":"#/definitions/ErrorConfig"}},"dependencies":{"type":"object","additionalProperties":{"$ref":"#/definitions/DependencyConfig"}}},"additionalProperties":false,"required":["errors","scripts"],"definitions":{"ScriptConfig":{"type":"object","properties":{"name":{"description":"The human readable name of the script.","type":"string"},"description":{"description":"A short description of the script.","type":"string"},"public":{"description":"If the script can be called from the public HTTP interface.\n\nIf enabled, ensure that authentication & rate limits are configured for\nthis endpoints. See the `user` and `rate_limit` modules.","default":false,"type":"boolean"}},"additionalProperties":false},"ActorConfig":{"type":"object","properties":{"storage_id":{"description":"A globally unique string for storing data for this actor.\n\n**IMPORTANT** Changing this will effectively unlink all data stored in this actor. Changing it back to\nthe old value will restore the data.","type":"string"}},"additionalProperties":false,"required":["storage_id"]},"ErrorConfig":{"type":"object","properties":{"name":{"description":"The human readable name of the error.","type":"string"},"description":{"description":"A short description of the error.","type":"string"}},"additionalProperties":false},"DependencyConfig":{"type":"object","additionalProperties":false}},"$schema":"http://json-schema.org/draft-07/schema#"}
2 changes: 1 addition & 1 deletion artifacts/runtime_archive.json

Large diffs are not rendered by default.

27 changes: 27 additions & 0 deletions deno.lock
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
"version": "3",
"packages": {
"specifiers": {
"npm:@prisma/adapter-pg@^5.12.0": "npm:@prisma/adapter-pg@5.13.0_pg@8.11.3",
"npm:@prisma/adapter-pg@^5.9.1": "npm:@prisma/adapter-pg@5.9.1_pg@8.11.3",
"npm:@rivet-gg/esbuild-plugin-polyfill-node@^0.4.0": "npm:@rivet-gg/esbuild-plugin-polyfill-node@0.4.0_esbuild@0.20.0",
"npm:@types/node": "npm:@types/node@18.16.19",
Expand Down Expand Up @@ -146,6 +147,14 @@
"integrity": "sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==",
"dependencies": {}
},
"@prisma/adapter-pg@5.13.0_pg@8.11.3": {
"integrity": "sha512-7AlihIeGvEuuGlZcjv66KAcz/xiu3pqgZzihh+447CDgf8eC+YtuT4tKgewyuYVWDAFb/U1SefgnAjcjAxRrXg==",
"dependencies": {
"@prisma/driver-adapter-utils": "@prisma/driver-adapter-utils@5.13.0",
"pg": "pg@8.11.3",
"postgres-array": "postgres-array@3.0.2"
}
},
"@prisma/adapter-pg@5.9.1_pg@8.11.3": {
"integrity": "sha512-0RhnB1sqLmSzilbIQS75YE5qTNotlGvLWhTG7cp+F59VJdQ5sWWXZ1j2W4Tn+AMb116Yp4AuFe0vggW2f+ujiQ==",
"dependencies": {
Expand All @@ -154,6 +163,16 @@
"postgres-array": "postgres-array@3.0.2"
}
},
"@prisma/debug@5.13.0": {
"integrity": "sha512-699iqlEvzyCj9ETrXhs8o8wQc/eVW+FigSsHpiskSFydhjVuwTJEfj/nIYqTaWFYuxiWQRfm3r01meuW97SZaQ==",
"dependencies": {}
},
"@prisma/driver-adapter-utils@5.13.0": {
"integrity": "sha512-SaimwvGuvXJTsWH+FOfl7PlkZZlPiRGeMEchC0kvB08Xw9B3CLYo/Q7zaY5Fp+u5D8asrpcFQmCjXEgDvOmPkg==",
"dependencies": {
"@prisma/debug": "@prisma/debug@5.13.0"
}
},
"@prisma/driver-adapter-utils@5.9.1": {
"integrity": "sha512-1h1+6kU3PfsE2CvQoU49Jt7yrXybU0C/H/+W8Bh0pJefMAbTY8KoWssYXgwQp1PUKBtdh1GDQsMf9ojFeQ0RWg==",
"dependencies": {
Expand Down Expand Up @@ -725,7 +744,9 @@
},
"redirects": {
"https://esm.sh/@neondatabase/serverless@^0.9.0": "https://esm.sh/@neondatabase/serverless@0.9.0",
"https://esm.sh/@neondatabase/serverless@^0.9.3": "https://esm.sh/@neondatabase/serverless@0.9.3",
"https://esm.sh/@prisma/adapter-neon@^5.10.2": "https://esm.sh/@prisma/adapter-neon@5.10.2",
"https://esm.sh/@prisma/adapter-neon@^5.13.0": "https://esm.sh/@prisma/adapter-neon@5.13.0",
"https://esm.sh/ajv-formats@^2.1.1": "https://esm.sh/ajv-formats@2.1.1",
"https://esm.sh/ajv@^8.12.0": "https://esm.sh/ajv@8.12.0",
"https://esm.sh/pg@^8.11.3": "https://esm.sh/pg@8.11.3",
Expand Down Expand Up @@ -2550,14 +2571,20 @@
"https://deno.land/x/wasmbuild@0.14.1/cache.ts": "89eea5f3ce6035a1164b3e655c95f21300498920575ade23161421f5b01967f4",
"https://deno.land/x/wasmbuild@0.14.1/loader.ts": "d98d195a715f823151cbc8baa3f32127337628379a02d9eb2a3c5902dbccfc02",
"https://esm.sh/@neondatabase/serverless@0.9.0": "3007f35c946e1ce273f644f2bfee27a9de48d1fbe332dab9d53566d12080e22d",
"https://esm.sh/@neondatabase/serverless@0.9.3": "44d18e016ebf3ce55f3e87f8f65976f6e8ff0624faafff1625bf6dd5863d21c6",
"https://esm.sh/@prisma/adapter-neon@5.10.2": "0139f84d719977a05264596fef6bb34e4d0e9ddf15f73d6fd9ec6ff203a8d432",
"https://esm.sh/@prisma/adapter-neon@5.13.0": "5b223ec54e4893e0191797043fda7eedbea8b3442f683e55a48633c5bad4b263",
"https://esm.sh/ajv-formats@2.1.1": "575b3830618970ddc3aba96310bf4df7358bb37fcea101f58b36897ff3ac2ea7",
"https://esm.sh/ajv@8.12.0": "cc1a73af661466c7f4e6a94d93ece78542d700f2165bdb16a531e9db8856c5aa",
"https://esm.sh/v135/@neondatabase/serverless@0.8.1/denonext/serverless.mjs": "a45acb984910225aa035c9787133d117fb585d6d62536238e135580cf6a0a695",
"https://esm.sh/v135/@neondatabase/serverless@0.9.0/denonext/serverless.mjs": "170ea3600a913c22aa959044968d73c6a214f17ce6ea60ce2002d4e9225f2491",
"https://esm.sh/v135/@neondatabase/serverless@0.9.3/denonext/serverless.mjs": "5351e9d60196cfbec4e83de6a91fd2878c201a9d79262248fd615373725eb061",
"https://esm.sh/v135/@prisma/adapter-neon@5.10.2/denonext/adapter-neon.mjs": "3639e2b49242e394582e1e36623a62ab75c60a487c502bc6d9665944531728dc",
"https://esm.sh/v135/@prisma/adapter-neon@5.13.0/denonext/adapter-neon.mjs": "964ca03df72d71669e519581e826dce6c21208e2530b2be6c1b283d4efa1542a",
"https://esm.sh/v135/@prisma/debug@5.10.2/denonext/debug.mjs": "cab0a6f1eb5df296ddf9b9590519e6bdc851bfad482961b7bd25e5bfe1cc428c",
"https://esm.sh/v135/@prisma/debug@5.13.0/denonext/debug.mjs": "f9422affb4aed3f33c884f52160531fabb7f3bd311ad15e99be3796640533e6f",
"https://esm.sh/v135/@prisma/driver-adapter-utils@5.10.2/denonext/driver-adapter-utils.mjs": "2266fc26eebd8821b502bb0ada2488062259b3b4d8188cd5692e13f14caa174c",
"https://esm.sh/v135/@prisma/driver-adapter-utils@5.13.0/denonext/driver-adapter-utils.mjs": "db5e5076ba2dab34d8ccb96dc211dbab04fa3a3d25ef648a34689c85e8f34612",
"https://esm.sh/v135/ajv-formats@2.1.1/denonext/ajv-formats.mjs": "06092e00b42202633ae6dab4b53287c133af882ddb14c6707277cdb237634967",
"https://esm.sh/v135/ajv@8.12.0/denonext/ajv.mjs": "4645df9093d0f8be0e964070a4a7aea8adea06e8883660340931f7a3f979fc65",
"https://esm.sh/v135/ajv@8.12.0/denonext/dist/compile/codegen.js": "d981238e5b1e78217e1c6db59cbd594369279722c608ed630d08717ee44edd84",
Expand Down
60 changes: 51 additions & 9 deletions src/build/entrypoint.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,16 @@
import { resolve } from "../deps.ts";
import { dirname, fromFileUrl, resolve } from "../deps.ts";
import { Project } from "../project/mod.ts";
import { genRegistryMapPath, genRuntimeModPath, genRuntimePath } from "../project/project.ts";
import { CommandError } from "../error/mod.ts";
import { autoGenHeader } from "./misc.ts";
import { BuildOpts, DbDriver, Runtime } from "./mod.ts";
import { dedent } from "./deps.ts";

const ACTOR_SOURCE = await Deno.readTextFile(resolve(dirname(fromFileUrl(import.meta.url)), "../dynamic/actor.ts"));
const ACTOR_CF_SOURCE = await Deno.readTextFile(
resolve(dirname(fromFileUrl(import.meta.url)), "../dynamic/actor_cf.ts"),
);

export async function generateEntrypoint(project: Project, opts: BuildOpts) {
const runtimeModPath = genRuntimeModPath(project);
const registryMapPath = genRegistryMapPath(project);
Expand All @@ -24,19 +29,27 @@ export async function generateEntrypoint(project: Project, opts: BuildOpts) {
} else if (opts.dbDriver == DbDriver.NeonServerless) {
imports += `
// Import Prisma serverless adapter for Neon
import * as neon from "https://esm.sh/@neondatabase/serverless@^0.9.0";
import { PrismaNeonHTTP } from "https://esm.sh/@prisma/adapter-neon@^5.10.2";
import * as neon from "https://esm.sh/@neondatabase/serverless@^0.9.3";
import { PrismaNeonHTTP } from "https://esm.sh/@prisma/adapter-neon@^5.13.0";
`;
}

let compat = "";
let actorSource = `
import { Config } from "${runtimeModPath}";
import config from "./runtime_config.ts";
`;

if (opts.runtime == Runtime.Deno) {
compat += `
// Create module for Prisma compatibility
import { createRequire } from "node:module";
const require = createRequire(import.meta.url);
`;

actorSource += ACTOR_SOURCE;
} else {
actorSource += ACTOR_CF_SOURCE;
}

// Generate config.ts
Expand All @@ -60,12 +73,17 @@ export async function generateEntrypoint(project: Project, opts: BuildOpts) {
entrypointSource = `
${autoGenHeader()}
import { Runtime } from "${runtimeModPath}";
import { camelToSnake } from "${registryMapPath};
import type { Registry, RegistryCamel } from "./registry.d.ts";
import { camelToSnake, actorCamelToSnake } from "${registryMapPath};
import type { Registry, RegistryCamel, ActorRegistry, ActorRegistryCamel } from "./registry.d.ts";
import config from "./runtime_config.ts";
import { ACTOR_DRIVER } from "./actor.ts";
async function main() {
const runtime = new Runtime<Registry, RegistryCamel>(config, camelToSnake);
const runtime = new Runtime<
Registry, RegistryCamel, ActorRegistry, ActorRegistryCamel
>(
config, ACTOR_DRIVER, camelToSnake, actorCamelToSnake
);
await runtime.serve();
}
Expand All @@ -81,12 +99,17 @@ export async function generateEntrypoint(project: Project, opts: BuildOpts) {
import type { IncomingRequestCf } from 'https://raw.githubusercontent.com/skymethod/denoflare/v0.6.0/common/cloudflare_workers_types.d.ts';
import { Runtime } from "${runtimeModPath}";
import { RuntimeError } from "${errorTsPath}";
import { camelToSnake } from "${registryMapPath}";
import type { Registry, RegistryCamel } from "./registry.d.ts";
import { camelToSnake, actorCamelToSnake } from "${registryMapPath}";
import type { Registry, RegistryCamel, ActorRegistry, ActorRegistryCamel } from "./registry.d.ts";
import config from "./runtime_config.ts";
import { ACTOR_DRIVER } from "./actor.ts";
import { serverHandler } from "${serverTsPath}";
const RUNTIME = new Runtime<Registry, RegistryCamel>(config, camelToSnake);
const RUNTIME = new Runtime<
Registry, RegistryCamel, ActorRegistry, ActorRegistryCamel
>(
config, ACTOR_DRIVER, camelToSnake, actorCamelToSnake
);
const SERVER_HANDLER = serverHandler(RUNTIME);
export default {
Expand All @@ -110,20 +133,25 @@ export async function generateEntrypoint(project: Project, opts: BuildOpts) {
});
}
}
// Export durable object binding
export { __GlobalDurableObject } from "./actor.ts";
`;
}

// Write files
const distDir = resolve(project.path, "_gen");
const configPath = resolve(distDir, "runtime_config.ts");
const entrypointPath = resolve(distDir, "entrypoint.ts");
const actorPath = resolve(distDir, "actor.ts");
await Deno.mkdir(distDir, { recursive: true });
await Deno.writeTextFile(configPath, configSource);
await Deno.writeTextFile(entrypointPath, entrypointSource);
await Deno.writeTextFile(
resolve(distDir, ".gitignore"),
".",
);
await Deno.writeTextFile(actorPath, actorSource);

// Format files
const fmtOutput = await new Deno.Command("deno", {
Expand Down Expand Up @@ -155,6 +183,20 @@ function generateModImports(project: Project, opts: BuildOpts) {
}
modConfig += "},";

// Generate actor configs
modConfig += "actors: {";
for (const actor of mod.actors.values()) {
const actorIdent = `modules$$${mod.name}$$${actor.name}$$Actor`;

modImports += `import { Actor as ${actorIdent} } from '${mod.path}/actors/${actor.name}.ts';\n`;

modConfig += `${JSON.stringify(actor.name)}: {`;
modConfig += `actor: ${actorIdent},`;
modConfig += `storageId: ${JSON.stringify(actor.config.storage_id)},`;
modConfig += `},`;
}
modConfig += "},";

// Generate error configs
modConfig += `errors: ${JSON.stringify(mod.config.errors)},`;

Expand Down
Loading

0 comments on commit c6d5e6e

Please sign in to comment.