srasm 0.0.2 → 0.0.4

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.
package/dist/index.cjs CHANGED
@@ -1,4 +1,3 @@
1
- "use strict";
2
1
  var __create = Object.create;
3
2
  var __defProp = Object.defineProperty;
4
3
  var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
@@ -35,7 +34,7 @@ __export(index_exports, {
35
34
  });
36
35
  module.exports = __toCommonJS(index_exports);
37
36
 
38
- // src/context/createStateStore.tsx
37
+ // src/context/createStateStore.ts
39
38
  var import_react = __toESM(require("react"), 1);
40
39
 
41
40
  // src/utils/deepEqual.ts
@@ -55,9 +54,17 @@ function deepEqual(obj1, obj2) {
55
54
  return true;
56
55
  }
57
56
 
58
- // src/context/createStateStore.tsx
57
+ // src/utils/tryRegisterSRASMDevtools.ts
58
+ function tryRegisterSRASMDevtools(storeName, api) {
59
+ if (typeof window === "undefined") return;
60
+ const dt = window.__SRASM_DEVTOOLS__;
61
+ if (dt && typeof dt.registerStore === "function") {
62
+ dt.registerStore(storeName, api);
63
+ }
64
+ }
65
+
66
+ // src/context/createStateStore.ts
59
67
  var import_with_selector = require("use-sync-external-store/with-selector");
60
- var import_jsx_runtime = require("react/jsx-runtime");
61
68
  function createStateStore(initialSlices) {
62
69
  let storeState = { ...initialSlices };
63
70
  const sliceListeners = /* @__PURE__ */ new Map();
@@ -107,14 +114,14 @@ function createStateStore(initialSlices) {
107
114
  selector ?? ((s) => s),
108
115
  options?.isEqual ?? Object.is
109
116
  );
110
- const setState = (0, import_react.useCallback)(
117
+ const setState2 = (0, import_react.useCallback)(
111
118
  (payload) => updateSlice(slice, payload, !!options?.useDeepEqualCheck),
112
119
  [slice, options?.useDeepEqualCheck]
113
120
  );
114
- return { state: selected, setState };
121
+ return { state: selected, setState: setState2 };
115
122
  }
116
123
  function useSRASMAsync(slice, fetcher, tags = []) {
117
- const { state, setState } = useSRASM(slice);
124
+ const { state, setState: setState2 } = useSRASM(slice);
118
125
  const [loading, setLoading] = import_react.default.useState(false);
119
126
  const [error, setError] = import_react.default.useState(null);
120
127
  const fetchData = (0, import_react.useCallback)(async () => {
@@ -122,13 +129,13 @@ function createStateStore(initialSlices) {
122
129
  setError(null);
123
130
  try {
124
131
  const data = await fetcher();
125
- setState(data);
132
+ setState2(data);
126
133
  } catch (err) {
127
134
  setError(err);
128
135
  } finally {
129
136
  setLoading(false);
130
137
  }
131
- }, [slice, fetcher, setState]);
138
+ }, [slice, fetcher, setState2]);
132
139
  import_react.default.useEffect(() => {
133
140
  fetchData();
134
141
  }, [JSON.stringify(tags)]);
@@ -139,11 +146,24 @@ function createStateStore(initialSlices) {
139
146
  refetch: fetchData
140
147
  };
141
148
  }
142
- const SRASMProvider = ({
143
- children
144
- }) => {
145
- return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_jsx_runtime.Fragment, { children });
149
+ const SRASMProvider = ({ children }) => {
150
+ return children;
151
+ };
152
+ const getState = () => storeState;
153
+ const subscribe = (listener) => {
154
+ const unsubs = Object.keys(storeState).map(
155
+ (k) => subscribeSlice(k, listener)
156
+ );
157
+ return () => unsubs.forEach((u) => u());
158
+ };
159
+ const setState = (key, payload, useDeepEqualCheck = false) => {
160
+ updateSlice(key, payload, useDeepEqualCheck);
146
161
  };
162
+ tryRegisterSRASMDevtools("default", {
163
+ getState,
164
+ subscribe,
165
+ setState
166
+ });
147
167
  return { SRASMProvider, useSRASM, useSRASMAsync };
148
168
  }
149
169
 
@@ -159,4 +179,3 @@ var logClick = (event) => {
159
179
  createStateStore,
160
180
  logClick
161
181
  });
162
- //# sourceMappingURL=index.cjs.map
package/dist/index.d.cts CHANGED
@@ -1,4 +1,3 @@
1
- import * as react_jsx_runtime from 'react/jsx-runtime';
2
1
  import React from 'react';
3
2
 
4
3
  /**
@@ -13,18 +12,20 @@ import React from 'react';
13
12
  * The `useSRASM` hook can be used by your React components to access and update the state.
14
13
  */
15
14
  declare function createStateStore<Slices extends Record<string, any>>(initialSlices: Slices): {
16
- SRASMProvider: ({ children, }: {
15
+ SRASMProvider: ({ children }: {
17
16
  children: React.ReactNode;
18
- }) => react_jsx_runtime.JSX.Element;
17
+ }) => React.ReactElement<{
18
+ children: React.ReactNode;
19
+ }>;
19
20
  useSRASM: <K extends keyof Slices, Selected = Slices[K]>(slice: K, selector?: (s: Slices[K]) => Selected, options?: {
20
21
  useDeepEqualCheck?: boolean;
21
22
  isEqual?: (a: Selected, b: Selected) => boolean;
22
23
  }) => {
23
- state: Selected;
24
+ state: any;
24
25
  setState: (payload: Partial<Slices[K]> | ((prev: Slices[K]) => Partial<Slices[K]>)) => void;
25
26
  };
26
27
  useSRASMAsync: <K extends keyof Slices>(slice: K, fetcher: () => Promise<Slices[K]>, tags?: any[]) => {
27
- data: Slices[K];
28
+ data: any;
28
29
  loading: boolean;
29
30
  error: any;
30
31
  refetch: () => Promise<void>;
package/dist/index.d.ts CHANGED
@@ -1,4 +1,3 @@
1
- import * as react_jsx_runtime from 'react/jsx-runtime';
2
1
  import React from 'react';
3
2
 
4
3
  /**
@@ -13,18 +12,20 @@ import React from 'react';
13
12
  * The `useSRASM` hook can be used by your React components to access and update the state.
14
13
  */
15
14
  declare function createStateStore<Slices extends Record<string, any>>(initialSlices: Slices): {
16
- SRASMProvider: ({ children, }: {
15
+ SRASMProvider: ({ children }: {
17
16
  children: React.ReactNode;
18
- }) => react_jsx_runtime.JSX.Element;
17
+ }) => React.ReactElement<{
18
+ children: React.ReactNode;
19
+ }>;
19
20
  useSRASM: <K extends keyof Slices, Selected = Slices[K]>(slice: K, selector?: (s: Slices[K]) => Selected, options?: {
20
21
  useDeepEqualCheck?: boolean;
21
22
  isEqual?: (a: Selected, b: Selected) => boolean;
22
23
  }) => {
23
- state: Selected;
24
+ state: any;
24
25
  setState: (payload: Partial<Slices[K]> | ((prev: Slices[K]) => Partial<Slices[K]>)) => void;
25
26
  };
26
27
  useSRASMAsync: <K extends keyof Slices>(slice: K, fetcher: () => Promise<Slices[K]>, tags?: any[]) => {
27
- data: Slices[K];
28
+ data: any;
28
29
  loading: boolean;
29
30
  error: any;
30
31
  refetch: () => Promise<void>;
package/dist/index.js CHANGED
@@ -1,4 +1,4 @@
1
- // src/context/createStateStore.tsx
1
+ // src/context/createStateStore.ts
2
2
  import React, { useCallback } from "react";
3
3
 
4
4
  // src/utils/deepEqual.ts
@@ -18,9 +18,17 @@ function deepEqual(obj1, obj2) {
18
18
  return true;
19
19
  }
20
20
 
21
- // src/context/createStateStore.tsx
21
+ // src/utils/tryRegisterSRASMDevtools.ts
22
+ function tryRegisterSRASMDevtools(storeName, api) {
23
+ if (typeof window === "undefined") return;
24
+ const dt = window.__SRASM_DEVTOOLS__;
25
+ if (dt && typeof dt.registerStore === "function") {
26
+ dt.registerStore(storeName, api);
27
+ }
28
+ }
29
+
30
+ // src/context/createStateStore.ts
22
31
  import { useSyncExternalStoreWithSelector } from "use-sync-external-store/with-selector";
23
- import { Fragment, jsx } from "react/jsx-runtime";
24
32
  function createStateStore(initialSlices) {
25
33
  let storeState = { ...initialSlices };
26
34
  const sliceListeners = /* @__PURE__ */ new Map();
@@ -70,14 +78,14 @@ function createStateStore(initialSlices) {
70
78
  selector ?? ((s) => s),
71
79
  options?.isEqual ?? Object.is
72
80
  );
73
- const setState = useCallback(
81
+ const setState2 = useCallback(
74
82
  (payload) => updateSlice(slice, payload, !!options?.useDeepEqualCheck),
75
83
  [slice, options?.useDeepEqualCheck]
76
84
  );
77
- return { state: selected, setState };
85
+ return { state: selected, setState: setState2 };
78
86
  }
79
87
  function useSRASMAsync(slice, fetcher, tags = []) {
80
- const { state, setState } = useSRASM(slice);
88
+ const { state, setState: setState2 } = useSRASM(slice);
81
89
  const [loading, setLoading] = React.useState(false);
82
90
  const [error, setError] = React.useState(null);
83
91
  const fetchData = useCallback(async () => {
@@ -85,13 +93,13 @@ function createStateStore(initialSlices) {
85
93
  setError(null);
86
94
  try {
87
95
  const data = await fetcher();
88
- setState(data);
96
+ setState2(data);
89
97
  } catch (err) {
90
98
  setError(err);
91
99
  } finally {
92
100
  setLoading(false);
93
101
  }
94
- }, [slice, fetcher, setState]);
102
+ }, [slice, fetcher, setState2]);
95
103
  React.useEffect(() => {
96
104
  fetchData();
97
105
  }, [JSON.stringify(tags)]);
@@ -102,11 +110,24 @@ function createStateStore(initialSlices) {
102
110
  refetch: fetchData
103
111
  };
104
112
  }
105
- const SRASMProvider = ({
106
- children
107
- }) => {
108
- return /* @__PURE__ */ jsx(Fragment, { children });
113
+ const SRASMProvider = ({ children }) => {
114
+ return children;
115
+ };
116
+ const getState = () => storeState;
117
+ const subscribe = (listener) => {
118
+ const unsubs = Object.keys(storeState).map(
119
+ (k) => subscribeSlice(k, listener)
120
+ );
121
+ return () => unsubs.forEach((u) => u());
122
+ };
123
+ const setState = (key, payload, useDeepEqualCheck = false) => {
124
+ updateSlice(key, payload, useDeepEqualCheck);
109
125
  };
126
+ tryRegisterSRASMDevtools("default", {
127
+ getState,
128
+ subscribe,
129
+ setState
130
+ });
110
131
  return { SRASMProvider, useSRASM, useSRASMAsync };
111
132
  }
112
133
 
@@ -121,4 +142,3 @@ export {
121
142
  createStateStore,
122
143
  logClick
123
144
  };
124
- //# sourceMappingURL=index.js.map
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "srasm",
3
3
  "private": false,
4
- "version": "0.0.2",
4
+ "version": "0.0.4",
5
5
  "type": "module",
6
6
  "files": [
7
7
  "dist",
@@ -24,35 +24,15 @@
24
24
  "debug": " npx eslint . --debug"
25
25
  },
26
26
  "dependencies": {
27
- "@langchain/core": "^1.1.0",
28
- "@langchain/openai": "^1.1.3",
29
- "@tailwindcss/vite": "^4.1.17",
30
- "@tensorflow/tfjs": "^4.22.0",
31
- "axios": "^1.13.2",
32
27
  "clsx": "^2.1.1",
33
- "dotenv": "^17.2.3",
34
- "langchain": "^1.1.1",
35
- "lucide-react": "^0.555.0",
36
- "postcss": "^8.5.6",
37
- "rc-tree": "^5.13.1",
38
- "react": "^19.2.0",
39
- "react-d3-tree": "^3.6.6",
40
- "react-dom": "^19.2.0",
41
- "react-hot-toast": "^2.6.0",
42
- "react-markdown": "^10.1.0",
43
- "react-router-dom": "^7.9.6",
28
+ "react": ">=18",
44
29
  "react-virtuoso": "^4.16.1",
45
- "rehype-highlight": "^7.0.2",
46
- "remark-gfm": "^4.0.1",
47
- "tailwindcss": "^4.1.18",
48
30
  "use-sync-external-store": "^1.6.0"
49
31
  },
50
32
  "peerDependencies": {
51
- "react": ">=18",
52
- "react-dom": ">=18"
33
+ "react": ">=18"
53
34
  },
54
35
  "devDependencies": {
55
- "@tailwindcss/postcss": "^4.1.18",
56
36
  "@testing-library/dom": "^10.4.1",
57
37
  "@testing-library/react": "^16.3.1",
58
38
  "@types/bun": "latest",
@@ -60,14 +40,9 @@
60
40
  "@types/react": "^19.2.2",
61
41
  "@types/react-dom": "^19.2.2",
62
42
  "@types/use-sync-external-store": "^1.5.0",
63
- "@vitejs/plugin-react": "^5.1.0",
64
- "baseline-browser-mapping": "^2.9.15",
65
- "happy-dom": "^20.0.11",
66
- "jsdom": "^27.0.1",
43
+ "esbuild": "^0.27.2",
67
44
  "tsup": "^8.5.1",
68
- "typescript": "~5.9.3",
69
- "vite": "^7.2.2",
70
- "vitest": "^4.0.16"
45
+ "typescript": "~5.9.3"
71
46
  },
72
47
  "module": "index.ts"
73
48
  }
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/index.ts","../src/context/createStateStore.tsx","../src/utils/deepEqual.ts","../src/ml/globalLogs.ts"],"sourcesContent":["// Core state management\r\nexport { createStateStore } from \"./context\";\r\n\r\n// Utilities / ML helpers\r\nexport { logClick } from \"./ml\";\r\nexport type { ClickEvent } from \"./ml\";\r\n","import React, { useCallback } from \"react\";\r\nimport { deepEqual } from \"../utils\";\r\nimport { useSyncExternalStoreWithSelector } from \"use-sync-external-store/with-selector\";\r\n/**\r\n * Creates a state store with the given initial state slices.\r\n * The state store is used by the `useSRASM` hook to provide a strongly-typed\r\n * way of accessing and updating the state.\r\n *\r\n * @param {Slices} initialSlices The initial state slices to be used by the state store.\r\n * @return {{ SRASMProvider: React.FC<{ children: React.ReactNode; relevantCode?: { fileName: string; code: string }[] | undefined; additionalSlices?: any[] | undefined }>; useSRASM: <K extends SliceKey, Selected = Slices[K]>(slice: K, selector?: (s: Slices[K]) => Selected, options?: { useDeepEqualCheck?: boolean; isEqual?: (a: Selected, b: Selected) => boolean; }) => useSRASMReturn }}\r\n * The returned object contains the `SRASMProvider` context provider component and the `useSRASM` hook.\r\n * The `SRASMProvider` component should be used to wrap your application, providing the necessary state and error handling to SRASM components.\r\n * The `useSRASM` hook can be used by your React components to access and update the state.\r\n */\r\nexport function createStateStore<Slices extends Record<string, any>>(\r\n initialSlices: Slices,\r\n) {\r\n type SliceKey = keyof Slices;\r\n\r\n let storeState: Slices = { ...initialSlices };\r\n\r\n const sliceListeners = new Map<SliceKey, Set<() => void>>();\r\n // const activeRequests = new Map<SliceKey, Promise<any>>();\r\n\r\n /**\r\n * Returns a set of listeners for the given slice key.\r\n * If no listeners are registered for the key, a new set is created and stored.\r\n * @param {SliceKey} k\r\n * @returns {Set<() => void>}\r\n */\r\n const getSliceListeners = (k: SliceKey) => {\r\n let set = sliceListeners.get(k);\r\n if (!set) {\r\n set = new Set();\r\n sliceListeners.set(k, set);\r\n }\r\n return set;\r\n };\r\n\r\n /**\r\n * Subscribes to the slice with the given key, adding the given\r\n * listener to the set of listeners for that slice.\r\n *\r\n * Returns a function that can be used to unsubscribe the given\r\n * listener from the slice.\r\n *\r\n * @param {SliceKey} key The key of the slice to subscribe to.\r\n * @param {() => void} listener The listener to add to the slice.\r\n * @returns {() => void} A function to unsubscribe the listener from the slice.\r\n */\r\n const subscribeSlice = (key: SliceKey, listener: () => void) => {\r\n const set = getSliceListeners(key);\r\n set.add(listener);\r\n return () => set.delete(listener);\r\n };\r\n\r\n /**\r\n * Emits the slice with the given key, calling all listeners\r\n * that are currently subscribed to that slice.\r\n *\r\n * This is used internally by the `useSRASM` hook to notify\r\n * components when the slice they are subscribed to changes.\r\n *\r\n * @param {SliceKey} key The key of the slice to emit.\r\n */\r\n const emitSlice = (key: SliceKey) => {\r\n getSliceListeners(key).forEach((l) => l());\r\n };\r\n\r\n /**\r\n * Updates the slice with the given key, using the given payload to\r\n * determine the new value of the slice. If the payload is a function,\r\n * it will be called with the current value of the slice as its argument.\r\n *\r\n * If the payload is not a function, it will be used as the new value\r\n * of the slice. If the current and new values are equal (using a\r\n * deep equality check if useDeepEqualCheck is true), the slice will\r\n * not be updated.\r\n *\r\n * @param {SliceKey} key The key of the slice to update.\r\n * @param {any} payload The payload to use to update the slice.\r\n * @param {boolean} useDeepEqualCheck Whether to use a deep equality\r\n * check when comparing the current and new values of the slice.\r\n */\r\n const updateSlice = (\r\n key: SliceKey,\r\n payload: any,\r\n useDeepEqualCheck: boolean,\r\n ) => {\r\n const current = storeState[key];\r\n let next = current;\r\n\r\n if (typeof payload === \"function\") {\r\n next = payload(current);\r\n if (Object.is(current, next)) return;\r\n if (useDeepEqualCheck && deepEqual(current, next)) return;\r\n } else {\r\n if (\r\n typeof current === \"object\" &&\r\n current !== null &&\r\n typeof payload === \"object\" &&\r\n payload !== null\r\n ) {\r\n next = { ...(current as any), ...(payload as any) };\r\n if (useDeepEqualCheck && deepEqual(current, next)) return;\r\n } else {\r\n if (Object.is(current, payload)) return;\r\n if (useDeepEqualCheck && deepEqual(current, payload)) return;\r\n next = payload;\r\n }\r\n }\r\n\r\n if (!Object.is(storeState[key], next)) {\r\n storeState = { ...storeState, [key]: next };\r\n emitSlice(key);\r\n }\r\n };\r\n\r\n /**\r\n * Hook to use a slice of the global state.\r\n * @param {SliceKey} slice The key of the slice to use.\r\n * @param {((s: Slices[K]) => Selected) | undefined} selector\r\n * A function to select the desired value from the slice.\r\n * @param {useSRASMOptions} options Options for the hook.\r\n * @returns {useSRASMReturn} An object with the selected state and a\r\n * function to update the state.\r\n *\r\n * The `useSRASM` hook allows you to use a slice of the global state\r\n * in your React components. It takes a slice key as its first argument and\r\n * an optional selector function as its second argument. The selector function\r\n * is called with the slice state as its argument and should return the desired value\r\n * from the slice state.\r\n *\r\n * The hook returns an object with two properties: `state` and `setState`. The\r\n * `state` property contains the selected value from the slice state, and the\r\n * `setState` property is a function that can be used to update the slice state.\r\n *\r\n * The `options` object can be used to customize the behavior of the hook. It\r\n * accepts two properties: `useDeepEqualCheck` and `isEqual`. The\r\n * `useDeepEqualCheck` property is a boolean that indicates whether to use a deep\r\n * equality check when comparing the current and new values of the slice state.\r\n * The `isEqual` property is a function that is used to compare the current and\r\n * new values of the slice state. If not provided, the hook will use the `Object.is`\r\n * function to compare the values.\r\n */\r\n function useSRASM<K extends SliceKey, Selected = Slices[K]>(\r\n slice: K,\r\n selector?: (s: Slices[K]) => Selected,\r\n options?: {\r\n useDeepEqualCheck?: boolean;\r\n isEqual?: (a: Selected, b: Selected) => boolean;\r\n },\r\n ) {\r\n const selected = useSyncExternalStoreWithSelector(\r\n (listener) => subscribeSlice(slice, listener),\r\n () => storeState[slice],\r\n () => initialSlices[slice],\r\n selector ?? ((s: Selected) => s as Selected),\r\n options?.isEqual ?? Object.is,\r\n );\r\n\r\n type SliceUpdater<S> = Partial<S> | ((prev: S) => Partial<S>);\r\n\r\n const setState = useCallback(\r\n (payload: SliceUpdater<Slices[K]>) =>\r\n updateSlice(slice, payload, !!options?.useDeepEqualCheck),\r\n [slice, options?.useDeepEqualCheck],\r\n );\r\n\r\n return { state: selected, setState };\r\n }\r\n\r\n /**\r\n * Hook to asynchronously fetch and manage a slice state.\r\n * @param {SliceKey} slice The slice key.\r\n * @param {() => Promise<Slices[K]>} fetcher The async function to fetch data.\r\n * @param {any[]} tags Array of dependencies. specific tags that trigger refetch.\r\n * @returns {{ data: Slices[K]; loading: boolean; error: any; refetch: () => void }}\r\n */\r\n function useSRASMAsync<K extends SliceKey>(\r\n slice: K,\r\n fetcher: () => Promise<Slices[K]>,\r\n tags: any[] = [],\r\n ) {\r\n const { state, setState } = useSRASM(slice);\r\n const [loading, setLoading] = React.useState(false);\r\n const [error, setError] = React.useState<any>(null);\r\n\r\n const fetchData = useCallback(async () => {\r\n // Deduping: if a request is already active for this slice, don't start another?\r\n // For now, let's allow it but simple tracking.\r\n setLoading(true);\r\n setError(null);\r\n\r\n try {\r\n const data = await fetcher();\r\n setState(data);\r\n } catch (err) {\r\n setError(err);\r\n } finally {\r\n setLoading(false);\r\n }\r\n }, [slice, fetcher, setState]); // tags are handled in useEffect\r\n\r\n React.useEffect(() => {\r\n // Simple \"auto-fetch\" on mount or tag change\r\n // In a real lib we would check if data exists/is fresh.\r\n fetchData();\r\n }, [JSON.stringify(tags)]); // deeply compare tags simple approach\r\n\r\n return {\r\n data: state,\r\n loading,\r\n error,\r\n refetch: fetchData,\r\n };\r\n }\r\n\r\n /**\r\n * @note Can be need at the future\r\n * A context provider that wraps your application and provides\r\n * the necessary state and error handling to SRASM components.\r\n *\r\n * @param {React.ReactNode} children The components to be rendered within\r\n * the provider.\r\n * @param {({ fileName: string; code: string }[] | undefined} relevantCode\r\n * An optional array of objects containing the file name and code of the\r\n * relevant code snippets to be used for AI error debugging.\r\n * @param {any[] | undefined} additionalSlices An optional array of\r\n * additional slices to be passed to the AI error debugging system.\r\n */\r\n const SRASMProvider = ({\r\n children,\r\n }: {\r\n children: React.ReactNode;\r\n }) => {\r\n return <>{children}</>;\r\n };\r\n\r\n return { SRASMProvider, useSRASM, useSRASMAsync };\r\n}\r\n","export function deepEqual(\r\n obj1: Record<string, any>,\r\n obj2: Record<string, any>\r\n) {\r\n if (obj1 === obj2) return true; // Handles primitive values and same object references\r\n\r\n // If one is null or not object, compare with Object.is\r\n if (\r\n typeof obj1 !== \"object\" ||\r\n typeof obj2 !== \"object\" ||\r\n obj1 === null ||\r\n obj2 === null\r\n ) {\r\n return Object.is(obj1, obj2);\r\n }\r\n\r\n const keys1 = Object.keys(obj1);\r\n const keys2 = Object.keys(obj2);\r\n\r\n if (keys1.length !== keys2.length) return false; // Different number of properties\r\n\r\n for (const key of keys1) {\r\n if (!keys2.includes(key) || !deepEqual(obj1[key], obj2[key])) {\r\n return false; // Key missing or values not deeply equal\r\n }\r\n }\r\n return true;\r\n}\r\n","export type ClickEvent = {\r\n itemId: string;\r\n categoryId: string;\r\n ts: number;\r\n};\r\n\r\nexport const logClick = (event: ClickEvent) => {\r\n const key = \"click_events\";\r\n const existing = JSON.parse(localStorage.getItem(key) || \"[]\");\r\n existing.push(event);\r\n localStorage.setItem(key, JSON.stringify(existing));\r\n};\r\n\r\n"],"mappings":"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","names":["React"]}
package/dist/index.js.map DELETED
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/context/createStateStore.tsx","../src/utils/deepEqual.ts","../src/ml/globalLogs.ts"],"sourcesContent":["import React, { useCallback } from \"react\";\r\nimport { deepEqual } from \"../utils\";\r\nimport { useSyncExternalStoreWithSelector } from \"use-sync-external-store/with-selector\";\r\n/**\r\n * Creates a state store with the given initial state slices.\r\n * The state store is used by the `useSRASM` hook to provide a strongly-typed\r\n * way of accessing and updating the state.\r\n *\r\n * @param {Slices} initialSlices The initial state slices to be used by the state store.\r\n * @return {{ SRASMProvider: React.FC<{ children: React.ReactNode; relevantCode?: { fileName: string; code: string }[] | undefined; additionalSlices?: any[] | undefined }>; useSRASM: <K extends SliceKey, Selected = Slices[K]>(slice: K, selector?: (s: Slices[K]) => Selected, options?: { useDeepEqualCheck?: boolean; isEqual?: (a: Selected, b: Selected) => boolean; }) => useSRASMReturn }}\r\n * The returned object contains the `SRASMProvider` context provider component and the `useSRASM` hook.\r\n * The `SRASMProvider` component should be used to wrap your application, providing the necessary state and error handling to SRASM components.\r\n * The `useSRASM` hook can be used by your React components to access and update the state.\r\n */\r\nexport function createStateStore<Slices extends Record<string, any>>(\r\n initialSlices: Slices,\r\n) {\r\n type SliceKey = keyof Slices;\r\n\r\n let storeState: Slices = { ...initialSlices };\r\n\r\n const sliceListeners = new Map<SliceKey, Set<() => void>>();\r\n // const activeRequests = new Map<SliceKey, Promise<any>>();\r\n\r\n /**\r\n * Returns a set of listeners for the given slice key.\r\n * If no listeners are registered for the key, a new set is created and stored.\r\n * @param {SliceKey} k\r\n * @returns {Set<() => void>}\r\n */\r\n const getSliceListeners = (k: SliceKey) => {\r\n let set = sliceListeners.get(k);\r\n if (!set) {\r\n set = new Set();\r\n sliceListeners.set(k, set);\r\n }\r\n return set;\r\n };\r\n\r\n /**\r\n * Subscribes to the slice with the given key, adding the given\r\n * listener to the set of listeners for that slice.\r\n *\r\n * Returns a function that can be used to unsubscribe the given\r\n * listener from the slice.\r\n *\r\n * @param {SliceKey} key The key of the slice to subscribe to.\r\n * @param {() => void} listener The listener to add to the slice.\r\n * @returns {() => void} A function to unsubscribe the listener from the slice.\r\n */\r\n const subscribeSlice = (key: SliceKey, listener: () => void) => {\r\n const set = getSliceListeners(key);\r\n set.add(listener);\r\n return () => set.delete(listener);\r\n };\r\n\r\n /**\r\n * Emits the slice with the given key, calling all listeners\r\n * that are currently subscribed to that slice.\r\n *\r\n * This is used internally by the `useSRASM` hook to notify\r\n * components when the slice they are subscribed to changes.\r\n *\r\n * @param {SliceKey} key The key of the slice to emit.\r\n */\r\n const emitSlice = (key: SliceKey) => {\r\n getSliceListeners(key).forEach((l) => l());\r\n };\r\n\r\n /**\r\n * Updates the slice with the given key, using the given payload to\r\n * determine the new value of the slice. If the payload is a function,\r\n * it will be called with the current value of the slice as its argument.\r\n *\r\n * If the payload is not a function, it will be used as the new value\r\n * of the slice. If the current and new values are equal (using a\r\n * deep equality check if useDeepEqualCheck is true), the slice will\r\n * not be updated.\r\n *\r\n * @param {SliceKey} key The key of the slice to update.\r\n * @param {any} payload The payload to use to update the slice.\r\n * @param {boolean} useDeepEqualCheck Whether to use a deep equality\r\n * check when comparing the current and new values of the slice.\r\n */\r\n const updateSlice = (\r\n key: SliceKey,\r\n payload: any,\r\n useDeepEqualCheck: boolean,\r\n ) => {\r\n const current = storeState[key];\r\n let next = current;\r\n\r\n if (typeof payload === \"function\") {\r\n next = payload(current);\r\n if (Object.is(current, next)) return;\r\n if (useDeepEqualCheck && deepEqual(current, next)) return;\r\n } else {\r\n if (\r\n typeof current === \"object\" &&\r\n current !== null &&\r\n typeof payload === \"object\" &&\r\n payload !== null\r\n ) {\r\n next = { ...(current as any), ...(payload as any) };\r\n if (useDeepEqualCheck && deepEqual(current, next)) return;\r\n } else {\r\n if (Object.is(current, payload)) return;\r\n if (useDeepEqualCheck && deepEqual(current, payload)) return;\r\n next = payload;\r\n }\r\n }\r\n\r\n if (!Object.is(storeState[key], next)) {\r\n storeState = { ...storeState, [key]: next };\r\n emitSlice(key);\r\n }\r\n };\r\n\r\n /**\r\n * Hook to use a slice of the global state.\r\n * @param {SliceKey} slice The key of the slice to use.\r\n * @param {((s: Slices[K]) => Selected) | undefined} selector\r\n * A function to select the desired value from the slice.\r\n * @param {useSRASMOptions} options Options for the hook.\r\n * @returns {useSRASMReturn} An object with the selected state and a\r\n * function to update the state.\r\n *\r\n * The `useSRASM` hook allows you to use a slice of the global state\r\n * in your React components. It takes a slice key as its first argument and\r\n * an optional selector function as its second argument. The selector function\r\n * is called with the slice state as its argument and should return the desired value\r\n * from the slice state.\r\n *\r\n * The hook returns an object with two properties: `state` and `setState`. The\r\n * `state` property contains the selected value from the slice state, and the\r\n * `setState` property is a function that can be used to update the slice state.\r\n *\r\n * The `options` object can be used to customize the behavior of the hook. It\r\n * accepts two properties: `useDeepEqualCheck` and `isEqual`. The\r\n * `useDeepEqualCheck` property is a boolean that indicates whether to use a deep\r\n * equality check when comparing the current and new values of the slice state.\r\n * The `isEqual` property is a function that is used to compare the current and\r\n * new values of the slice state. If not provided, the hook will use the `Object.is`\r\n * function to compare the values.\r\n */\r\n function useSRASM<K extends SliceKey, Selected = Slices[K]>(\r\n slice: K,\r\n selector?: (s: Slices[K]) => Selected,\r\n options?: {\r\n useDeepEqualCheck?: boolean;\r\n isEqual?: (a: Selected, b: Selected) => boolean;\r\n },\r\n ) {\r\n const selected = useSyncExternalStoreWithSelector(\r\n (listener) => subscribeSlice(slice, listener),\r\n () => storeState[slice],\r\n () => initialSlices[slice],\r\n selector ?? ((s: Selected) => s as Selected),\r\n options?.isEqual ?? Object.is,\r\n );\r\n\r\n type SliceUpdater<S> = Partial<S> | ((prev: S) => Partial<S>);\r\n\r\n const setState = useCallback(\r\n (payload: SliceUpdater<Slices[K]>) =>\r\n updateSlice(slice, payload, !!options?.useDeepEqualCheck),\r\n [slice, options?.useDeepEqualCheck],\r\n );\r\n\r\n return { state: selected, setState };\r\n }\r\n\r\n /**\r\n * Hook to asynchronously fetch and manage a slice state.\r\n * @param {SliceKey} slice The slice key.\r\n * @param {() => Promise<Slices[K]>} fetcher The async function to fetch data.\r\n * @param {any[]} tags Array of dependencies. specific tags that trigger refetch.\r\n * @returns {{ data: Slices[K]; loading: boolean; error: any; refetch: () => void }}\r\n */\r\n function useSRASMAsync<K extends SliceKey>(\r\n slice: K,\r\n fetcher: () => Promise<Slices[K]>,\r\n tags: any[] = [],\r\n ) {\r\n const { state, setState } = useSRASM(slice);\r\n const [loading, setLoading] = React.useState(false);\r\n const [error, setError] = React.useState<any>(null);\r\n\r\n const fetchData = useCallback(async () => {\r\n // Deduping: if a request is already active for this slice, don't start another?\r\n // For now, let's allow it but simple tracking.\r\n setLoading(true);\r\n setError(null);\r\n\r\n try {\r\n const data = await fetcher();\r\n setState(data);\r\n } catch (err) {\r\n setError(err);\r\n } finally {\r\n setLoading(false);\r\n }\r\n }, [slice, fetcher, setState]); // tags are handled in useEffect\r\n\r\n React.useEffect(() => {\r\n // Simple \"auto-fetch\" on mount or tag change\r\n // In a real lib we would check if data exists/is fresh.\r\n fetchData();\r\n }, [JSON.stringify(tags)]); // deeply compare tags simple approach\r\n\r\n return {\r\n data: state,\r\n loading,\r\n error,\r\n refetch: fetchData,\r\n };\r\n }\r\n\r\n /**\r\n * @note Can be need at the future\r\n * A context provider that wraps your application and provides\r\n * the necessary state and error handling to SRASM components.\r\n *\r\n * @param {React.ReactNode} children The components to be rendered within\r\n * the provider.\r\n * @param {({ fileName: string; code: string }[] | undefined} relevantCode\r\n * An optional array of objects containing the file name and code of the\r\n * relevant code snippets to be used for AI error debugging.\r\n * @param {any[] | undefined} additionalSlices An optional array of\r\n * additional slices to be passed to the AI error debugging system.\r\n */\r\n const SRASMProvider = ({\r\n children,\r\n }: {\r\n children: React.ReactNode;\r\n }) => {\r\n return <>{children}</>;\r\n };\r\n\r\n return { SRASMProvider, useSRASM, useSRASMAsync };\r\n}\r\n","export function deepEqual(\r\n obj1: Record<string, any>,\r\n obj2: Record<string, any>\r\n) {\r\n if (obj1 === obj2) return true; // Handles primitive values and same object references\r\n\r\n // If one is null or not object, compare with Object.is\r\n if (\r\n typeof obj1 !== \"object\" ||\r\n typeof obj2 !== \"object\" ||\r\n obj1 === null ||\r\n obj2 === null\r\n ) {\r\n return Object.is(obj1, obj2);\r\n }\r\n\r\n const keys1 = Object.keys(obj1);\r\n const keys2 = Object.keys(obj2);\r\n\r\n if (keys1.length !== keys2.length) return false; // Different number of properties\r\n\r\n for (const key of keys1) {\r\n if (!keys2.includes(key) || !deepEqual(obj1[key], obj2[key])) {\r\n return false; // Key missing or values not deeply equal\r\n }\r\n }\r\n return true;\r\n}\r\n","export type ClickEvent = {\r\n itemId: string;\r\n categoryId: string;\r\n ts: number;\r\n};\r\n\r\nexport const logClick = (event: ClickEvent) => {\r\n const key = \"click_events\";\r\n const existing = JSON.parse(localStorage.getItem(key) || \"[]\");\r\n existing.push(event);\r\n localStorage.setItem(key, JSON.stringify(existing));\r\n};\r\n\r\n"],"mappings":"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","names":[]}