@simplysm/solid 13.0.33 → 13.0.35

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.
Files changed (79) hide show
  1. package/README.md +22 -42
  2. package/dist/components/disclosure/DialogContext.d.ts +29 -0
  3. package/dist/components/disclosure/DialogContext.d.ts.map +1 -1
  4. package/dist/components/disclosure/DialogContext.js.map +1 -1
  5. package/dist/components/disclosure/DialogInstanceContext.d.ts +14 -0
  6. package/dist/components/disclosure/DialogInstanceContext.d.ts.map +1 -1
  7. package/dist/components/disclosure/DialogInstanceContext.js.map +1 -1
  8. package/dist/components/feedback/busy/BusyContext.d.ts +18 -0
  9. package/dist/components/feedback/busy/BusyContext.d.ts.map +1 -1
  10. package/dist/components/feedback/busy/BusyContext.js.map +1 -1
  11. package/dist/components/feedback/busy/BusyProvider.d.ts +10 -0
  12. package/dist/components/feedback/busy/BusyProvider.d.ts.map +1 -1
  13. package/dist/components/feedback/busy/BusyProvider.js.map +1 -1
  14. package/dist/components/feedback/notification/NotificationContext.d.ts +29 -0
  15. package/dist/components/feedback/notification/NotificationContext.d.ts.map +1 -1
  16. package/dist/components/feedback/notification/NotificationContext.js.map +1 -1
  17. package/dist/components/feedback/notification/NotificationProvider.d.ts +9 -0
  18. package/dist/components/feedback/notification/NotificationProvider.d.ts.map +1 -1
  19. package/dist/components/feedback/notification/NotificationProvider.js.map +1 -1
  20. package/dist/hooks/useLogger.d.ts +4 -2
  21. package/dist/hooks/useLogger.d.ts.map +1 -1
  22. package/dist/hooks/useLogger.js +11 -4
  23. package/dist/hooks/useLogger.js.map +1 -1
  24. package/dist/hooks/useSyncConfig.d.ts +2 -0
  25. package/dist/hooks/useSyncConfig.d.ts.map +1 -1
  26. package/dist/hooks/useSyncConfig.js +30 -26
  27. package/dist/hooks/useSyncConfig.js.map +1 -1
  28. package/dist/index.d.ts +8 -14
  29. package/dist/index.d.ts.map +1 -1
  30. package/dist/index.js +21 -15
  31. package/dist/index.js.map +1 -1
  32. package/dist/providers/InitializeProvider.d.ts +33 -0
  33. package/dist/providers/InitializeProvider.d.ts.map +1 -0
  34. package/dist/providers/InitializeProvider.js +75 -0
  35. package/dist/providers/InitializeProvider.js.map +6 -0
  36. package/dist/providers/LoggerContext.d.ts +24 -8
  37. package/dist/providers/LoggerContext.d.ts.map +1 -1
  38. package/dist/providers/LoggerContext.js +13 -13
  39. package/dist/providers/LoggerContext.js.map +2 -2
  40. package/dist/providers/ServiceClientContext.d.ts +13 -0
  41. package/dist/providers/ServiceClientContext.d.ts.map +1 -1
  42. package/dist/providers/ServiceClientContext.js.map +1 -1
  43. package/dist/providers/ServiceClientProvider.d.ts +21 -0
  44. package/dist/providers/ServiceClientProvider.d.ts.map +1 -1
  45. package/dist/providers/ServiceClientProvider.js.map +1 -1
  46. package/dist/providers/SyncStorageContext.d.ts +25 -11
  47. package/dist/providers/SyncStorageContext.d.ts.map +1 -1
  48. package/dist/providers/SyncStorageContext.js +13 -13
  49. package/dist/providers/SyncStorageContext.js.map +2 -2
  50. package/dist/providers/shared-data/SharedDataChangeEvent.d.ts +8 -0
  51. package/dist/providers/shared-data/SharedDataChangeEvent.d.ts.map +1 -1
  52. package/dist/providers/shared-data/SharedDataChangeEvent.js.map +1 -1
  53. package/dist/providers/shared-data/SharedDataContext.d.ts +39 -0
  54. package/dist/providers/shared-data/SharedDataContext.d.ts.map +1 -1
  55. package/dist/providers/shared-data/SharedDataContext.js +1 -3
  56. package/dist/providers/shared-data/SharedDataContext.js.map +1 -1
  57. package/dist/providers/shared-data/SharedDataProvider.d.ts +30 -5
  58. package/dist/providers/shared-data/SharedDataProvider.d.ts.map +1 -1
  59. package/dist/providers/shared-data/SharedDataProvider.js +59 -38
  60. package/dist/providers/shared-data/SharedDataProvider.js.map +2 -2
  61. package/docs/providers.md +70 -195
  62. package/package.json +3 -3
  63. package/src/components/disclosure/DialogContext.ts +29 -0
  64. package/src/components/disclosure/DialogInstanceContext.ts +14 -0
  65. package/src/components/feedback/busy/BusyContext.ts +18 -0
  66. package/src/components/feedback/busy/BusyProvider.tsx +10 -0
  67. package/src/components/feedback/notification/NotificationContext.ts +29 -0
  68. package/src/components/feedback/notification/NotificationProvider.tsx +9 -0
  69. package/src/hooks/useLogger.ts +14 -4
  70. package/src/hooks/useSyncConfig.ts +42 -35
  71. package/src/index.ts +34 -14
  72. package/src/providers/InitializeProvider.tsx +74 -0
  73. package/src/providers/LoggerContext.tsx +39 -10
  74. package/src/providers/ServiceClientContext.ts +13 -0
  75. package/src/providers/ServiceClientProvider.tsx +21 -0
  76. package/src/providers/SyncStorageContext.tsx +40 -15
  77. package/src/providers/shared-data/SharedDataChangeEvent.ts +8 -0
  78. package/src/providers/shared-data/SharedDataContext.ts +40 -3
  79. package/src/providers/shared-data/SharedDataProvider.tsx +102 -54
@@ -1,22 +1,61 @@
1
1
  import { type Accessor } from "solid-js";
2
+ /**
3
+ * 공유 데이터 정의
4
+ *
5
+ * @remarks
6
+ * SharedDataProvider에 전달하여 서버 데이터 구독을 설정한다.
7
+ */
2
8
  export interface SharedDataDefinition<TData> {
9
+ /** 서비스 연결 key (useServiceClient의 connect key와 동일) */
3
10
  serviceKey: string;
11
+ /** 데이터 조회 함수 (changeKeys가 있으면 해당 항목만 부분 갱신) */
4
12
  fetch: (changeKeys?: Array<string | number>) => Promise<TData[]>;
13
+ /** 항목의 고유 key 추출 함수 */
5
14
  getKey: (item: TData) => string | number;
15
+ /** 정렬 기준 배열 (여러 기준 적용 가능) */
6
16
  orderBy: [(item: TData) => unknown, "asc" | "desc"][];
17
+ /** 서버 이벤트 필터 (같은 name의 이벤트 중 filter가 일치하는 것만 수신) */
7
18
  filter?: unknown;
8
19
  }
20
+ /**
21
+ * 공유 데이터 접근자
22
+ *
23
+ * @remarks
24
+ * 각 데이터 key에 대한 반응형 접근 및 변경 알림을 제공한다.
25
+ */
9
26
  export interface SharedDataAccessor<TData> {
27
+ /** 반응형 항목 배열 */
10
28
  items: Accessor<TData[]>;
29
+ /** key로 단일 항목 조회 */
11
30
  get: (key: string | number | undefined) => TData | undefined;
31
+ /** 서버에 변경 이벤트 전파 (모든 구독자에게 refetch 트리거) */
12
32
  emit: (changeKeys?: Array<string | number>) => Promise<void>;
13
33
  }
34
+ /**
35
+ * 공유 데이터 Context 값
36
+ *
37
+ * @remarks
38
+ * - configure 호출 전: wait, busy, configure만 접근 가능. 데이터 접근 시 throw
39
+ * - configure 호출 후: 각 데이터 key별 SharedDataAccessor와 전체 상태 관리 메서드 포함
40
+ */
14
41
  export type SharedDataValue<TSharedData extends Record<string, unknown>> = {
15
42
  [K in keyof TSharedData]: SharedDataAccessor<TSharedData[K]>;
16
43
  } & {
44
+ /** 모든 초기 fetch 완료까지 대기 */
17
45
  wait: () => Promise<void>;
46
+ /** fetch 진행 중 여부 */
18
47
  busy: Accessor<boolean>;
48
+ /** definitions를 설정하여 데이터 구독 시작 */
49
+ configure: (definitions: {
50
+ [K in keyof TSharedData]: SharedDataDefinition<TSharedData[K]>;
51
+ }) => void;
19
52
  };
53
+ /** 공유 데이터 Context */
20
54
  export declare const SharedDataContext: import("solid-js").Context<SharedDataValue<Record<string, unknown>> | undefined>;
55
+ /**
56
+ * 공유 데이터에 접근하는 훅
57
+ *
58
+ * @throws SharedDataProvider가 없으면 에러 발생
59
+ */
21
60
  export declare function useSharedData<TSharedData extends Record<string, unknown> = Record<string, unknown>>(): SharedDataValue<TSharedData>;
22
61
  //# sourceMappingURL=SharedDataContext.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"SharedDataContext.d.ts","sourceRoot":"","sources":["../../../src/providers/shared-data/SharedDataContext.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,QAAQ,EAA6B,MAAM,UAAU,CAAC;AAEpE,MAAM,WAAW,oBAAoB,CAAC,KAAK;IACzC,UAAU,EAAE,MAAM,CAAC;IACnB,KAAK,EAAE,CAAC,UAAU,CAAC,EAAE,KAAK,CAAC,MAAM,GAAG,MAAM,CAAC,KAAK,OAAO,CAAC,KAAK,EAAE,CAAC,CAAC;IACjE,MAAM,EAAE,CAAC,IAAI,EAAE,KAAK,KAAK,MAAM,GAAG,MAAM,CAAC;IACzC,OAAO,EAAE,CAAC,CAAC,IAAI,EAAE,KAAK,KAAK,OAAO,EAAE,KAAK,GAAG,MAAM,CAAC,EAAE,CAAC;IACtD,MAAM,CAAC,EAAE,OAAO,CAAC;CAClB;AAED,MAAM,WAAW,kBAAkB,CAAC,KAAK;IACvC,KAAK,EAAE,QAAQ,CAAC,KAAK,EAAE,CAAC,CAAC;IACzB,GAAG,EAAE,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,KAAK,KAAK,GAAG,SAAS,CAAC;IAC7D,IAAI,EAAE,CAAC,UAAU,CAAC,EAAE,KAAK,CAAC,MAAM,GAAG,MAAM,CAAC,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;CAC9D;AAED,MAAM,MAAM,eAAe,CAAC,WAAW,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,IAAI;KACxE,CAAC,IAAI,MAAM,WAAW,GAAG,kBAAkB,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC;CAC7D,GAAG;IACF,IAAI,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;IAC1B,IAAI,EAAE,QAAQ,CAAC,OAAO,CAAC,CAAC;CACzB,CAAC;AAEF,eAAO,MAAM,iBAAiB,kFAA4D,CAAC;AAE3F,wBAAgB,aAAa,CAC3B,WAAW,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAClE,eAAe,CAAC,WAAW,CAAC,CAQhC"}
1
+ {"version":3,"file":"SharedDataContext.d.ts","sourceRoot":"","sources":["../../../src/providers/shared-data/SharedDataContext.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,QAAQ,EAA6B,MAAM,UAAU,CAAC;AAEpE;;;;;GAKG;AACH,MAAM,WAAW,oBAAoB,CAAC,KAAK;IACzC,qDAAqD;IACrD,UAAU,EAAE,MAAM,CAAC;IACnB,+CAA+C;IAC/C,KAAK,EAAE,CAAC,UAAU,CAAC,EAAE,KAAK,CAAC,MAAM,GAAG,MAAM,CAAC,KAAK,OAAO,CAAC,KAAK,EAAE,CAAC,CAAC;IACjE,uBAAuB;IACvB,MAAM,EAAE,CAAC,IAAI,EAAE,KAAK,KAAK,MAAM,GAAG,MAAM,CAAC;IACzC,6BAA6B;IAC7B,OAAO,EAAE,CAAC,CAAC,IAAI,EAAE,KAAK,KAAK,OAAO,EAAE,KAAK,GAAG,MAAM,CAAC,EAAE,CAAC;IACtD,oDAAoD;IACpD,MAAM,CAAC,EAAE,OAAO,CAAC;CAClB;AAED;;;;;GAKG;AACH,MAAM,WAAW,kBAAkB,CAAC,KAAK;IACvC,gBAAgB;IAChB,KAAK,EAAE,QAAQ,CAAC,KAAK,EAAE,CAAC,CAAC;IACzB,oBAAoB;IACpB,GAAG,EAAE,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,KAAK,KAAK,GAAG,SAAS,CAAC;IAC7D,2CAA2C;IAC3C,IAAI,EAAE,CAAC,UAAU,CAAC,EAAE,KAAK,CAAC,MAAM,GAAG,MAAM,CAAC,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;CAC9D;AAED;;;;;;GAMG;AACH,MAAM,MAAM,eAAe,CAAC,WAAW,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,IAAI;KACxE,CAAC,IAAI,MAAM,WAAW,GAAG,kBAAkB,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC;CAC7D,GAAG;IACF,0BAA0B;IAC1B,IAAI,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;IAC1B,oBAAoB;IACpB,IAAI,EAAE,QAAQ,CAAC,OAAO,CAAC,CAAC;IACxB,kCAAkC;IAClC,SAAS,EAAE,CAAC,WAAW,EAAE;SACtB,CAAC,IAAI,MAAM,WAAW,GAAG,oBAAoB,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC;KAC/D,KAAK,IAAI,CAAC;CACZ,CAAC;AAEF,qBAAqB;AACrB,eAAO,MAAM,iBAAiB,kFAA4D,CAAC;AAE3F;;;;GAIG;AACH,wBAAgB,aAAa,CAC3B,WAAW,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAClE,eAAe,CAAC,WAAW,CAAC,CAMhC"}
@@ -3,9 +3,7 @@ const SharedDataContext = createContext();
3
3
  function useSharedData() {
4
4
  const context = useContext(SharedDataContext);
5
5
  if (!context) {
6
- throw new Error(
7
- "useSharedData\uB294 SharedDataProvider \uB0B4\uBD80\uC5D0\uC11C\uB9CC \uC0AC\uC6A9\uD560 \uC218 \uC788\uC2B5\uB2C8\uB2E4. SharedDataProvider\uB294 ServiceClientProvider \uC544\uB798\uC5D0 \uC704\uCE58\uD574\uC57C \uD569\uB2C8\uB2E4"
8
- );
6
+ throw new Error("useSharedData\uB294 SharedDataProvider \uB0B4\uBD80\uC5D0\uC11C\uB9CC \uC0AC\uC6A9\uD560 \uC218 \uC788\uC2B5\uB2C8\uB2E4");
9
7
  }
10
8
  return context;
11
9
  }
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../src/providers/shared-data/SharedDataContext.ts"],
4
- "mappings": "AAAA,SAAwB,eAAe,kBAAkB;AAuBlD,MAAM,oBAAoB,cAAwD;AAElF,SAAS,gBAEkB;AAChC,QAAM,UAAU,WAAW,iBAAiB;AAC5C,MAAI,CAAC,SAAS;AACZ,UAAM,IAAI;AAAA,MACR;AAAA,IACF;AAAA,EACF;AACA,SAAO;AACT;",
4
+ "mappings": "AAAA,SAAwB,eAAe,kBAAkB;AAyDlD,MAAM,oBAAoB,cAAwD;AAOlF,SAAS,gBAEkB;AAChC,QAAM,UAAU,WAAW,iBAAiB;AAC5C,MAAI,CAAC,SAAS;AACZ,UAAM,IAAI,MAAM,0HAAoD;AAAA,EACtE;AACA,SAAO;AACT;",
5
5
  "names": []
6
6
  }
@@ -1,9 +1,34 @@
1
1
  import { type JSX } from "solid-js";
2
- import { type SharedDataDefinition } from "./SharedDataContext";
3
- export declare function SharedDataProvider<TSharedData extends Record<string, unknown>>(props: {
4
- definitions: {
5
- [K in keyof TSharedData]: SharedDataDefinition<TSharedData[K]>;
6
- };
2
+ /**
3
+ * 공유 데이터 Provider
4
+ *
5
+ * @remarks
6
+ * - ServiceClientProvider와 NotificationProvider 내부에서 사용해야 함
7
+ * - LoggerProvider가 있으면 fetch 실패를 로거에도 기록
8
+ * - configure() 호출 전: wait, busy, configure만 접근 가능. 데이터 접근 시 throw
9
+ * - configure() 호출 후: definitions의 각 key마다 서버 이벤트 리스너를 등록하여 실시간 동기화
10
+ * - 동시 fetch 호출 시 version counter로 데이터 역전 방지
11
+ * - fetch 실패 시 사용자에게 danger 알림 표시
12
+ * - cleanup 시 모든 이벤트 리스너 자동 해제
13
+ *
14
+ * @example
15
+ * ```tsx
16
+ * <SharedDataProvider>
17
+ * <App />
18
+ * </SharedDataProvider>
19
+ *
20
+ * // 자식 컴포넌트에서 나중에 설정:
21
+ * useSharedData().configure({
22
+ * users: {
23
+ * serviceKey: "main",
24
+ * fetch: async (changeKeys) => fetchUsers(changeKeys),
25
+ * getKey: (item) => item.id,
26
+ * orderBy: [[(item) => item.name, "asc"]],
27
+ * },
28
+ * });
29
+ * ```
30
+ */
31
+ export declare function SharedDataProvider(props: {
7
32
  children: JSX.Element;
8
33
  }): JSX.Element;
9
34
  //# sourceMappingURL=SharedDataProvider.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"SharedDataProvider.d.ts","sourceRoot":"","sources":["../../../src/providers/shared-data/SharedDataProvider.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAiB,KAAK,GAAG,EAAuC,MAAM,UAAU,CAAC;AAExF,OAAO,EAGL,KAAK,oBAAoB,EAE1B,MAAM,qBAAqB,CAAC;AAM7B,wBAAgB,kBAAkB,CAAC,WAAW,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,KAAK,EAAE;IACrF,WAAW,EAAE;SAAG,CAAC,IAAI,MAAM,WAAW,GAAG,oBAAoB,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC;KAAE,CAAC;IAChF,QAAQ,EAAE,GAAG,CAAC,OAAO,CAAC;CACvB,GAAG,GAAG,CAAC,OAAO,CA4Id"}
1
+ {"version":3,"file":"SharedDataProvider.d.ts","sourceRoot":"","sources":["../../../src/providers/shared-data/SharedDataProvider.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAiB,KAAK,GAAG,EAAuC,MAAM,UAAU,CAAC;AAaxF;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AACH,wBAAgB,kBAAkB,CAAC,KAAK,EAAE;IAAE,QAAQ,EAAE,GAAG,CAAC,OAAO,CAAA;CAAE,GAAG,GAAG,CAAC,OAAO,CAkKhF"}
@@ -10,12 +10,15 @@ function SharedDataProvider(props) {
10
10
  const serviceClient = useServiceClient();
11
11
  const notification = useNotification();
12
12
  const logger = useLogger();
13
+ let configured = false;
13
14
  const [busyCount, setBusyCount] = createSignal(0);
14
15
  const busy = () => busyCount() > 0;
15
16
  const signalMap = /* @__PURE__ */ new Map();
16
17
  const memoMap = /* @__PURE__ */ new Map();
17
18
  const listenerKeyMap = /* @__PURE__ */ new Map();
18
19
  const versionMap = /* @__PURE__ */ new Map();
20
+ const accessors = {};
21
+ let currentDefinitions;
19
22
  function ordering(data, orderByList) {
20
23
  let result = [...data];
21
24
  for (const orderBy of [...orderByList].reverse()) {
@@ -57,54 +60,72 @@ function SharedDataProvider(props) {
57
60
  async function wait() {
58
61
  await waitUntil(() => busyCount() <= 0);
59
62
  }
60
- const accessors = {};
61
- for (const [name, def] of Object.entries(props.definitions)) {
62
- const [items, setItems] = createSignal([]);
63
- signalMap.set(name, [items, setItems]);
64
- const itemMap = createMemo(() => {
65
- const map = /* @__PURE__ */ new Map();
66
- for (const item of items()) {
67
- map.set(def.getKey(item), item);
68
- }
69
- return map;
70
- });
71
- memoMap.set(name, itemMap);
72
- const client = serviceClient.get(def.serviceKey);
73
- void client.addEventListener(SharedDataChangeEvent, {
74
- name,
75
- filter: def.filter
76
- }, async (changeKeys) => {
77
- await loadData(name, def, changeKeys);
78
- }).then((key) => {
79
- listenerKeyMap.set(name, key);
80
- });
81
- void loadData(name, def);
82
- accessors[name] = {
83
- items,
84
- get: (key) => {
85
- if (key === void 0) return void 0;
86
- return itemMap().get(key);
87
- },
88
- emit: async (changeKeys) => {
89
- await client.emitToServer(SharedDataChangeEvent, (info) => info.name === name && objEqual(info.filter, def.filter), changeKeys);
90
- }
91
- };
63
+ function configure(definitions) {
64
+ if (configured) {
65
+ throw new Error("SharedDataProvider: configure()\uB294 1\uD68C\uB9CC \uD638\uCD9C\uD560 \uC218 \uC788\uC2B5\uB2C8\uB2E4");
66
+ }
67
+ configured = true;
68
+ currentDefinitions = definitions;
69
+ for (const [name, def] of Object.entries(definitions)) {
70
+ const [items, setItems] = createSignal([]);
71
+ signalMap.set(name, [items, setItems]);
72
+ const itemMap = createMemo(() => {
73
+ const map = /* @__PURE__ */ new Map();
74
+ for (const item of items()) {
75
+ map.set(def.getKey(item), item);
76
+ }
77
+ return map;
78
+ });
79
+ memoMap.set(name, itemMap);
80
+ const client = serviceClient.get(def.serviceKey);
81
+ void client.addEventListener(SharedDataChangeEvent, {
82
+ name,
83
+ filter: def.filter
84
+ }, async (changeKeys) => {
85
+ await loadData(name, def, changeKeys);
86
+ }).then((key) => {
87
+ listenerKeyMap.set(name, key);
88
+ });
89
+ void loadData(name, def);
90
+ accessors[name] = {
91
+ items,
92
+ get: (key) => {
93
+ if (key === void 0) return void 0;
94
+ return itemMap().get(key);
95
+ },
96
+ emit: async (changeKeys) => {
97
+ await client.emitToServer(SharedDataChangeEvent, (info) => info.name === name && objEqual(info.filter, def.filter), changeKeys);
98
+ }
99
+ };
100
+ }
92
101
  }
93
102
  onCleanup(() => {
94
- for (const [name] of Object.entries(props.definitions)) {
103
+ if (!currentDefinitions) return;
104
+ for (const [name] of Object.entries(currentDefinitions)) {
95
105
  const listenerKey = listenerKeyMap.get(name);
96
106
  if (listenerKey != null) {
97
- const def = props.definitions[name];
107
+ const def = currentDefinitions[name];
98
108
  const client = serviceClient.get(def.serviceKey);
99
109
  void client.removeEventListener(listenerKey);
100
110
  }
101
111
  }
102
112
  });
103
- const contextValue = {
104
- ...accessors,
113
+ const KNOWN_KEYS = /* @__PURE__ */ new Set(["wait", "busy", "configure"]);
114
+ const contextValue = new Proxy({
105
115
  wait,
106
- busy
107
- };
116
+ busy,
117
+ configure
118
+ }, {
119
+ get(target, prop) {
120
+ if (KNOWN_KEYS.has(prop)) {
121
+ return target[prop];
122
+ }
123
+ if (!configured) {
124
+ throw new Error("SharedDataProvider: configure()\uB97C \uBA3C\uC800 \uD638\uCD9C\uD574\uC57C \uD569\uB2C8\uB2E4");
125
+ }
126
+ return accessors[prop];
127
+ }
128
+ });
108
129
  return _$createComponent(SharedDataContext.Provider, {
109
130
  value: contextValue,
110
131
  get children() {
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../src/providers/shared-data/SharedDataProvider.tsx"],
4
- "mappings": ";AAAA,SAAkCA,YAAYC,cAAcC,iBAAiB;AAC7E,SAASC,UAAUC,iBAAiB;AACpC,SACEC,yBAIK;AACP,SAASC,6BAA6B;AACtC,SAASC,wBAAwB;AACjC,SAASC,uBAAuB;AAChC,SAASC,iBAAiB;AAEnB,SAASC,mBAAgEC,OAGhE;AACd,QAAMC,gBAAgBL,iBAAiB;AACvC,QAAMM,eAAeL,gBAAgB;AACrC,QAAMM,SAASL,UAAU;AAEzB,QAAM,CAACM,WAAWC,YAAY,IAAIf,aAAa,CAAC;AAChD,QAAMgB,OAA0BA,MAAMF,UAAU,IAAI;AAEpD,QAAMG,YAAY,oBAAIC,IAAwD;AAC9E,QAAMC,UAAU,oBAAID,IAAqD;AACzE,QAAME,iBAAiB,oBAAIF,IAAoB;AAC/C,QAAMG,aAAa,oBAAIH,IAAoB;AAE3C,WAASI,SAAaC,MAAYC,aAA8D;AAC9F,QAAIC,SAAS,CAAC,GAAGF,IAAI;AACrB,eAAWG,WAAW,CAAC,GAAGF,WAAW,EAAEG,QAAQ,GAAG;AAChD,YAAMC,WAAYC,UAAaH,QAAQ,CAAC,EAAEG,IAAI;AAC9C,UAAIH,QAAQ,CAAC,MAAM,QAAQ;AACzBD,iBAASA,OAAOK,YAAYF,QAAQ;MACtC,OAAO;AACLH,iBAASA,OAAOC,QAAQE,QAAQ;MAClC;IACF;AACA,WAAOH;EACT;AAEA,iBAAeM,SACbC,MACAC,KACAC,YACe;AAEf,UAAMC,kBAAkBd,WAAWe,IAAIJ,IAAI,KAAK,KAAK;AACrDX,eAAWgB,IAAIL,MAAMG,cAAc;AAEnCpB,iBAAcuB,OAAMA,IAAI,CAAC;AACzB,QAAI;AACF,YAAMC,SAAStB,UAAUmB,IAAIJ,IAAI;AACjC,UAAI,CAACO,OAAQ,OAAM,IAAIC,MAAM,IAAIR,IAAI,wGAAwB;AAE7D,YAAM,CAAA,EAAGS,QAAQ,IAAIF;AACrB,YAAMG,UAAU,MAAMT,IAAIU,MAAMT,UAAU;AAG1C,UAAIb,WAAWe,IAAIJ,IAAI,MAAMG,eAAgB;AAE7C,UAAI,CAACD,YAAY;AACfO,iBAASnB,SAASoB,SAAST,IAAIP,OAAO,CAAC;MACzC,OAAO;AACLe,iBAAUG,UAAS;AACjB,gBAAMC,WAAWD,KAAKE,OAAQjB,UAAS,CAACK,WAAWa,SAASd,IAAIe,OAAOnB,IAAa,CAAC,CAAC;AACtFgB,mBAASI,KAAK,GAAGP,OAAO;AACxB,iBAAOpB,SAASuB,UAAUZ,IAAIP,OAAO;QACvC,CAAC;MACH;IACF,SAASwB,KAAK;AAEZrC,aAAOsC,MAAM,eAAenB,IAAI,mBAAmBkB,GAAG;AACtDtC,mBAAawC,OACX,6DACAF,eAAeV,QAAQU,IAAIG,UAAU,IAAIrB,IAAI,qHAC/C;IACF,UAAC;AACCjB,mBAAcuB,OAAMA,IAAI,CAAC;IAC3B;EACF;AAEA,iBAAegB,OAAsB;AAEnC,UAAMnD,UAAU,MAAMW,UAAU,KAAK,CAAC;EACxC;AAEA,QAAMyC,YAAyD,CAAC;AAGhE,aAAW,CAACvB,MAAMC,GAAG,KAAKuB,OAAOC,QAAQ/C,MAAMgD,WAAW,GAGrD;AACH,UAAM,CAACC,OAAOlB,QAAQ,IAAIzC,aAAwB,CAAA,CAAE;AAEpDiB,cAAUoB,IAAIL,MAAM,CAAC2B,OAAOlB,QAAQ,CAAC;AAErC,UAAMmB,UAAU7D,WAAW,MAAM;AAC/B,YAAM8D,MAAM,oBAAI3C,IAA8B;AAC9C,iBAAWW,QAAQ8B,MAAM,GAAG;AAC1BE,YAAIxB,IAAIJ,IAAIe,OAAOnB,IAAa,GAAGA,IAAI;MACzC;AACA,aAAOgC;IACT,CAAC;AAED1C,YAAQkB,IAAIL,MAAM4B,OAAO;AAEzB,UAAME,SAASnD,cAAcyB,IAAIH,IAAI8B,UAAU;AAC/C,SAAKD,OACFE,iBAAiB3D,uBAAuB;MAAE2B;MAAMc,QAAQb,IAAIa;IAAO,GAAG,OAAOZ,eAAe;AAC3F,YAAMH,SAASC,MAAMC,KAAKC,UAAU;IACtC,CAAC,EACA+B,KAAMC,SAAQ;AACb9C,qBAAeiB,IAAIL,MAAMkC,GAAG;IAC9B,CAAC;AAEH,SAAKnC,SAASC,MAAMC,GAAG;AAEvBsB,cAAUvB,IAAI,IAAI;MAChB2B;MACAvB,KAAM8B,SAAqC;AACzC,YAAIA,QAAQC,OAAW,QAAOA;AAC9B,eAAOP,QAAQ,EAAExB,IAAI8B,GAAG;MAC1B;MACAE,MAAM,OAAOlC,eAAwC;AACnD,cAAM4B,OAAOO,aACXhE,uBACCiE,UAASA,KAAKtC,SAASA,QAAQ9B,SAASoE,KAAKxB,QAAQb,IAAIa,MAAM,GAChEZ,UACF;MACF;IACF;EACF;AAEAjC,YAAU,MAAM;AACd,eAAW,CAAC+B,IAAI,KAAKwB,OAAOC,QAAQ/C,MAAMgD,WAAW,GAAG;AACtD,YAAMa,cAAcnD,eAAegB,IAAIJ,IAAI;AAC3C,UAAIuC,eAAe,MAAM;AACvB,cAAMtC,MAAOvB,MAAMgD,YAA8D1B,IAAI;AACrF,cAAM8B,SAASnD,cAAcyB,IAAIH,IAAI8B,UAAU;AAC/C,aAAKD,OAAOU,oBAAoBD,WAAW;MAC7C;IACF;EACF,CAAC;AAED,QAAME,eAAe;IACnB,GAAGlB;IACHD;IACAtC;EACF;AAEA,SAAA0D,kBACGtE,kBAAkBuE,UAAQ;IAACC,OAAOH;IAAY,IAAAI,WAAA;AAAA,aAAGnE,MAAMmE;IAAQ;EAAA,CAAA;AAEpE;",
5
- "names": ["createMemo", "createSignal", "onCleanup", "objEqual", "waitUntil", "SharedDataContext", "SharedDataChangeEvent", "useServiceClient", "useNotification", "useLogger", "SharedDataProvider", "props", "serviceClient", "notification", "logger", "busyCount", "setBusyCount", "busy", "signalMap", "Map", "memoMap", "listenerKeyMap", "versionMap", "ordering", "data", "orderByList", "result", "orderBy", "reverse", "selector", "item", "orderByDesc", "loadData", "name", "def", "changeKeys", "currentVersion", "get", "set", "c", "signal", "Error", "setItems", "resData", "fetch", "prev", "filtered", "filter", "includes", "getKey", "push", "err", "error", "danger", "message", "wait", "accessors", "Object", "entries", "definitions", "items", "itemMap", "map", "client", "serviceKey", "addEventListener", "then", "key", "undefined", "emit", "emitToServer", "info", "listenerKey", "removeEventListener", "contextValue", "_$createComponent", "Provider", "value", "children"]
4
+ "mappings": "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",
5
+ "names": ["createMemo", "createSignal", "onCleanup", "objEqual", "waitUntil", "SharedDataContext", "SharedDataChangeEvent", "useServiceClient", "useNotification", "useLogger", "SharedDataProvider", "props", "serviceClient", "notification", "logger", "configured", "busyCount", "setBusyCount", "busy", "signalMap", "Map", "memoMap", "listenerKeyMap", "versionMap", "accessors", "currentDefinitions", "ordering", "data", "orderByList", "result", "orderBy", "reverse", "selector", "item", "orderByDesc", "loadData", "name", "def", "changeKeys", "currentVersion", "get", "set", "c", "signal", "Error", "setItems", "resData", "fetch", "prev", "filtered", "filter", "includes", "getKey", "push", "err", "error", "danger", "message", "wait", "configure", "definitions", "Object", "entries", "items", "itemMap", "map", "client", "serviceKey", "addEventListener", "then", "key", "undefined", "emit", "emitToServer", "info", "listenerKey", "removeEventListener", "KNOWN_KEYS", "Set", "contextValue", "Proxy", "target", "prop", "has", "_$createComponent", "Provider", "value", "children"]
6
6
  }
package/docs/providers.md CHANGED
@@ -1,212 +1,103 @@
1
1
  # Providers
2
2
 
3
- Providers are composable and independent. Compose them at your app root in the recommended order:
3
+ ## InitializeProvider
4
4
 
5
- ```tsx
6
- <ConfigProvider clientName="my-app">
7
- <SyncStorageProvider storage={...}> {/* optional */}
8
- <LoggerProvider adapter={...}> {/* optional */}
9
- <NotificationProvider>
10
- <NotificationBanner />
11
- <ErrorLoggerProvider>
12
- <PwaUpdateProvider>
13
- <ClipboardProvider>
14
- <ThemeProvider>
15
- <BusyProvider>{/* app content */}</BusyProvider>
16
- </ThemeProvider>
17
- </ClipboardProvider>
18
- </PwaUpdateProvider>
19
- </ErrorLoggerProvider>
20
- </NotificationProvider>
21
- </LoggerProvider>
22
- </SyncStorageProvider>
23
- </ConfigProvider>
24
- ```
25
-
26
- ## ConfigProvider
27
-
28
- Required root provider. Provides `clientName` used as storage key prefix.
5
+ The only exported provider component. Wraps all internal providers in the correct dependency order. Use this to set up your app.
29
6
 
30
7
  ```tsx
31
- <ConfigProvider clientName="my-app">
32
- {/* app content */}
33
- </ConfigProvider>
34
- ```
35
-
36
- | Prop | Type | Description |
37
- |------|------|-------------|
38
- | `clientName` | `string` | Client identifier (used as storage key prefix) |
8
+ import { InitializeProvider } from "@simplysm/solid";
39
9
 
40
- ---
41
-
42
- ## SyncStorageProvider
43
-
44
- Optional provider for custom sync storage (cross-device sync). When present, `useSyncConfig` uses this storage instead of `localStorage`.
45
-
46
- ```tsx
47
- <SyncStorageProvider storage={myStorageAdapter}>
48
- {/* children */}
49
- </SyncStorageProvider>
10
+ <InitializeProvider clientName="my-app">
11
+ <AppRoot />
12
+ </InitializeProvider>
50
13
  ```
51
14
 
52
- | Prop | Type | Description |
53
- |------|------|-------------|
54
- | `storage` | `StorageAdapter` | Storage adapter implementation |
55
-
56
- ---
57
-
58
- ## LoggerProvider
59
-
60
- Optional provider for remote logging. When present, `useLogger` sends logs to the adapter instead of `consola`.
15
+ Configuration is done via hooks inside child components:
61
16
 
62
17
  ```tsx
63
- <LoggerProvider adapter={myLogAdapter}>
64
- {/* children */}
65
- </LoggerProvider>
66
- ```
67
-
68
- | Prop | Type | Description |
69
- |------|------|-------------|
70
- | `adapter` | `LogAdapter` | Log adapter implementation |
18
+ function AppRoot() {
19
+ const serviceClient = useServiceClient();
71
20
 
72
- ---
73
-
74
- ## ErrorLoggerProvider
75
-
76
- Captures uncaught errors (`window.onerror`) and unhandled promise rejections (`unhandledrejection`) and logs them via `useLogger`.
77
-
78
- ```tsx
79
- <ErrorLoggerProvider>
80
- {/* children */}
81
- </ErrorLoggerProvider>
21
+ onMount(async () => {
22
+ await serviceClient.connect("main", { port: 3000 });
23
+ useSyncStorage()!.configure(myStorageAdapter);
24
+ useLogger().configure(myLogAdapter);
25
+ useSharedData().configure(definitions);
26
+ });
27
+ }
82
28
  ```
83
29
 
84
- ---
85
-
86
- ## PwaUpdateProvider
87
-
88
- PWA Service Worker update detection. Polls for SW updates every 5 minutes. When a new version is detected, shows a notification with a reload action. Must be inside `NotificationProvider`.
30
+ | Prop | Type | Default | Description |
31
+ |------|------|---------|-------------|
32
+ | `clientName` | `string` | (required) | Client identifier (used as storage key prefix) |
33
+ | `busyVariant` | `BusyVariant` | `"spinner"` | Busy overlay display variant (`"spinner"` or `"bar"`) |
89
34
 
90
- Graceful no-op when `navigator.serviceWorker` is unavailable (HTTP, unsupported browser, dev mode).
35
+ **Internal nesting order:**
91
36
 
92
- ```tsx
93
- <PwaUpdateProvider>
94
- {/* children */}
95
- </PwaUpdateProvider>
96
37
  ```
97
-
98
- ---
99
-
100
- ## ClipboardProvider
101
-
102
- Intercepts `Ctrl+C` to copy form control values (input, textarea, select, checkbox) as plain text. Handles table structures as TSV format.
103
-
104
- ```tsx
105
- <ClipboardProvider>
106
- {/* children */}
107
- </ClipboardProvider>
38
+ ConfigProvider → SyncStorageProvider → LoggerProvider →
39
+ NotificationProvider + NotificationBanner →
40
+ ErrorLoggerProvider → PwaUpdateProvider →
41
+ ClipboardProvider → ThemeProvider →
42
+ ServiceClientProvider → SharedDataProvider →
43
+ BusyProvider DialogProvider {children}
108
44
  ```
109
45
 
110
- ---
111
-
112
- ## ThemeProvider
113
-
114
- Dark/light/system theme provider. Toggles the `dark` class on `<html>` and manages theme persistence via `useSyncConfig`.
115
-
116
- ```tsx
117
- <ThemeProvider>
118
- {/* children */}
119
- </ThemeProvider>
120
- ```
46
+ Individual providers are not exported. All provider setup goes through `InitializeProvider`.
121
47
 
122
48
  ---
123
49
 
124
- ## ServiceClientProvider
50
+ ## Exported Types & Hooks
51
+
52
+ The following types, context objects, and hooks are exported for use with `InitializeProvider`:
53
+
54
+ | Export | Kind | Description |
55
+ |--------|------|-------------|
56
+ | `useConfig` | hook | App configuration access |
57
+ | `useTheme` | hook | Theme mode access and toggle |
58
+ | `useSyncStorage` | hook | Sync storage adapter access |
59
+ | `useServiceClient` | hook | WebSocket RPC client access |
60
+ | `useSharedData` | hook | Shared data subscription access |
61
+ | `useNotification` | hook | Notification system access |
62
+ | `useBusy` | hook | Busy overlay control |
63
+ | `useDialog` | hook | Programmatic dialog opening |
64
+ | `ConfigContext` | context | For mock injection in tests |
65
+ | `SyncStorageContext` | context | For mock injection in tests |
66
+ | `ServiceClientContext` | context | For mock injection in tests |
67
+ | `SharedDataContext` | context | For mock injection in tests |
68
+ | `AppConfig` | type | Config context value type |
69
+ | `StorageAdapter` | type | Sync storage adapter interface |
70
+ | `SyncStorageContextValue` | type | Sync storage context value type |
71
+ | `LogAdapter` | type | Log adapter interface |
72
+ | `LoggerContextValue` | type | Logger context value type |
73
+ | `ThemeMode` | type | `"light" \| "dark" \| "system"` |
74
+ | `ResolvedTheme` | type | `"light" \| "dark"` |
75
+ | `ServiceClientContextValue` | type | Service client context value type |
76
+ | `SharedDataDefinition` | type | Data subscription definition |
77
+ | `SharedDataAccessor` | type | Per-key data accessor |
78
+ | `SharedDataValue` | type | Full shared data context value |
79
+ | `BusyVariant` | type | `"spinner" \| "bar"` |
80
+ | `SharedDataChangeEvent` | class | Server-side change event definition |
125
81
 
126
- WebSocket client provider for RPC communication with `@simplysm/service-server`. Wraps `ServiceClient` from `@simplysm/service-client`. Provides `useServiceClient` hook to components.
82
+ ---
127
83
 
128
- `ServiceClientProvider` takes no props. After mounting, use `useServiceClient()` to connect, close, and access client instances by key.
84
+ ## SharedData Usage
129
85
 
130
86
  ```tsx
131
- import { ServiceClientProvider, useServiceClient } from "@simplysm/solid";
132
-
133
- // Wrap your app
134
- <ServiceClientProvider>
135
- <App />
136
- </ServiceClientProvider>
137
-
138
- // In a component
139
- function App() {
140
- const client = useServiceClient();
87
+ import { useSharedData } from "@simplysm/solid";
141
88
 
142
- onMount(async () => {
143
- await client.connect("main", { host: "localhost", port: 3000, ssl: false });
144
- });
89
+ function MyComponent() {
90
+ const sharedData = useSharedData<MySharedData>();
145
91
 
146
- onCleanup(async () => {
147
- await client.close("main");
148
- });
92
+ const users = () => sharedData.users.items(); // Accessor<TData[]>
93
+ const user = () => sharedData.users.get(userId()); // TData | undefined
149
94
 
150
- const handleCall = async () => {
151
- const svc = client.get("main");
152
- const result = await svc.call("MyService", "myMethod", [arg1, arg2]);
95
+ const handleUpdate = async () => {
96
+ await sharedData.users.emit([updatedUserId]); // trigger refetch for keys
153
97
  };
154
98
  }
155
99
  ```
156
100
 
157
- **useServiceClient API:**
158
-
159
- | Method | Signature | Description |
160
- |--------|-----------|-------------|
161
- | `connect` | `(key: string, options?: Partial<ServiceConnectionConfig>) => Promise<void>` | Open WebSocket connection |
162
- | `close` | `(key: string) => Promise<void>` | Close connection by key |
163
- | `get` | `(key: string) => ServiceClient` | Get connected client by key (throws if not connected) |
164
- | `isConnected` | `(key: string) => boolean` | Check connection state |
165
-
166
- `ServiceConnectionConfig`: `{ host: string; port: number; ssl: boolean }`
167
-
168
- Defaults for `host`, `port`, and `ssl` are derived from `window.location` when omitted.
169
-
170
- ---
171
-
172
- ## SharedDataProvider
173
-
174
- Shared data provider for managing server-side data subscriptions. Works with `ServiceClientProvider` to provide reactive shared data across components via `useSharedData`.
175
-
176
- ```tsx
177
- import { SharedDataProvider, type SharedDataDefinition } from "@simplysm/solid";
178
-
179
- interface MySharedData {
180
- users: UserRecord;
181
- products: ProductRecord;
182
- }
183
-
184
- const definitions: { [K in keyof MySharedData]: SharedDataDefinition<MySharedData[K]> } = {
185
- users: {
186
- serviceKey: "main",
187
- fetch: async (changeKeys) => fetchUsers(changeKeys),
188
- getKey: (item) => item.id,
189
- orderBy: [(item) => item.name, "asc"],
190
- },
191
- products: {
192
- serviceKey: "main",
193
- fetch: async (changeKeys) => fetchProducts(changeKeys),
194
- getKey: (item) => item.id,
195
- orderBy: [(item) => item.name, "asc"],
196
- },
197
- };
198
-
199
- <SharedDataProvider definitions={definitions}>
200
- <App />
201
- </SharedDataProvider>
202
- ```
203
-
204
- **SharedDataProvider Props:**
205
-
206
- | Prop | Type | Description |
207
- |------|------|-------------|
208
- | `definitions` | `{ [K in keyof TSharedData]: SharedDataDefinition<TSharedData[K]> }` | Map of data key to fetch definition |
209
-
210
101
  **SharedDataDefinition type:**
211
102
 
212
103
  ```typescript
@@ -219,23 +110,6 @@ interface SharedDataDefinition<TData> {
219
110
  }
220
111
  ```
221
112
 
222
- **useSharedData API:**
223
-
224
- ```tsx
225
- import { useSharedData } from "@simplysm/solid";
226
-
227
- function MyComponent() {
228
- const sharedData = useSharedData<MySharedData>();
229
-
230
- const users = () => sharedData.users.items(); // Accessor<TData[]>
231
- const user = () => sharedData.users.get(userId()); // TData | undefined
232
-
233
- const handleUpdate = async () => {
234
- await sharedData.users.emit([updatedUserId]); // trigger refetch for keys
235
- };
236
- }
237
- ```
238
-
239
113
  **SharedDataAccessor API:**
240
114
 
241
115
  | Property/Method | Type | Description |
@@ -250,10 +124,11 @@ function MyComponent() {
250
124
  |-----------------|------|-------------|
251
125
  | `wait` | `() => Promise<void>` | Wait until all initial fetches complete |
252
126
  | `busy` | `Accessor<boolean>` | True while any fetch is in progress |
127
+ | `configure` | `(definitions) => void` | Set up data subscriptions (call once after service client connects) |
253
128
 
254
129
  **SharedDataChangeEvent:**
255
130
 
256
- `SharedDataChangeEvent` is the event definition used internally by `SharedDataProvider` to communicate data changes between server and clients. Export it if you need to emit changes from the server side.
131
+ `SharedDataChangeEvent` is the event definition used internally to communicate data changes between server and clients. Export it if you need to emit changes from the server side.
257
132
 
258
133
  ```typescript
259
134
  import { SharedDataChangeEvent } from "@simplysm/solid";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@simplysm/solid",
3
- "version": "13.0.33",
3
+ "version": "13.0.35",
4
4
  "description": "심플리즘 패키지 - SolidJS 라이브러리",
5
5
  "author": "김석래",
6
6
  "license": "Apache-2.0",
@@ -49,8 +49,8 @@
49
49
  "solid-tiptap": "^0.8.0",
50
50
  "tailwind-merge": "^3.5.0",
51
51
  "tailwindcss": "^3.4.19",
52
- "@simplysm/core-browser": "13.0.33",
53
- "@simplysm/core-common": "13.0.33"
52
+ "@simplysm/core-browser": "13.0.35",
53
+ "@simplysm/core-common": "13.0.35"
54
54
  },
55
55
  "devDependencies": {
56
56
  "@solidjs/testing-library": "^0.8.10"