Skip to content

Commit

Permalink
store: add native support (base + memory driver)
Browse files Browse the repository at this point in the history
  • Loading branch information
terrablue committed Jul 21, 2024
1 parent b4823bb commit c60e696
Show file tree
Hide file tree
Showing 39 changed files with 306 additions and 290 deletions.
1 change: 1 addition & 0 deletions packages/core/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
"./logger": "./src/shared/Logger.js",
"./logger/print": "./src/shared/print.js",
"./logger/error": "./src/shared/error.js",
"./logger/warn": "./src/shared/warn.js",
"./config": "./src/shared/primate.config.js",
"./handlers/*": "./src/serve/handlers/*.js"
}
Expand Down
37 changes: 21 additions & 16 deletions packages/core/src/build/hooks/build.js
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ const pre = async (app, mode, target) => {
resolveDir: app.path.build.path,
},
}, mode);
app.server_build = ["routes"];

// remove build directory in case exists
await app.path.build.remove();
Expand All @@ -38,20 +39,20 @@ const pre = async (app, mode, target) => {
};

const js_re = /^.*.js$/u;
const write_routes = async (build_directory, app) => {
const location = app.get("location");
const d = app.runpath(location.routes);
const e = await Promise.all((await File.collect(d, js_re, { recursive: true }))
.map(async file => `${file}`.replace(d, _ => "")));

const routes_js = `
const routes = [];
${e.map((route, i) =>
`import * as route${i} from "../routes${route}";
routes.push(["${route.slice(1, -".js".length)}", route${i}]);`,
const write_directories = async (build_directory, app) => {
for (const name of app.server_build) {
const d = app.runpath(name);
const e = await Promise.all((await File.collect(d, js_re, { recursive: true }))
.map(async file => `${file}`.replace(d, _ => "")));
const files_js = `
const ${name} = [];
${e.map((file , i) =>
`import * as ${name}${i} from "../${name}${file}";
${name}.push(["${file.slice(1, -".js".length)}", ${name}${i}]);`,
).join("\n")}
export default routes;`;
await build_directory.join("routes.js").write(routes_js);
export default ${name};`;
await build_directory.join(`${name}.js`).write(files_js);
}
};

const write_components = async (build_directory, app) => {
Expand Down Expand Up @@ -80,14 +81,18 @@ const write_bootstrap = async (build_number, app) => {
import { File } from "rcompat/fs";
import serve from "@primate/core/serve";
import config from "./primate.config.js";
import routes from "./${build_number}/routes.js";
const files = {};
${app.server_build.map(name =>
`import ${name} from "./${build_number}/${name}.js";
files.${name} = ${name};`,
).join("\n")}
import components from "./${build_number}/components.js";
import * as target from "./target.js";
await serve(new File(import.meta.url).directory, {
...target,
config,
routes,
files,
components,
});`;
await app.path.build.join("serve.js").write(build_start_script);
Expand Down Expand Up @@ -147,8 +152,8 @@ const post = async (app, target) => {
// TODO: remove after rcompat automatically creates directories
await build_directory.create();

await write_routes(build_directory, app);
await write_components(build_directory, app);
await write_directories(build_directory, app);
await write_bootstrap(build_number, app);

const c = "primate.config.js";
Expand Down
7 changes: 3 additions & 4 deletions packages/core/src/serve/app.js
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ const render_head = (assets, fonts, head) =>
tags.font({ href, type: "font/woff2" }),
).join("\n"));

export default async (log, root, { config, assets, routes, components, loader, target }) => {
export default async (log, root, { config, assets, files, components, loader, target }) => {
const { http } = config;
const secure = http?.ssl !== undefined;
const path = O.valmap(config.location, value => root.join(value));
Expand All @@ -76,7 +76,7 @@ export default async (log, root, { config, assets, routes, components, loader, t
secure,
importmaps: {},
assets,
routes,
files,
path,
root,
log,
Expand Down Expand Up @@ -106,7 +106,7 @@ export default async (log, root, { config, assets, routes, components, loader, t
};
},
runpath(...directories) {
return this.path.build.join(...directories);
return this.root.join(...directories);
},
async render(content) {
const { body, head, partial, placeholders = {}, page } = content;
Expand Down Expand Up @@ -142,7 +142,6 @@ export default async (log, root, { config, assets, routes, components, loader, t
return { head, integrity: `'${integrity}'` };
},
async publish({ src, code, type = "", inline = false }) {
console.log(src, code);
if (inline || type === "style") {
this.assets.push({
src: File.join(http.static.root, src ?? "").path,
Expand Down
8 changes: 3 additions & 5 deletions packages/core/src/serve/hooks/serve.js
Original file line number Diff line number Diff line change
@@ -1,15 +1,13 @@
import { cascade, tryreturn } from "rcompat/async";
import { dim } from "rcompat/colors";
import { File, Router } from "rcompat/fs";
import { Router } from "rcompat/fs";
import { serve, Status } from "rcompat/http";
import dispatch from "../dispatch.js";
import * as loaders from "../loaders/exports.js";
import * as hooks from "./exports.js";

const post = async app => {
const location = app.get("location");
const http = app.get("http");
const client = app.runpath(app.get("location.client"));
const user_types = await loaders.types(app.log, app.runpath(location.types));
const types = { ...app.types, ...user_types };
let router;
Expand All @@ -24,9 +22,9 @@ const post = async app => {
predicate(route, request) {
return route.default[request.method.toLowerCase()] !== undefined;
},
}, app.routes);
}, app.files.routes);
} catch (error) {
//console.log("YYYOYOOO", error);
//console.log(error);
}

app.create_csp();
Expand Down
4 changes: 4 additions & 0 deletions packages/core/src/shared/warn.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
import { throwable } from "./Logger.js";

export default ({ message, fix, name, module }) =>
throwable({ message, fix, level: "Warn" }, name, module);
4 changes: 2 additions & 2 deletions packages/frontend/src/base/server/depend.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import MissingDependencies from "@primate/frontend/errors/missing-dependencies";
import NoDependencies from "@primate/frontend/errors/no-dependencies";
import { tryreturn } from "rcompat/async";
import * as O from "rcompat/object";
import { manifest, packager } from "rcompat/package";
Expand All @@ -22,7 +22,7 @@ export default async (on, name) => {
.map(([key, value]) => `${key}@${value}`);
if (errored.length > 0) {
const install = module => `${packager()} install ${module.join(" ")}`;
MissingDependencies.throw(errored.join(", "), from, install(versions));
NoDependencies.throw(errored.join(", "), from, install(versions));
}
return results.filter(result => typeof result !== "string");
};
16 changes: 8 additions & 8 deletions packages/frontend/src/base/server/load.js
Original file line number Diff line number Diff line change
@@ -1,23 +1,23 @@
import ErrorInComponent from "@primate/frontend/errors/error-in-component";
import MissingComponent from "@primate/frontend/errors/missing-component";
import ComponentError from "@primate/frontend/errors/component-error";
import NoComponent from "@primate/frontend/errors/no-component";
import { tryreturn } from "rcompat/async";
import { File } from "rcompat/fs";

const MODULE_NOT_FOUND = "ERR_MODULE_NOT_FOUND";
const in_component = (code, error_path, component_path) =>
code === MODULE_NOT_FOUND && File.same(error_path, component_path);

const missing_component = (name, path) => {
MissingComponent.throw(name, path);
const no_component = (name, path) => {
NoComponent.throw(name, path);
};
const error_in_component = (name, path, error) => {
const component_error = (name, path, error) => {
console.log(error);
ErrorInComponent.throw(name, path);
ComponentError.throw(name, path);
};
const get_error = (error, path) =>
in_component(error.code, new File(error.url), new File(path))
? missing_component
: error_in_component
? no_component
: component_error
;

export default async path =>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import error from "@primate/core/logger/error";

export default error({
name: "ErrorInComponent",
name: "ComponentError",
message: "error in component {0}",
fix: "fix previous error in {1}",
module: "primate/frontend",
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import error from "@primate/core/logger/error";

export default error({
name: "MissingComponentClassName",
name: "NoClassName",
message: "the component at {0} is missing a class name",
fix: "add a class name to the component",
module: "primate/frontend/webc",
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import error from "@primate/core/logger/error";

export default error({
name: "MissingClientSideTemplateDependency",
name: "NoClientExtension",
message: "the extension {0} is required for {1} client side support",
fix: "add \"{0}\" to the `extensions` array for the HTMX module",
module: "primate/frontend/htmx",
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import error from "@primate/core/logger/error";

export default error({
name: "MissingComponent",
name: "NoComponent",
message: "missing component {0}",
fix: "create {1} or remove route function",
module: "primate/frontend",
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import error from "@primate/core/logger/error";

export default error({
name: "MissingDependencies",
name: "NoDependencies",
message: "cannot find {0} (imported from {1})",
fix: "install dependencies by issuing {2}",
module: "primate/frontend",
Expand Down
10 changes: 5 additions & 5 deletions packages/frontend/src/server/htmx/default/build.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import compile from "@primate/frontend/base/compile";
import depend from "@primate/frontend/base/depend";
import MissingClientSideTemplateDependency from
"@primate/frontend/errors/missing-client-side-template-dependency";
import NoClientExtension from "@primate/frontend/errors/no-client-extension";
import { dependencies, name } from "@primate/frontend/htmx/common";
import * as O from "rcompat/object";
import { server } from "./compile.js";
Expand Down Expand Up @@ -32,9 +31,10 @@ export default ({
app.build.export(`export * from "${htmx_esm}/${extension_name}";`));

if (!O.empty(client_side_templates)) {
if (!extensions.includes(templates)) {
MissingClientSideTemplateDependency.throw(templates,
client_side_templates.join(", "));
const has_templates = extensions.includes(templates);
//app.assert(has_templates, nce(templates, client_side_templates.join(",")));
if (!has_templates) {
NoClientExtension.throw(templates, client_side_templates.join(", "));
}
client_side_templates.forEach(client_side_template =>
import_template[client_side_template](app));
Expand Down
6 changes: 3 additions & 3 deletions packages/frontend/src/server/webc/default/compile.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import MissingComponentClassName from
"@primate/frontend/errors/missing-component-class-name";
import NoClassName from "@primate/frontend/errors/no-class-name";
import { File } from "rcompat/fs";

const script_re = /(?<=<script)>(?<code>.*?)(?=<\/script>)/gus;
Expand All @@ -9,7 +8,8 @@ export const client = (app, extension) => async (text, component) => {
const [script] = await Promise.all([...text.matchAll(script_re)]
.map(({ groups: { code } }) => code));
const { name } = script.match(webc_class_name_re)?.groups ?? {};
name === undefined && MissingComponentClassName.throw(component);
// app.assert(name !== undefined, NoClassName._(component))
name === undefined && NoClassName.throw(component);
const tag = new File(component)
.debase(`${app.runpath(app.get("location.components"))}/`)
.path.replaceAll("/", "-").slice(0, -extension.length);
Expand Down
6 changes: 5 additions & 1 deletion packages/store/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -52,5 +52,9 @@
}
},
"type": "module",
"exports": "./src/exports.js"
"exports": {
".": "./src/index.js",
"./errors/*": "./src/errors/*.js",
"./drivers/memory": "./src/drivers/memory/index.js"
}
}
15 changes: 15 additions & 0 deletions packages/store/src/build.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import NoStoreDirectory from "@primate/store/errors/no-store-directory";

export default directory => async (app, next) => {
const root = app.root.join(directory);
if (!await root.exists()) {
NoStoreDirectory.warn(app.log, root);
return next(app);
}

await app.stage(app.root.join(directory), directory);

app.server_build.push("stores");

return next(app);
};
6 changes: 2 additions & 4 deletions packages/store/src/depend.js
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
import NoDependencies from "@primate/store/errors/no-dependencies";
import { tryreturn } from "rcompat/async";
import { packager } from "rcompat/package";
import errors from "./errors.js";

const { MissingDependencies } = errors;

export default async (dependencies, from) => {
const modules = Object.keys(dependencies);
Expand All @@ -16,7 +14,7 @@ export default async (dependencies, from) => {
.map(([key, value]) => `${key}@${value}`);
if (errored.length > 0) {
const install = module => `${packager()} install ${module.join(" ")}`;
MissingDependencies.throw(errored.join(", "), from, install(versions));
NoDependencies.throw(errored.join(", "), from, install(versions));
}
return results.filter(result => typeof result !== "string");
};
6 changes: 0 additions & 6 deletions packages/store/src/drivers/exports.js

This file was deleted.

4 changes: 2 additions & 2 deletions packages/store/src/drivers/memory/Facade.js
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ export default class Connection {
const documents = await this.#filter(name, criteria);
if (options.sort !== undefined) {
const sort = Object.entries(
o.valmap(options.sort, value => value === "asc" ? 1 : -1));
O.valmap(options.sort, value => value === "asc" ? 1 : -1));
documents.sort((d1, d2) => {
for (const [field, direction] of sort) {
if (d1[field] === d2[field]) {
Expand All @@ -86,7 +86,7 @@ export default class Connection {

return projection.length === 0
? documents
: documents.map(document => o.filter(document,
: documents.map(document => O.filter(document,
([key]) => projection.includes(key)));
}

Expand Down
File renamed without changes.
6 changes: 0 additions & 6 deletions packages/store/src/errors.js

This file was deleted.

Loading

0 comments on commit c60e696

Please sign in to comment.