@uniai-fe/util-functions 0.1.1 → 0.2.1

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/README.md CHANGED
@@ -1,47 +1,3 @@
1
1
  # util / functions
2
2
 
3
3
  의존성을 최소화한 범용 도구 모음
4
-
5
- ## 빠른 사용법 (API + 환경변수)
6
-
7
- - 1단계만 기억하세요: **env 맵만 넘겨 `createBackendApiClientFromEnv`를 호출**합니다.
8
- - 예시:
9
-
10
- ```ts
11
- import { createBackendApiClientFromEnv } from "@uniai-fe/util-functions/api";
12
-
13
- // env 맵 → 도메인으로 바꿔주는 클라이언트를 한 번만 생성
14
- const api = createBackendApiClientFromEnv({
15
- ai: process.env.AI_API_BASE,
16
- db: process.env.DB_API_BASE,
17
- uniai: process.env.UNIAI_API_BASE,
18
- });
19
-
20
- export const { generateBackendQueryUrl_GET, fetchBackendQuery } = api;
21
- export const apiLog = api.logger; // == nextAPILog
22
- ```
23
-
24
- - 서비스 앱이든 모듈 패키지든 동일한 접근입니다. Next.js이면 `@uniai-fe/util-next`의 어댑터를 통해 같은 API를 그대로 사용하면 됩니다.
25
-
26
- ## 타입 선언 관리 메모
27
-
28
- - 내부 타입 정의는 `.d.ts` 대신 `.ts` 모듈(예: `src/core/format/types.ts`)로 유지합니다.
29
- - tsup 번들 과정에서 선언 전용 파일이 엔트리에 포함되면 경고가 발생할 수 있어,
30
- `.ts` 모듈로 import/export 하되 TypeScript가 컴파일 시 타입만 제거하도록 위임합니다.
31
-
32
- ## 동작 원리 / 로직 개요
33
-
34
- - `createBackendApiClientFromEnv`는 env 맵 → `resolveDomain` → API 클라이언트로 이어지는 단계를 한 번에 처리합니다. env가 비어 있으면 `process.env[${INFRA}_API_BASE]` → `infra` 문자열 순으로 fallback 합니다.
35
- - 직접 제어가 필요하면 `createEnvDomainResolver`를 사용해 resolver만 만들고 `createBackendApiClient`에 주입할 수 있습니다.
36
- - 클라이언트에서 얻을 수 있는 것들:
37
- - `generateBackendQueryUrl_GET`: 도메인 + 쿼리스트링 조합
38
- - `fetchBackendQuery`: POST/DELETE 등 본문 포함 요청과 로깅/대체응답 처리
39
- - `getQueryString`: 객체/URLSearchParams 직렬화
40
- - `logger`: 공통 포맷 로거
41
- - 이 구조 덕분에 최종 사용 단계는 “한 번 정의한 클라이언트에서 함수 가져다 쓰기”로 끝납니다.
42
-
43
- ## Next.js 유틸 안내
44
-
45
- - Next 서버 전용 API 도우미는 `@uniai-fe/util-next` 패키지로 이동했습니다.
46
- - 환경 구성(`api-infra.config.ts`)을 통해 도메인을 주입한 뒤 util-functions의 공용 API 헬퍼를 활용하세요.
47
- - JSX/파일 등 React 의존 유틸은 `@uniai-fe/util-react` 패키지에서 제공됩니다.
package/dist/index.cjs CHANGED
@@ -786,6 +786,101 @@ var fetchWithBody = async ({
786
786
  }
787
787
  };
788
788
 
789
+ // src/runtime-env/device.ts
790
+ var apple = ["iPhone", "iPad", "iPod", "Mac", "Macintosh"];
791
+ var tablet = ["Tablet", "iPad", "playbook", "silk"];
792
+ var mobile = [
793
+ "Android",
794
+ "Mobile",
795
+ "iPhone",
796
+ "iPod",
797
+ "iPad",
798
+ "BlackBerry",
799
+ "IEMobile",
800
+ "Kindle",
801
+ "NetFront",
802
+ "Silk-Accelerated",
803
+ "hpwOS",
804
+ "webOS",
805
+ "Fennec",
806
+ "Minimo",
807
+ "Opera Mobi",
808
+ "Opera Mini",
809
+ "Blazer",
810
+ "Dolfin",
811
+ "Dolphin",
812
+ "Skyfire",
813
+ "Zune"
814
+ ];
815
+ var userAgentCollection = {
816
+ apple,
817
+ tablet,
818
+ mobile
819
+ };
820
+ var setLowerCase = (v) => String(v).toLowerCase();
821
+ var deviceLowerCasePatterns = {
822
+ apple: apple.map(setLowerCase),
823
+ tablet: tablet.map(setLowerCase),
824
+ mobile: mobile.map(setLowerCase)
825
+ };
826
+ var checkResponsiveDevice = (userAgent) => {
827
+ const { mobile: mobile2, tablet: tablet2 } = deviceLowerCasePatterns;
828
+ const clientAgent = setLowerCase(userAgent);
829
+ const isTablet = tablet2.some((agent) => clientAgent.includes(agent));
830
+ const isMobile = mobile2.some((agent) => clientAgent.includes(agent));
831
+ if (isMobile) return isTablet ? "tablet" : "mobile";
832
+ return "desktop";
833
+ };
834
+ var checkAppleDevice = (userAgent) => {
835
+ const { apple: apple2 } = deviceLowerCasePatterns;
836
+ const clientAgent = setLowerCase(userAgent);
837
+ return apple2.some((agent) => clientAgent.includes(agent));
838
+ };
839
+
840
+ // src/runtime-env/pwa.ts
841
+ var DISPLAY_MODE_QUERIES = [
842
+ { mode: "standalone", query: "(display-mode: standalone)" },
843
+ { mode: "fullscreen", query: "(display-mode: fullscreen)" },
844
+ { mode: "minimal-ui", query: "(display-mode: minimal-ui)" },
845
+ { mode: "browser", query: "(display-mode: browser)" }
846
+ ];
847
+ var STANDALONE_DISPLAY_MODES = /* @__PURE__ */ new Set([
848
+ "standalone",
849
+ "fullscreen",
850
+ "minimal-ui"
851
+ ]);
852
+ var isWindowAvailable = () => typeof window !== "undefined";
853
+ var detectDisplayMode = () => {
854
+ if (!isWindowAvailable() || typeof window.matchMedia !== "function") {
855
+ return "unknown";
856
+ }
857
+ for (const { mode, query } of DISPLAY_MODE_QUERIES) {
858
+ if (window.matchMedia(query).matches) {
859
+ return mode;
860
+ }
861
+ }
862
+ return "unknown";
863
+ };
864
+ var detectNavigatorStandalone = () => {
865
+ if (!isWindowAvailable()) {
866
+ return false;
867
+ }
868
+ const nav = window.navigator;
869
+ return typeof nav.standalone === "boolean" ? Boolean(nav.standalone) : false;
870
+ };
871
+ var getPwaRuntimeInfo = () => {
872
+ const displayMode = detectDisplayMode();
873
+ const navigatorStandalone = detectNavigatorStandalone();
874
+ if (displayMode === "unknown" && navigatorStandalone) {
875
+ return { isStandalone: true, displayMode: "standalone" };
876
+ }
877
+ return {
878
+ displayMode,
879
+ isStandalone: displayMode === "unknown" ? navigatorStandalone : STANDALONE_DISPLAY_MODES.has(displayMode)
880
+ };
881
+ };
882
+ var checkStandaloneApp = getPwaRuntimeInfo;
883
+
789
884
  // src/form/checkbox/module.ts
790
885
  var syncAllToEach = (checkStateObject, allCheckState) => Object.fromEntries(
791
886
  Object.entries(checkStateObject).map(([key]) => [key, allCheckState])
@@ -831,7 +926,10 @@ var stylePaddingSize = styleSpacingSize;
831
926
  var styleMarginSize = styleSpacingSize;
832
927
 
833
928
  exports.capitalize = capitalize;
929
+ exports.checkAppleDevice = checkAppleDevice;
834
930
  exports.checkDateMoment = checkDateMoment;
931
+ exports.checkResponsiveDevice = checkResponsiveDevice;
932
+ exports.checkStandaloneApp = checkStandaloneApp;
835
933
  exports.convert2Digit = convert2Digit;
836
934
  exports.convertDigit = convertDigit;
837
935
  exports.convertLiter = convertLiter;
@@ -861,6 +959,7 @@ exports.getNextDay = getNextDay;
861
959
  exports.getNextWeeks = getNextWeeks;
862
960
  exports.getNumberReplaceComma = getNumberReplaceComma;
863
961
  exports.getPrevDay = getPrevDay;
962
+ exports.getPwaRuntimeInfo = getPwaRuntimeInfo;
864
963
  exports.getQueryString = getQueryString;
865
964
  exports.getRepeatCycleUnit = getRepeatCycleUnit;
866
965
  exports.getToday = getToday;
@@ -902,6 +1001,7 @@ exports.styleSpacingSize = styleSpacingSize;
902
1001
  exports.syncAllToEach = syncAllToEach;
903
1002
  exports.syncEachToAll = syncEachToAll;
904
1003
  exports.timeFormat = timeFormat;
1004
+ exports.userAgentCollection = userAgentCollection;
905
1005
  exports.weekOrderIndex = weekOrderIndex;
906
1006
  exports.weekOrderKo = weekOrderKo;
907
1007
  exports.weekdayByDayCode = weekdayByDayCode;