@rslsp1/fa-app-tools 7.0.1 → 7.2.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.
@@ -5,6 +5,85 @@ import {
5
5
  resolvePreferredHead
6
6
  } from "./chunk-FUY2OCVC.mjs";
7
7
 
8
+ // src/lib/szenen/szenenSnapshot.ts
9
+ var SZENEN_SNAPSHOT_SCHEMA_VERSION = 1;
10
+ var SZENEN_SNAPSHOT_PREFIX = "szenen-state-";
11
+ var SZENEN_SNAPSHOT_FILE = "szenen-state.json";
12
+ function szenenSnapshotFilename(maxTs) {
13
+ const stamp = new Date(maxTs).toISOString().replace(/:/g, "-").replace(".", "-");
14
+ return `${SZENEN_SNAPSHOT_PREFIX}${stamp}.json`;
15
+ }
16
+ function istSzenenSnapshotDatei(name) {
17
+ return name.startsWith(SZENEN_SNAPSHOT_PREFIX) && name.endsWith(".json");
18
+ }
19
+ var maxTsOf = (events) => {
20
+ let max = 0;
21
+ for (const event of events) if (event.ts > max) max = event.ts;
22
+ return max;
23
+ };
24
+ function buildSzenenSnapshot(base, neue, neuePfade = []) {
25
+ const events = [...base?.events ?? [], ...neue];
26
+ const paths = [...base?.consumed.paths ?? [], ...neuePfade.map(basisname)];
27
+ return {
28
+ schema_version: SZENEN_SNAPSHOT_SCHEMA_VERSION,
29
+ consumed: { count: events.length, max_ts: maxTsOf(events), paths },
30
+ events
31
+ };
32
+ }
33
+ function basisname(pfad) {
34
+ return pfad.split("/").pop() ?? pfad;
35
+ }
36
+ function aufgenommeneDateien(snapshot) {
37
+ return new Set(snapshot ? snapshot.consumed.paths : []);
38
+ }
39
+ function parseSzenenSnapshot(raw, herkunft) {
40
+ if (!raw || typeof raw !== "object") {
41
+ throw new Error(`Szenen-Snapshot ${herkunft}: kein Objekt, sondern ${typeof raw}.`);
42
+ }
43
+ const obj = raw;
44
+ if (obj.schema_version !== SZENEN_SNAPSHOT_SCHEMA_VERSION) {
45
+ throw new Error(
46
+ `Szenen-Snapshot ${herkunft}: schema_version ${String(obj.schema_version)} wird nicht gelesen, erwartet ${SZENEN_SNAPSHOT_SCHEMA_VERSION}.`
47
+ );
48
+ }
49
+ if (!Array.isArray(obj.events)) {
50
+ throw new Error(`Szenen-Snapshot ${herkunft}: "events" fehlt oder ist kein Array.`);
51
+ }
52
+ const events = obj.events;
53
+ for (const [i, event] of events.entries()) {
54
+ if (!event || typeof event.type !== "string" || typeof event.ts !== "number") {
55
+ throw new Error(
56
+ `Szenen-Snapshot ${herkunft}: Ereignis ${i} hat keinen Typ oder keinen Zeitstempel.`
57
+ );
58
+ }
59
+ }
60
+ const consumed = obj.consumed;
61
+ if (!consumed || typeof consumed.count !== "number" || typeof consumed.max_ts !== "number") {
62
+ throw new Error(`Szenen-Snapshot ${herkunft}: "consumed" fehlt oder ist unvollstaendig.`);
63
+ }
64
+ if (!Array.isArray(consumed.paths)) {
65
+ throw new Error(
66
+ `Szenen-Snapshot ${herkunft}: "consumed.paths" fehlt. Ohne die aufgenommenen Dateinamen laesst sich nicht entscheiden, welche Datei in events/ noch aussteht.`
67
+ );
68
+ }
69
+ if (consumed.count !== events.length) {
70
+ throw new Error(
71
+ `Szenen-Snapshot ${herkunft}: consumed.count ${consumed.count} passt nicht zu ${events.length} Ereignis(sen) in der Datei \u2014 die Datei ist unvollstaendig.`
72
+ );
73
+ }
74
+ const echt = maxTsOf(events);
75
+ if (consumed.max_ts !== echt) {
76
+ throw new Error(
77
+ `Szenen-Snapshot ${herkunft}: consumed.max_ts ${consumed.max_ts} passt nicht zum groessten Zeitstempel ${echt} in der Datei.`
78
+ );
79
+ }
80
+ return { schema_version: SZENEN_SNAPSHOT_SCHEMA_VERSION, consumed, events };
81
+ }
82
+ function mergeSnapshotAndPending(snapshot, pending, bereitsImSnapshot = 0) {
83
+ if (!snapshot) return { events: pending, bereitsImSnapshot };
84
+ return { events: [...snapshot.events, ...pending], bereitsImSnapshot };
85
+ }
86
+
8
87
  // src/lib/hfEventTypes.ts
9
88
  var HF_BASE = "https://huggingface.co";
10
89
  var HF_REPO = "RolandSch/fa-app-state";
@@ -153,6 +232,16 @@ async function loadPendingEvents(namespace, token, sinceTs, knownPaths) {
153
232
  for (const f of pending) knownPaths?.add(f.path);
154
233
  return raw.flatMap((e) => Array.isArray(e) ? e : [e]);
155
234
  }
235
+ async function findLatestSzenenSnapshotPath(namespace, token) {
236
+ const files = await hfListDir(namespace, "", token);
237
+ const treffer = files.filter((f) => f.type === "file" && istSzenenSnapshotDatei(f.path.split("/").pop() || "")).map((f) => f.path).sort((a, b) => b.localeCompare(a));
238
+ return treffer[0] ?? null;
239
+ }
240
+ async function loadLatestSzenenSnapshot(namespace, token) {
241
+ const pfad = await findLatestSzenenSnapshotPath(namespace, token);
242
+ if (!pfad) return null;
243
+ return parseSzenenSnapshot(await hfDownloadJsonByPath(pfad, token), pfad);
244
+ }
156
245
  var SESSION_CLIENT_ID = `client-${crypto.randomUUID().slice(0, 8)}`;
157
246
  function getSessionClientId() {
158
247
  return SESSION_CLIENT_ID;
@@ -13701,11 +13790,20 @@ function createHfElementStore(options) {
13701
13790
 
13702
13791
  // src/lib/szenen/hfEventChannel.ts
13703
13792
  function createHfEventChannel(options) {
13704
- const { namespace, token, sinceTs = 0 } = options;
13793
+ const { namespace, token, sinceTs = 0, ohneSnapshot = false } = options;
13705
13794
  const knownPaths = /* @__PURE__ */ new Set();
13706
13795
  let cachedRawEvents = [];
13707
13796
  let syncInFlight = null;
13797
+ let snapshot = null;
13798
+ let snapshotGeladen = ohneSnapshot;
13708
13799
  const refresh = async () => {
13800
+ if (!snapshotGeladen) {
13801
+ snapshot = await loadLatestSzenenSnapshot(namespace, token);
13802
+ snapshotGeladen = true;
13803
+ for (const name of aufgenommeneDateien(snapshot)) {
13804
+ knownPaths.add(`${namespace}events/${name}`);
13805
+ }
13806
+ }
13709
13807
  const neue = await loadPendingEvents(namespace, token, sinceTs, knownPaths);
13710
13808
  if (neue.length) cachedRawEvents = [...cachedRawEvents, ...neue];
13711
13809
  };
@@ -13720,12 +13818,13 @@ function createHfEventChannel(options) {
13720
13818
  return {
13721
13819
  async readEvents() {
13722
13820
  await sync();
13723
- return cachedRawEvents.filter((event) => typeof event.type === "string" && event.type.startsWith(SZENEN_EVENT_PREFIX)).map((event) => ({
13821
+ const pending = cachedRawEvents.filter((event) => typeof event.type === "string" && event.type.startsWith(SZENEN_EVENT_PREFIX)).map((event) => ({
13724
13822
  type: event.type,
13725
13823
  payload: event.payload,
13726
13824
  clientId: event.clientId,
13727
13825
  ts: event.ts
13728
13826
  }));
13827
+ return mergeSnapshotAndPending(snapshot, pending).events;
13729
13828
  },
13730
13829
  async appendEvent(type, payload) {
13731
13830
  if (!type.startsWith(SZENEN_EVENT_PREFIX)) {
@@ -16313,6 +16412,14 @@ function createFlowSzenenViewPort(options) {
16313
16412
  }
16314
16413
 
16315
16414
  export {
16415
+ SZENEN_SNAPSHOT_SCHEMA_VERSION,
16416
+ SZENEN_SNAPSHOT_PREFIX,
16417
+ SZENEN_SNAPSHOT_FILE,
16418
+ szenenSnapshotFilename,
16419
+ istSzenenSnapshotDatei,
16420
+ buildSzenenSnapshot,
16421
+ parseSzenenSnapshot,
16422
+ mergeSnapshotAndPending,
16316
16423
  hfListDir,
16317
16424
  hfDownloadBinaryByPath,
16318
16425
  hfUploadSmallFile,
package/dist/index.d.mts CHANGED
@@ -6,7 +6,7 @@ import { Node, Edge } from '@xyflow/react';
6
6
  import * as zustand_vanilla from 'zustand/vanilla';
7
7
  import { F as FeatureSliceId, b as SliceContract, a as PersistenceDescriptor, W as WorkspacePersistence, P as PersistedSlice, L as LoadResult, f as WriteResult, e as WorkspaceTabId, C as CommandResult, R as RequestContext, Q as QueryResult } from './contracts-DdYOMBl9.mjs';
8
8
 
9
- var version = "7.0.1";
9
+ var version = "7.2.0";
10
10
 
11
11
  declare function useOnClickOutside(ref: RefObject<HTMLElement | null>, handler: (e: MouseEvent | TouchEvent) => void): void;
12
12
 
package/dist/index.d.ts CHANGED
@@ -6,7 +6,7 @@ import { Node, Edge } from '@xyflow/react';
6
6
  import * as zustand_vanilla from 'zustand/vanilla';
7
7
  import { F as FeatureSliceId, b as SliceContract, a as PersistenceDescriptor, W as WorkspacePersistence, P as PersistedSlice, L as LoadResult, f as WriteResult, e as WorkspaceTabId, C as CommandResult, R as RequestContext, Q as QueryResult } from './contracts-DdYOMBl9.js';
8
8
 
9
- var version = "7.0.1";
9
+ var version = "7.2.0";
10
10
 
11
11
  declare function useOnClickOutside(ref: RefObject<HTMLElement | null>, handler: (e: MouseEvent | TouchEvent) => void): void;
12
12