alinea
Version:
Headless git-based CMS
112 lines (110 loc) • 3.31 kB
JavaScript
import "../chunks/chunk-NZLE2WMY.js";
// src/core/Scope.ts
import { Expr } from "./Expr.js";
import { getExpr, hasExpr } from "./Internal.js";
import { entries } from "./util/Objects.js";
var scopes = /* @__PURE__ */ new WeakMap();
var ENTITY_KEY = "@alinea.Entity";
var EXPR_KEY = "@alinea.Expr";
var ScopeKey = {
workspace(workspace) {
return `Workspace.${workspace}`;
},
root(workspace, root) {
return `Root.${workspace}.${root}`;
},
page(workspace, root, page) {
return `Page.${workspace}.${root}.${page}`;
},
type(type) {
return `Type.${type}`;
},
field(type, field) {
return `Field.${type}.${field}`;
},
entry(entryId) {
return `Entry.${entryId}`;
}
};
var Scope = class {
#keys = /* @__PURE__ */ new Map();
#paths = /* @__PURE__ */ new Map();
constructor(config) {
for (const [workspaceName, workspace] of entries(config.workspaces)) {
this.#insert(workspace, ScopeKey.workspace(workspaceName));
for (const [rootName, root] of entries(workspace)) {
this.#insert(root, ScopeKey.root(workspaceName, rootName));
for (const [pageName, page] of entries(root)) {
this.#insert(page, ScopeKey.page(workspaceName, rootName, pageName));
}
}
}
for (const [typeName, type] of entries(config.schema)) {
this.#insert(type, ScopeKey.type(typeName));
for (const [fieldName, field] of entries(type)) {
this.#insert(field, ScopeKey.field(typeName, fieldName));
}
}
}
workspaceOf(root) {
const path = this.#paths.get(root);
if (!path) throw new Error(`Root not found in scope: ${root}`);
return this.#keys.get(path[0]);
}
keyOf(entity) {
const path = this.#paths.get(entity);
if (!path) throw new Error(`Entity not found in scope: ${entity}`);
return path.join(".");
}
locationOf(entity) {
return this.#paths.get(entity)?.slice(1);
}
nameOf(entity) {
return this.#paths.get(entity)?.at(-1);
}
stringify(input) {
const result = JSON.stringify(input, (key, value) => {
if (this.#paths.has(value))
return { [ENTITY_KEY]: this.#paths.get(value)?.join(".") };
if (value && typeof value === "object" && hasExpr(value))
return { [EXPR_KEY]: getExpr(value) };
return value;
});
return result;
}
parse(input) {
const result = JSON.parse(input, (key, value) => {
if (value && typeof value === "object") {
const props = Object.keys(value);
if (props.length === 1) {
const [key2] = props;
if (key2 === ENTITY_KEY) return this.#keys.get(value[key2]);
if (key2 === EXPR_KEY) return new Expr(value[key2]);
}
}
return value;
});
return result;
}
#insert(entity, key) {
const exists = this.#paths.get(entity);
const segments = key.split(".");
if (exists)
throw new Error(
`${segments[0]} '${segments.slice(1).join(".")}' is already in use at '${exists.slice(1).join(".")}' \u2014 ${segments[0]}s must be unique`
);
this.#paths.set(entity, segments);
this.#keys.set(key, entity);
}
};
function getScope(config) {
if (!scopes.has(config)) {
scopes.set(config, new Scope(config));
}
return scopes.get(config);
}
export {
Scope,
ScopeKey,
getScope
};