tsondb 0.12.2 → 0.12.3

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.
@@ -41,6 +41,7 @@ gitApi.get("/status", async (req, res) => {
41
41
  // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
42
42
  req.entitiesByName[entityName], instance, req.getInstanceById, getChildInstancesForInstanceId, req.locales)),
43
43
  ])),
44
+ latestCommit: await req.git.revparse(["HEAD"]),
44
45
  };
45
46
  res.json(body);
46
47
  });
@@ -15,7 +15,8 @@ instancesApi.get("/", (req, res) => {
15
15
  .filter(([entityName]) => Object.hasOwn(req.entitiesByName, entityName))
16
16
  .map(([entityName, instances]) => [
17
17
  entityName,
18
- instances.map(instance => {
18
+ instances
19
+ .map(instance => {
19
20
  const { name, localeId } = getDisplayNameFromEntityInstance(
20
21
  // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
21
22
  req.entitiesByName[entityName], instance, req.getInstanceById, getChildInstancesForInstanceId, req.locales);
@@ -24,7 +25,8 @@ instancesApi.get("/", (req, res) => {
24
25
  name,
25
26
  displayNameLocaleId: localeId,
26
27
  };
27
- }),
28
+ })
29
+ .toSorted((a, b) => a.name.localeCompare(b.name, a.displayNameLocaleId)),
28
30
  ])),
29
31
  };
30
32
  res.json(body);
@@ -24,6 +24,7 @@ export interface TSONDBRequestLocals {
24
24
  locales: string[];
25
25
  homeLayoutSections?: HomeLayoutSection[];
26
26
  getInstanceById: GetInstanceById;
27
+ setLocal: <K extends keyof Omit<TSONDBRequestLocals, "setLocal">>(key: K, value: TSONDBRequestLocals[K]) => void;
27
28
  }
28
29
  export type GetInstanceById = (id: string) => {
29
30
  entity: EntityDecl;
@@ -30,6 +30,9 @@ export const createServer = async (schema, dataRootPath, instancesByEntityName,
30
30
  const requestLocals = await init(schema, dataRootPath, Object.assign({}, instancesByEntityName), defaultLocales, homeLayoutSections);
31
31
  app.use((req, _res, next) => {
32
32
  debug("%s %s", req.method, req.originalUrl);
33
+ requestLocals.setLocal = (key, value) => {
34
+ requestLocals[key] = req[key] = value;
35
+ };
33
36
  Object.assign(req, requestLocals);
34
37
  req.locales = getLocalesFromRequest(req) ?? defaultLocales;
35
38
  next();
@@ -2,5 +2,5 @@ import type { InstancesByEntityName } from "../../shared/utils/instances.ts";
2
2
  import type { HomeLayoutSection } from "../config.ts";
3
3
  import type { Schema } from "../schema/Schema.ts";
4
4
  import type { TSONDBRequestLocals } from "./index.ts";
5
- export declare const init: (schema: Schema, dataRootPath: string, instancesByEntityName: InstancesByEntityName, defaultLocales: string[], homeLayoutSections?: HomeLayoutSection[]) => Promise<TSONDBRequestLocals>;
5
+ export declare const init: (schema: Schema, dataRootPath: string, instancesByEntityName: InstancesByEntityName, defaultLocales: string[], homeLayoutSections?: HomeLayoutSection[]) => Promise<Omit<TSONDBRequestLocals, "setLocal">>;
6
6
  export declare const reinit: (locals: TSONDBRequestLocals) => Promise<void>;
@@ -29,7 +29,6 @@ export const init = async (schema, dataRootPath, instancesByEntityName, defaultL
29
29
  debug("found %d entities in declarations", entities.length);
30
30
  const entitiesByName = Object.fromEntries(entities.map(entity => [entity.name, entity]));
31
31
  const serializedDeclarationsByName = Object.fromEntries(declarations.map(decl => [decl.name, serializeNode(decl)]));
32
- const instancesByEntityNameInMemory = Object.assign({}, instancesByEntityName);
33
32
  const referencesToInstances = await getReferencesToInstances(instancesByEntityName, serializedDeclarationsByName);
34
33
  debug("created references cache");
35
34
  if (gitStatus) {
@@ -37,10 +36,10 @@ export const init = async (schema, dataRootPath, instancesByEntityName, defaultL
37
36
  debug("retrieved git status to instances");
38
37
  }
39
38
  const getInstanceById = id => {
40
- for (const entityName in instancesByEntityNameInMemory) {
41
- const instance = instancesByEntityNameInMemory[entityName]?.find(i => i.id === id);
42
- if (instance && entitiesByName[entityName]) {
43
- return { entity: entitiesByName[entityName], instance };
39
+ for (const entityName in requestLocals.instancesByEntityName) {
40
+ const instance = requestLocals.instancesByEntityName[entityName]?.find(i => i.id === id);
41
+ if (instance && requestLocals.entitiesByName[entityName]) {
42
+ return { entity: requestLocals.entitiesByName[entityName], instance };
44
43
  }
45
44
  }
46
45
  return undefined;
@@ -51,7 +50,7 @@ export const init = async (schema, dataRootPath, instancesByEntityName, defaultL
51
50
  dataRoot: dataRootPath,
52
51
  declarations: declarations,
53
52
  entities: entities,
54
- instancesByEntityName: instancesByEntityNameInMemory,
53
+ instancesByEntityName: Object.assign({}, instancesByEntityName),
55
54
  entitiesByName: entitiesByName,
56
55
  serializedDeclarationsByName,
57
56
  localeEntity: schema.localeEntity,
@@ -64,8 +63,8 @@ export const init = async (schema, dataRootPath, instancesByEntityName, defaultL
64
63
  return requestLocals;
65
64
  };
66
65
  export const reinit = async (locals) => {
67
- locals.instancesByEntityName = await getInstancesByEntityName(locals.dataRoot, locals.entities);
68
- locals.referencesToInstances = await getReferencesToInstances(locals.instancesByEntityName, locals.serializedDeclarationsByName);
66
+ locals.setLocal("instancesByEntityName", await getInstancesByEntityName(locals.dataRoot, locals.entities));
67
+ locals.setLocal("referencesToInstances", await getReferencesToInstances(locals.instancesByEntityName, locals.serializedDeclarationsByName));
69
68
  const gitStatus = (await locals.git.checkIsRepo()) ? await locals.git.status() : undefined;
70
69
  if (locals.gitRoot && gitStatus) {
71
70
  attachGitStatusToInstancesByEntityName(locals.instancesByEntityName, locals.dataRoot, locals.gitRoot, gitStatus);
@@ -42,11 +42,11 @@ export const createInstance = async (locals, instance, idQueryParam) => {
42
42
  if (isError(res)) {
43
43
  return res;
44
44
  }
45
- const treeRes = await unsafeApplyInstanceTree(locals.dataRoot, locals.entitiesByName, locals.instancesByEntityName, instance.id, instance.entityName, [], instance.childInstances);
45
+ const newInstanceId = res.value;
46
+ const treeRes = await unsafeApplyInstanceTree(locals.dataRoot, locals.entitiesByName, locals.instancesByEntityName, newInstanceId, instance.entityName, [], instance.childInstances);
46
47
  if (isError(treeRes)) {
47
48
  return treeRes;
48
49
  }
49
- const newInstanceId = res.value;
50
50
  const instanceContainer = await updateLocalsAfterInstanceChangeToReflectDiskState(locals, entity.name, newInstanceId, instance.content);
51
51
  await updateLocalsAfterInstanceTreeChangeToReflectDiskState(locals, newInstanceId, entity.name, [], instance.childInstances);
52
52
  return ok(instanceContainer);
@@ -64,6 +64,7 @@ export interface GitStatusResponseBody {
64
64
  instances: {
65
65
  [entity: string]: InstanceContainerOverview[];
66
66
  };
67
+ latestCommit: string;
67
68
  }
68
69
  export interface GetAllGitBranchesResponseBodyBranchSummary {
69
70
  current: boolean;
@@ -36,11 +36,13 @@ export const InstanceRouteSkeleton = ({ mode, buttons, init, titleBuilder, onSub
36
36
  const [instanceNamesByEntity] = useInstanceNamesByEntity();
37
37
  const [instanceContent, setInstanceContent] = useState();
38
38
  const [savedInstanceContent, setSavedInstanceContent] = useState();
39
+ const [savedChildInstances, setSavedChildInstances] = useState([]);
39
40
  const [childInstances, setChildInstances] = useState([]);
40
41
  const [customId, setCustomId] = useState("");
41
42
  const client = useContext(GitClientContext);
42
43
  const { route } = useLocation();
43
- const hasUnsavedChanges = useMemo(() => !deepEqual(instanceContent, savedInstanceContent), [instanceContent, savedInstanceContent]);
44
+ const hasUnsavedChanges = useMemo(() => !deepEqual(instanceContent, savedInstanceContent) ||
45
+ !deepEqual(childInstances, savedChildInstances), [childInstances, instanceContent, savedChildInstances, savedInstanceContent]);
44
46
  const saveHandler = useCallback((event) => {
45
47
  if (checkCmdOrCtrl(event) && event.key === "s" && entity && instanceContent !== undefined) {
46
48
  event.preventDefault();
@@ -119,6 +121,7 @@ export const InstanceRouteSkeleton = ({ mode, buttons, init, titleBuilder, onSub
119
121
  .then(() => id
120
122
  ? getChildInstancesForInstanceByEntityName(locales, entity.name, id).then(result => {
121
123
  setChildInstances(result.instances);
124
+ setSavedChildInstances(result.instances);
122
125
  })
123
126
  : Promise.resolve())
124
127
  .catch((error) => {
@@ -145,6 +148,7 @@ export const InstanceRouteSkeleton = ({ mode, buttons, init, titleBuilder, onSub
145
148
  setInstanceContent: value => {
146
149
  setInstanceContent(value);
147
150
  setSavedInstanceContent(value);
151
+ setSavedChildInstances(childInstances);
148
152
  },
149
153
  childInstances,
150
154
  updateLocalGitState: client?.updateLocalState,
@@ -6,9 +6,7 @@ export const ReferenceIdentifierTypeInput = ({ type, value, instanceNamesByEntit
6
6
  if (typeof value !== "string") {
7
7
  return _jsx(MismatchingTypeError, { expected: "string identifier", actual: value });
8
8
  }
9
- const instances = (instanceNamesByEntity[type.entity] ?? [])
10
- .slice()
11
- .sort((a, b) => a.name.localeCompare(b.name, undefined, { numeric: true }));
9
+ const instances = instanceNamesByEntity[type.entity] ?? [];
12
10
  return (_jsxs("div", { class: "field", children: [_jsxs(Select, { value: value, onInput: event => {
13
11
  onChange(event.currentTarget.value);
14
12
  }, disabled: disabled || instances.length === 0, "aria-invalid": !value, children: [instances.length === 0 ? (_jsx("option", { value: "", disabled: true, children: "No instances available" })) : (_jsx("option", { value: "", disabled: true, children: "No selected instance" })), instances.map(instance => (_jsx("option", { value: instance.id, children: instance.name }, instance.id)))] }), _jsx(ValidationErrors, { disabled: disabled, errors: !value ? [ReferenceError("no reference provided")] : [] })] }));
@@ -19,6 +19,7 @@ export type GitClient = {
19
19
  currentBranch: string;
20
20
  branches: Record<string, GitBranchSummary>;
21
21
  isDetached: boolean;
22
+ latestCommit: string;
22
23
  updateLocalState: () => Promise<void>;
23
24
  getGitStatusOfInstance: (entityName: string, instanceId: string) => GitFileStatus | undefined;
24
25
  fetch: () => Promise<void>;
@@ -28,6 +28,7 @@ export const useGitClient = () => {
28
28
  const [workingTreeFiles, setWorkingTreeFiles] = useState([]);
29
29
  const [allBranches, setAllBranches] = useState([]);
30
30
  const [currentBranch, setCurrentBranch] = useState("");
31
+ const [latestCommit, setLatestCommit] = useState("");
31
32
  const [branches, setBranches] = useState({});
32
33
  const [isDetached, setIsDetached] = useState(false);
33
34
  const updateGitStatus = useCallback(async () => {
@@ -57,6 +58,8 @@ export const useGitClient = () => {
57
58
  ];
58
59
  })));
59
60
  setIsDetached(branchesData.isDetached);
61
+ setLatestCommit(statusData.latestCommit);
62
+ console.log(statusData.latestCommit);
60
63
  }
61
64
  catch (error) {
62
65
  logAndAlertError(error, "Error updating git status: ");
@@ -271,6 +274,7 @@ export const useGitClient = () => {
271
274
  currentBranch,
272
275
  branches,
273
276
  isDetached,
277
+ latestCommit,
274
278
  getGitStatusOfInstance,
275
279
  updateLocalState: updateGitStatus,
276
280
  fetch,
@@ -299,6 +303,7 @@ export const useGitClient = () => {
299
303
  indexFiles,
300
304
  isDetached,
301
305
  isRepo,
306
+ latestCommit,
302
307
  pull,
303
308
  push,
304
309
  reset,
@@ -12,6 +12,7 @@ import { GitClientContext } from "../context/gitClient.js";
12
12
  import { useEntityFromRoute } from "../hooks/useEntityFromRoute.js";
13
13
  import { useMappedAPIResource } from "../hooks/useMappedAPIResource.js";
14
14
  import { useSetting } from "../hooks/useSettings.js";
15
+ import { logAndAlertError } from "../utils/debug.js";
15
16
  import { Markdown } from "../utils/Markdown.js";
16
17
  import { homeTitle } from "./Home.js";
17
18
  import { NotFound } from "./NotFound.js";
@@ -26,8 +27,14 @@ export const Entity = () => {
26
27
  const gitClient = useContext(GitClientContext);
27
28
  const { reloadEntities } = useContext(EntitiesContext);
28
29
  const { declaration: entity, isLocaleEntity } = entityFromRoute ?? {};
29
- const [instances, reloadInstances] = useMappedAPIResource(getInstancesByEntityName, mapInstances, locales, entity?.name ?? "");
30
- const [localeInstances] = useMappedAPIResource(getLocaleInstances, localeMapper, locales, config.localeEntityName);
30
+ const [instances, reloadInstances] = useMappedAPIResource(getInstancesByEntityName, mapInstances, locales, entity?.name ?? name ?? "");
31
+ const [localeInstances, reloadLocaleInstances] = useMappedAPIResource(getLocaleInstances, localeMapper, locales, config.localeEntityName);
32
+ const { latestCommit } = useContext(GitClientContext) ?? {};
33
+ useEffect(() => {
34
+ reloadInstances()
35
+ .then(() => reloadLocaleInstances())
36
+ .catch(logAndAlertError);
37
+ }, [latestCommit, reloadInstances, reloadLocaleInstances]);
31
38
  useEffect(() => {
32
39
  document.title = toTitleCase(entity?.namePlural ?? name ?? "") + " — TSONDB";
33
40
  }, [entity?.namePlural, name]);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "tsondb",
3
- "version": "0.12.2",
3
+ "version": "0.12.3",
4
4
  "description": "",
5
5
  "license": "ISC",
6
6
  "author": "Lukas Obermann",