@things-factory/kpi 10.0.0-beta.9 → 10.0.0-beta.91

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 (41) hide show
  1. package/client/index.ts +1 -0
  2. package/client/pages/kpi/kpi-list-page.ts +150 -17
  3. package/client/pages/kpi-dashboard/components/kpi-map-panel.ts +2 -2
  4. package/client/pages/kpi-metric/kpi-metric-list-page.ts +17 -3
  5. package/dist-client/index.d.ts +1 -0
  6. package/dist-client/index.js +1 -1
  7. package/dist-client/index.js.map +1 -1
  8. package/dist-client/pages/kpi/kpi-list-page.d.ts +48 -3
  9. package/dist-client/pages/kpi/kpi-list-page.js +140 -18
  10. package/dist-client/pages/kpi/kpi-list-page.js.map +1 -1
  11. package/dist-client/pages/kpi-dashboard/components/kpi-map-panel.js +2 -2
  12. package/dist-client/pages/kpi-dashboard/components/kpi-map-panel.js.map +1 -1
  13. package/dist-client/pages/kpi-metric/kpi-metric-list-page.js +17 -3
  14. package/dist-client/pages/kpi-metric/kpi-metric-list-page.js.map +1 -1
  15. package/dist-client/tsconfig.tsbuildinfo +1 -1
  16. package/dist-server/service/kpi/kpi-query.d.ts +1 -1
  17. package/dist-server/service/kpi/kpi-query.js +38 -16
  18. package/dist-server/service/kpi/kpi-query.js.map +1 -1
  19. package/dist-server/service/kpi/kpi-type.d.ts +5 -1
  20. package/dist-server/service/kpi/kpi-type.js +28 -0
  21. package/dist-server/service/kpi/kpi-type.js.map +1 -1
  22. package/dist-server/service/kpi/kpi.d.ts +64 -0
  23. package/dist-server/service/kpi/kpi.js +89 -1
  24. package/dist-server/service/kpi/kpi.js.map +1 -1
  25. package/dist-server/service/kpi-metric/kpi-metric-mutation.js +15 -7
  26. package/dist-server/service/kpi-metric/kpi-metric-mutation.js.map +1 -1
  27. package/dist-server/service/kpi-metric/kpi-metric-query.d.ts +2 -0
  28. package/dist-server/service/kpi-metric/kpi-metric-query.js +30 -5
  29. package/dist-server/service/kpi-metric/kpi-metric-query.js.map +1 -1
  30. package/dist-server/service/kpi-metric/kpi-metric-type.d.ts +3 -2
  31. package/dist-server/service/kpi-metric/kpi-metric-type.js +7 -6
  32. package/dist-server/service/kpi-metric/kpi-metric-type.js.map +1 -1
  33. package/dist-server/service/kpi-metric-value/kpi-metric-value-query.js +10 -3
  34. package/dist-server/service/kpi-metric-value/kpi-metric-value-query.js.map +1 -1
  35. package/dist-server/service/kpi-value/kpi-value-query.js +10 -3
  36. package/dist-server/service/kpi-value/kpi-value-query.js.map +1 -1
  37. package/dist-server/service/utils/domain-inheritance.d.ts +17 -0
  38. package/dist-server/service/utils/domain-inheritance.js +69 -0
  39. package/dist-server/service/utils/domain-inheritance.js.map +1 -0
  40. package/dist-server/tsconfig.tsbuildinfo +1 -1
  41. package/package.json +5 -5
@@ -0,0 +1,17 @@
1
+ import { Domain } from '@things-factory/shell';
2
+ export declare function getDomainIdsWithAncestors(domain: Domain): Promise<string[]>;
3
+ /**
4
+ * "가까운 도메인 우선(override)" 의미 구현.
5
+ * 여러 ancestor 도메인의 항목들 중 같은 키(name 등)가 중복 존재하면
6
+ * domainIds 배열에서 더 앞(=가까운 도메인)에 있는 도메인에 속한 항목 1개만 남긴다.
7
+ *
8
+ * - domainIds: closest-first 순서 (getDomainIdsWithAncestors 결과)
9
+ * - keyFn: 중복 판정 키 (예: kpi.name)
10
+ *
11
+ * 정렬은 호출자가 다시 적용해야 한다 (typeorm 의 사전 정렬은 dedup 으로 깨지지 않음 -
12
+ * 같은 키 그룹 내부의 선택만 바뀌고 그룹의 위치는 입력 순서를 유지하므로
13
+ * 안정적이다).
14
+ */
15
+ export declare function dedupByClosestDomain<T extends {
16
+ domainId?: string;
17
+ }>(items: T[], domainIds: string[], keyFn: (item: T) => string | undefined): T[];
@@ -0,0 +1,69 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.getDomainIdsWithAncestors = getDomainIdsWithAncestors;
4
+ exports.dedupByClosestDomain = dedupByClosestDomain;
5
+ const shell_1 = require("@things-factory/shell");
6
+ /**
7
+ * 멀티테넌트 도메인 다단계 상속 헬퍼.
8
+ *
9
+ * SYSTEM → PROJECT-TEMPLATE → project 처럼 계층이 깊어질 수 있으므로
10
+ * 현재 도메인 부터 루트(부모가 없는 도메인)까지의 ancestor id 를
11
+ * "가까운 순서대로" 반환한다. (closest-first)
12
+ *
13
+ * - 사용처: 단일 fetch 의 `In([...])`, list 조회의 `andWhere('domain IN (:...ids)')`,
14
+ * 그리고 closest-wins dedup 의 우선순위 키.
15
+ *
16
+ * 깊이는 보통 2~3 이지만 순환 방지 + 최대 깊이(10) 안전장치를 둔다.
17
+ */
18
+ const MAX_ANCESTOR_DEPTH = 10;
19
+ async function getDomainIdsWithAncestors(domain) {
20
+ const ids = [domain.id];
21
+ const seen = new Set([domain.id]);
22
+ let parentId = domain.parentId;
23
+ let depth = 0;
24
+ while (parentId && !seen.has(parentId) && depth < MAX_ANCESTOR_DEPTH) {
25
+ seen.add(parentId);
26
+ ids.push(parentId);
27
+ const parent = await (0, shell_1.getRepository)(shell_1.Domain).findOne({ where: { id: parentId } });
28
+ parentId = parent?.parentId;
29
+ depth++;
30
+ }
31
+ return ids;
32
+ }
33
+ /**
34
+ * "가까운 도메인 우선(override)" 의미 구현.
35
+ * 여러 ancestor 도메인의 항목들 중 같은 키(name 등)가 중복 존재하면
36
+ * domainIds 배열에서 더 앞(=가까운 도메인)에 있는 도메인에 속한 항목 1개만 남긴다.
37
+ *
38
+ * - domainIds: closest-first 순서 (getDomainIdsWithAncestors 결과)
39
+ * - keyFn: 중복 판정 키 (예: kpi.name)
40
+ *
41
+ * 정렬은 호출자가 다시 적용해야 한다 (typeorm 의 사전 정렬은 dedup 으로 깨지지 않음 -
42
+ * 같은 키 그룹 내부의 선택만 바뀌고 그룹의 위치는 입력 순서를 유지하므로
43
+ * 안정적이다).
44
+ */
45
+ function dedupByClosestDomain(items, domainIds, keyFn) {
46
+ const rankOf = (domainId) => {
47
+ if (!domainId)
48
+ return Number.MAX_SAFE_INTEGER;
49
+ const idx = domainIds.indexOf(domainId);
50
+ return idx < 0 ? Number.MAX_SAFE_INTEGER : idx;
51
+ };
52
+ const byKey = new Map();
53
+ const order = [];
54
+ for (const item of items) {
55
+ const key = keyFn(item);
56
+ if (key == null)
57
+ continue;
58
+ const existing = byKey.get(key);
59
+ if (!existing) {
60
+ byKey.set(key, item);
61
+ order.push(key);
62
+ }
63
+ else if (rankOf(item.domainId) < rankOf(existing.domainId)) {
64
+ byKey.set(key, item);
65
+ }
66
+ }
67
+ return order.map(k => byKey.get(k));
68
+ }
69
+ //# sourceMappingURL=domain-inheritance.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"domain-inheritance.js","sourceRoot":"","sources":["../../../server/service/utils/domain-inheritance.ts"],"names":[],"mappings":";;AAgBA,8DAiBC;AAcD,oDA4BC;AA3ED,iDAA6D;AAE7D;;;;;;;;;;;GAWG;AACH,MAAM,kBAAkB,GAAG,EAAE,CAAA;AAEtB,KAAK,UAAU,yBAAyB,CAAC,MAAc;IAC5D,MAAM,GAAG,GAAa,CAAC,MAAM,CAAC,EAAE,CAAC,CAAA;IACjC,MAAM,IAAI,GAAG,IAAI,GAAG,CAAS,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC,CAAA;IAEzC,IAAI,QAAQ,GAAuB,MAAM,CAAC,QAAQ,CAAA;IAClD,IAAI,KAAK,GAAG,CAAC,CAAA;IAEb,OAAO,QAAQ,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,QAAQ,CAAC,IAAI,KAAK,GAAG,kBAAkB,EAAE,CAAC;QACrE,IAAI,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAA;QAClB,GAAG,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAA;QAElB,MAAM,MAAM,GAAG,MAAM,IAAA,qBAAa,EAAC,cAAM,CAAC,CAAC,OAAO,CAAC,EAAE,KAAK,EAAE,EAAE,EAAE,EAAE,QAAQ,EAAE,EAAE,CAAC,CAAA;QAC/E,QAAQ,GAAG,MAAM,EAAE,QAAQ,CAAA;QAC3B,KAAK,EAAE,CAAA;IACT,CAAC;IAED,OAAO,GAAG,CAAA;AACZ,CAAC;AAED;;;;;;;;;;;GAWG;AACH,SAAgB,oBAAoB,CAClC,KAAU,EACV,SAAmB,EACnB,KAAsC;IAEtC,MAAM,MAAM,GAAG,CAAC,QAA4B,EAAU,EAAE;QACtD,IAAI,CAAC,QAAQ;YAAE,OAAO,MAAM,CAAC,gBAAgB,CAAA;QAC7C,MAAM,GAAG,GAAG,SAAS,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAA;QACvC,OAAO,GAAG,GAAG,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,gBAAgB,CAAC,CAAC,CAAC,GAAG,CAAA;IAChD,CAAC,CAAA;IAED,MAAM,KAAK,GAAG,IAAI,GAAG,EAAa,CAAA;IAClC,MAAM,KAAK,GAAa,EAAE,CAAA;IAE1B,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;QACzB,MAAM,GAAG,GAAG,KAAK,CAAC,IAAI,CAAC,CAAA;QACvB,IAAI,GAAG,IAAI,IAAI;YAAE,SAAQ;QAEzB,MAAM,QAAQ,GAAG,KAAK,CAAC,GAAG,CAAC,GAAG,CAAC,CAAA;QAC/B,IAAI,CAAC,QAAQ,EAAE,CAAC;YACd,KAAK,CAAC,GAAG,CAAC,GAAG,EAAE,IAAI,CAAC,CAAA;YACpB,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,CAAA;QACjB,CAAC;aAAM,IAAI,MAAM,CAAC,IAAI,CAAC,QAAQ,CAAC,GAAG,MAAM,CAAC,QAAQ,CAAC,QAAQ,CAAC,EAAE,CAAC;YAC7D,KAAK,CAAC,GAAG,CAAC,GAAG,EAAE,IAAI,CAAC,CAAA;QACtB,CAAC;IACH,CAAC;IAED,OAAO,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAE,CAAC,CAAA;AACtC,CAAC","sourcesContent":["import { Domain, getRepository } from '@things-factory/shell'\n\n/**\n * 멀티테넌트 도메인 다단계 상속 헬퍼.\n *\n * SYSTEM → PROJECT-TEMPLATE → project 처럼 계층이 깊어질 수 있으므로\n * 현재 도메인 부터 루트(부모가 없는 도메인)까지의 ancestor id 를\n * \"가까운 순서대로\" 반환한다. (closest-first)\n *\n * - 사용처: 단일 fetch 의 `In([...])`, list 조회의 `andWhere('domain IN (:...ids)')`,\n * 그리고 closest-wins dedup 의 우선순위 키.\n *\n * 깊이는 보통 2~3 이지만 순환 방지 + 최대 깊이(10) 안전장치를 둔다.\n */\nconst MAX_ANCESTOR_DEPTH = 10\n\nexport async function getDomainIdsWithAncestors(domain: Domain): Promise<string[]> {\n const ids: string[] = [domain.id]\n const seen = new Set<string>([domain.id])\n\n let parentId: string | undefined = domain.parentId\n let depth = 0\n\n while (parentId && !seen.has(parentId) && depth < MAX_ANCESTOR_DEPTH) {\n seen.add(parentId)\n ids.push(parentId)\n\n const parent = await getRepository(Domain).findOne({ where: { id: parentId } })\n parentId = parent?.parentId\n depth++\n }\n\n return ids\n}\n\n/**\n * \"가까운 도메인 우선(override)\" 의미 구현.\n * 여러 ancestor 도메인의 항목들 중 같은 키(name 등)가 중복 존재하면\n * domainIds 배열에서 더 앞(=가까운 도메인)에 있는 도메인에 속한 항목 1개만 남긴다.\n *\n * - domainIds: closest-first 순서 (getDomainIdsWithAncestors 결과)\n * - keyFn: 중복 판정 키 (예: kpi.name)\n *\n * 정렬은 호출자가 다시 적용해야 한다 (typeorm 의 사전 정렬은 dedup 으로 깨지지 않음 -\n * 같은 키 그룹 내부의 선택만 바뀌고 그룹의 위치는 입력 순서를 유지하므로\n * 안정적이다).\n */\nexport function dedupByClosestDomain<T extends { domainId?: string }>(\n items: T[],\n domainIds: string[],\n keyFn: (item: T) => string | undefined\n): T[] {\n const rankOf = (domainId: string | undefined): number => {\n if (!domainId) return Number.MAX_SAFE_INTEGER\n const idx = domainIds.indexOf(domainId)\n return idx < 0 ? Number.MAX_SAFE_INTEGER : idx\n }\n\n const byKey = new Map<string, T>()\n const order: string[] = []\n\n for (const item of items) {\n const key = keyFn(item)\n if (key == null) continue\n\n const existing = byKey.get(key)\n if (!existing) {\n byKey.set(key, item)\n order.push(key)\n } else if (rankOf(item.domainId) < rankOf(existing.domainId)) {\n byKey.set(key, item)\n }\n }\n\n return order.map(k => byKey.get(k)!)\n}\n"]}