sayren 0.3.4 → 0.5.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.
Files changed (2) hide show
  1. package/dist/index.mjs +2844 -520
  2. package/package.json +4 -3
package/dist/index.mjs CHANGED
@@ -2,11 +2,13 @@
2
2
  import { spawn, spawnSync } from "node:child_process";
3
3
  import { stdin, stdout } from "node:process";
4
4
  import { createInterface } from "node:readline/promises";
5
- import { ApiError, ApprovalPendingError, STOREFRONT_BUILD_TERMINAL_STATUSES, STOREFRONT_SOURCE_BLOB_BATCH_MAX, createStoreClient, normalizeStorefrontPath } from "@sayren/store-sdk";
5
+ import { APP_DEPLOY_KEY_PATTERN, APP_SECRET_PATTERNS, APP_SERVER_BUNDLE_MAX_GZIP_BYTES, APP_UI_MAX_BYTES, APP_UI_MAX_FILES, ApiError, ApprovalPendingError, STOREFRONT_BUILD_TERMINAL_STATUSES, STOREFRONT_SOURCE_BLOB_BATCH_MAX, appManifestProblems, appManifestSchema, createStoreClient, normalizeStorefrontPath } from "@sayren/store-sdk";
6
6
  import { chmodSync, closeSync, existsSync, lstatSync, mkdirSync, openSync, readFileSync, readdirSync, rmSync, statSync, writeFileSync } from "node:fs";
7
- import { dirname, join, relative, resolve, sep } from "node:path";
8
- import { createHash, randomBytes } from "node:crypto";
9
7
  import { createServer } from "node:http";
8
+ import { dirname, extname, join, relative, resolve, sep } from "node:path";
9
+ import { pathToFileURL } from "node:url";
10
+ import { gzipSync } from "node:zlib";
11
+ import { createHash, randomBytes } from "node:crypto";
10
12
 
11
13
  //#region ../i18n/src/paraglide/runtime.js
12
14
  /** @type {any} */
@@ -681,26 +683,6 @@ defineCustomClientStrategy("custom-query", {
681
683
  setLocale: () => {}
682
684
  });
683
685
 
684
- //#endregion
685
- //#region ../i18n/src/lazy-messages.ts
686
- /**
687
- * 라벨 표 — 값을 읽을 때마다 메시지 함수를 불러 그 순간의 로케일 문구를 돌려준다(이슈 #73).
688
- * 모듈을 읽을 때 문구를 만들면 서버 렌더링에서 요청 로케일이 아니라 기동 시점 로케일로 굳는다.
689
- * 타입은 `Record<K, string>`이라 호출부(`LABEL[key]`, `Object.entries(LABEL)`)를 바꾸지 않는다.
690
- *
691
- * ```ts
692
- * export const ROLE_LABEL = lazyMessages<StoreRole>({ OWNER: m.store_shell_role_owner, ... });
693
- * ```
694
- */
695
- function lazyMessages(table) {
696
- const labels = {};
697
- for (const key of Object.keys(table)) Object.defineProperty(labels, key, {
698
- enumerable: true,
699
- get: () => table[key]()
700
- });
701
- return Object.freeze(labels);
702
- }
703
-
704
686
  //#endregion
705
687
  //#region ../i18n/src/paraglide/messages/cli_access_token_expired.js
706
688
  /** @typedef {import('../runtime.js').LocalizedString} LocalizedString */
@@ -774,1120 +756,2361 @@ const cli_accounts_unreachable = ((inputs = {}, options = {}) => {
774
756
  });
775
757
 
776
758
  //#endregion
777
- //#region ../i18n/src/paraglide/messages/cli_approval_id.js
759
+ //#region ../i18n/src/paraglide/messages/cli_app_bridge_missing.js
778
760
  /** @typedef {import('../runtime.js').LocalizedString} LocalizedString */
779
- /** @typedef {{ id: NonNullable<unknown> }} Cli_Approval_IdInputs */
780
- const ko_cli_approval_id = (i) => {
781
- return `승인 요청 id: ${i?.id} (상점 플랫폼 › 설정 › 보안 › 승인 요청)`;
761
+ /** @typedef {{}} Cli_App_Bridge_MissingInputs */
762
+ const ko_cli_app_bridge_missing = () => {
763
+ return `앱 폴더에 @sayren/app이 설치돼 있지 않습니다(ui/_sayren/ui.js를 만들 수 없습니다). npm install을 먼저 하십시오`;
782
764
  };
783
765
  /**
784
766
 
785
- * @param {Cli_Approval_IdInputs} inputs
767
+ * @param {Cli_App_Bridge_MissingInputs} inputs
786
768
  * @param {{ locale?: "ko" }} options
787
769
  * @returns {LocalizedString}
788
770
  */
789
- const cli_approval_id = ((inputs, options = {}) => {
771
+ const cli_app_bridge_missing = ((inputs = {}, options = {}) => {
790
772
  experimentalStaticLocale ?? options.locale ?? getLocale();
791
- return ko_cli_approval_id(inputs);
773
+ return ko_cli_app_bridge_missing(inputs);
792
774
  });
793
775
 
794
776
  //#endregion
795
- //#region ../i18n/src/paraglide/messages/cli_approval_url.js
777
+ //#region ../i18n/src/paraglide/messages/cli_app_build_failed.js
796
778
  /** @typedef {import('../runtime.js').LocalizedString} LocalizedString */
797
- /** @typedef {{ url: NonNullable<unknown> }} Cli_Approval_UrlInputs */
798
- const ko_cli_approval_url = (i) => {
799
- return `승인 요청: ${i?.url}`;
779
+ /** @typedef {{ stage: NonNullable<unknown>, code: NonNullable<unknown>, tail: NonNullable<unknown> }} Cli_App_Build_FailedInputs */
780
+ const ko_cli_app_build_failed = (i) => {
781
+ return `빌드 실패: ${i?.stage} (${i?.code})
782
+ ${i?.tail}`;
800
783
  };
801
784
  /**
802
785
 
803
- * @param {Cli_Approval_UrlInputs} inputs
786
+ * @param {Cli_App_Build_FailedInputs} inputs
804
787
  * @param {{ locale?: "ko" }} options
805
788
  * @returns {LocalizedString}
806
789
  */
807
- const cli_approval_url = ((inputs, options = {}) => {
790
+ const cli_app_build_failed = ((inputs, options = {}) => {
808
791
  experimentalStaticLocale ?? options.locale ?? getLocale();
809
- return ko_cli_approval_url(inputs);
792
+ return ko_cli_app_build_failed(inputs);
810
793
  });
811
794
 
812
795
  //#endregion
813
- //#region ../i18n/src/paraglide/messages/cli_auth_login_missing.js
796
+ //#region ../i18n/src/paraglide/messages/cli_app_bundle_failed.js
814
797
  /** @typedef {import('../runtime.js').LocalizedString} LocalizedString */
815
- /** @typedef {{}} Cli_Auth_Login_MissingInputs */
816
- const ko_cli_auth_login_missing = () => {
817
- return `로그인 정보가 없습니다. npx sayren login으로 다시 로그인하십시오`;
798
+ /** @typedef {{ tail: NonNullable<unknown> }} Cli_App_Bundle_FailedInputs */
799
+ const ko_cli_app_bundle_failed = (i) => {
800
+ return `서버 번들을 만들지 못했습니다:
801
+ ${i?.tail}`;
818
802
  };
819
803
  /**
820
804
 
821
- * @param {Cli_Auth_Login_MissingInputs} inputs
805
+ * @param {Cli_App_Bundle_FailedInputs} inputs
822
806
  * @param {{ locale?: "ko" }} options
823
807
  * @returns {LocalizedString}
824
808
  */
825
- const cli_auth_login_missing = ((inputs = {}, options = {}) => {
809
+ const cli_app_bundle_failed = ((inputs, options = {}) => {
826
810
  experimentalStaticLocale ?? options.locale ?? getLocale();
827
- return ko_cli_auth_login_missing(inputs);
811
+ return ko_cli_app_bundle_failed(inputs);
828
812
  });
829
813
 
830
814
  //#endregion
831
- //#region ../i18n/src/paraglide/messages/cli_blobs_missing.js
815
+ //#region ../i18n/src/paraglide/messages/cli_app_bundle_too_large.js
832
816
  /** @typedef {import('../runtime.js').LocalizedString} LocalizedString */
833
- /** @typedef {{}} Cli_Blobs_MissingInputs */
834
- const ko_cli_blobs_missing = () => {
835
- return `파일 내용을 올렸지만 서버가 찾지 못했습니다. 잠시 뒤 다시 배포하십시오`;
817
+ /** @typedef {{ size: NonNullable<unknown> }} Cli_App_Bundle_Too_LargeInputs */
818
+ const ko_cli_app_bundle_too_large = (i) => {
819
+ return `서버 번들이 ${i?.size}(gzip)입니다. 상한은 3MB입니다 (ARTIFACT_TOO_LARGE)`;
836
820
  };
837
821
  /**
838
822
 
839
- * @param {Cli_Blobs_MissingInputs} inputs
823
+ * @param {Cli_App_Bundle_Too_LargeInputs} inputs
840
824
  * @param {{ locale?: "ko" }} options
841
825
  * @returns {LocalizedString}
842
826
  */
843
- const cli_blobs_missing = ((inputs = {}, options = {}) => {
827
+ const cli_app_bundle_too_large = ((inputs, options = {}) => {
844
828
  experimentalStaticLocale ?? options.locale ?? getLocale();
845
- return ko_cli_blobs_missing(inputs);
829
+ return ko_cli_app_bundle_too_large(inputs);
846
830
  });
847
831
 
848
832
  //#endregion
849
- //#region ../i18n/src/paraglide/messages/cli_blobs_uploaded.js
833
+ //#region ../i18n/src/paraglide/messages/cli_app_default_export_missing.js
850
834
  /** @typedef {import('../runtime.js').LocalizedString} LocalizedString */
851
- /** @typedef {{ count: NonNullable<unknown> }} Cli_Blobs_UploadedInputs */
852
- const ko_cli_blobs_uploaded = (i) => {
853
- return `바뀐 파일 ${i?.count}개 올림`;
835
+ /** @typedef {{}} Cli_App_Default_Export_MissingInputs */
836
+ const ko_cli_app_default_export_missing = () => {
837
+ return `src/server.ts가 defineApp(...)을 기본 내보내기(export default)해야 합니다`;
854
838
  };
855
839
  /**
856
840
 
857
- * @param {Cli_Blobs_UploadedInputs} inputs
841
+ * @param {Cli_App_Default_Export_MissingInputs} inputs
858
842
  * @param {{ locale?: "ko" }} options
859
843
  * @returns {LocalizedString}
860
844
  */
861
- const cli_blobs_uploaded = ((inputs, options = {}) => {
845
+ const cli_app_default_export_missing = ((inputs = {}, options = {}) => {
862
846
  experimentalStaticLocale ?? options.locale ?? getLocale();
863
- return ko_cli_blobs_uploaded(inputs);
847
+ return ko_cli_app_default_export_missing(inputs);
864
848
  });
865
849
 
866
850
  //#endregion
867
- //#region ../i18n/src/paraglide/messages/cli_build_dependencies_blocked.js
851
+ //#region ../i18n/src/paraglide/messages/cli_app_deploy_done.js
868
852
  /** @typedef {import('../runtime.js').LocalizedString} LocalizedString */
869
- /** @typedef {{}} Cli_Build_Dependencies_BlockedInputs */
870
- const ko_cli_build_dependencies_blocked = () => {
871
- return `npm 의존성 검사에서 막혔습니다. 아래 사유의 패키지를 빼거나 바꾼 뒤 다시 배포하십시오`;
853
+ /** @typedef {{ number: NonNullable<unknown> }} Cli_App_Deploy_DoneInputs */
854
+ const ko_cli_app_deploy_done = (i) => {
855
+ return `버전 ${i?.number}을 만들었습니다. 적용하려면: npx sayren app release ${i?.number}`;
872
856
  };
873
857
  /**
874
858
 
875
- * @param {Cli_Build_Dependencies_BlockedInputs} inputs
859
+ * @param {Cli_App_Deploy_DoneInputs} inputs
876
860
  * @param {{ locale?: "ko" }} options
877
861
  * @returns {LocalizedString}
878
862
  */
879
- const cli_build_dependencies_blocked = ((inputs = {}, options = {}) => {
863
+ const cli_app_deploy_done = ((inputs, options = {}) => {
880
864
  experimentalStaticLocale ?? options.locale ?? getLocale();
881
- return ko_cli_build_dependencies_blocked(inputs);
865
+ return ko_cli_app_deploy_done(inputs);
882
866
  });
883
867
 
884
868
  //#endregion
885
- //#region ../i18n/src/paraglide/messages/cli_build_failed.js
869
+ //#region ../i18n/src/paraglide/messages/cli_app_dev_error.js
886
870
  /** @typedef {import('../runtime.js').LocalizedString} LocalizedString */
887
- /** @typedef {{ stage: NonNullable<unknown> }} Cli_Build_FailedInputs */
888
- const ko_cli_build_failed = (i) => {
889
- return `빌드 실패 — ${i?.stage}`;
871
+ /** @typedef {{ message: NonNullable<unknown> }} Cli_App_Dev_ErrorInputs */
872
+ const ko_cli_app_dev_error = (i) => {
873
+ return `로컬 실행 오류: ${i?.message}`;
890
874
  };
891
875
  /**
892
876
 
893
- * @param {Cli_Build_FailedInputs} inputs
877
+ * @param {Cli_App_Dev_ErrorInputs} inputs
894
878
  * @param {{ locale?: "ko" }} options
895
879
  * @returns {LocalizedString}
896
880
  */
897
- const cli_build_failed = ((inputs, options = {}) => {
881
+ const cli_app_dev_error = ((inputs, options = {}) => {
898
882
  experimentalStaticLocale ?? options.locale ?? getLocale();
899
- return ko_cli_build_failed(inputs);
883
+ return ko_cli_app_dev_error(inputs);
900
884
  });
901
885
 
902
886
  //#endregion
903
- //#region ../i18n/src/paraglide/messages/cli_build_failed_code.js
887
+ //#region ../i18n/src/paraglide/messages/cli_app_dev_listening.js
904
888
  /** @typedef {import('../runtime.js').LocalizedString} LocalizedString */
905
- /** @typedef {{ stage: NonNullable<unknown>, code: NonNullable<unknown> }} Cli_Build_Failed_CodeInputs */
906
- const ko_cli_build_failed_code = (i) => {
907
- return `빌드 실패 — ${i?.stage} (${i?.code})`;
889
+ /** @typedef {{ port: NonNullable<unknown>, store: NonNullable<unknown>, events: NonNullable<unknown> }} Cli_App_Dev_ListeningInputs */
890
+ const ko_cli_app_dev_listening = (i) => {
891
+ return `앱 로컬 실행 중 http://localhost:${i?.port} — 상점 ${i?.store} · 이벤트 ${i?.events}
892
+ 이벤트: npx sayren app trigger ORDER.PAID --order <orderId>
893
+ HTTP: http://localhost:${i?.port}/_http/<경로>
894
+ 설정·비밀 값: .env의 SAYREN_APP_SETTING_*·SAYREN_APP_SECRET_*
895
+ 종료는 Ctrl-C`;
908
896
  };
909
897
  /**
910
898
 
911
- * @param {Cli_Build_Failed_CodeInputs} inputs
899
+ * @param {Cli_App_Dev_ListeningInputs} inputs
912
900
  * @param {{ locale?: "ko" }} options
913
901
  * @returns {LocalizedString}
914
902
  */
915
- const cli_build_failed_code = ((inputs, options = {}) => {
903
+ const cli_app_dev_listening = ((inputs, options = {}) => {
916
904
  experimentalStaticLocale ?? options.locale ?? getLocale();
917
- return ko_cli_build_failed_code(inputs);
905
+ return ko_cli_app_dev_listening(inputs);
918
906
  });
919
907
 
920
908
  //#endregion
921
- //#region ../i18n/src/paraglide/messages/cli_build_log_tail.js
909
+ //#region ../i18n/src/paraglide/messages/cli_app_dev_store_created.js
922
910
  /** @typedef {import('../runtime.js').LocalizedString} LocalizedString */
923
- /** @typedef {{}} Cli_Build_Log_TailInputs */
924
- const ko_cli_build_log_tail = () => {
925
- return `로그 꼬리:`;
911
+ /** @typedef {{ name: NonNullable<unknown>, storeId: NonNullable<unknown> }} Cli_App_Dev_Store_CreatedInputs */
912
+ const ko_cli_app_dev_store_created = (i) => {
913
+ return `개발 상점을 만들었습니다: ${i?.name} (${i?.storeId})`;
926
914
  };
927
915
  /**
928
916
 
929
- * @param {Cli_Build_Log_TailInputs} inputs
917
+ * @param {Cli_App_Dev_Store_CreatedInputs} inputs
930
918
  * @param {{ locale?: "ko" }} options
931
919
  * @returns {LocalizedString}
932
920
  */
933
- const cli_build_log_tail = ((inputs = {}, options = {}) => {
921
+ const cli_app_dev_store_created = ((inputs, options = {}) => {
934
922
  experimentalStaticLocale ?? options.locale ?? getLocale();
935
- return ko_cli_build_log_tail(inputs);
923
+ return ko_cli_app_dev_store_created(inputs);
936
924
  });
937
925
 
938
926
  //#endregion
939
- //#region ../i18n/src/paraglide/messages/cli_build_stage.js
927
+ //#region ../i18n/src/paraglide/messages/cli_app_dev_store_empty.js
940
928
  /** @typedef {import('../runtime.js').LocalizedString} LocalizedString */
941
- /** @typedef {{ mark: NonNullable<unknown>, stage: NonNullable<unknown>, seconds: NonNullable<unknown> }} Cli_Build_StageInputs */
942
- const ko_cli_build_stage = (i) => {
943
- return `${i?.mark} ${i?.stage} ${i?.seconds}초`;
929
+ /** @typedef {{}} Cli_App_Dev_Store_EmptyInputs */
930
+ const ko_cli_app_dev_store_empty = () => {
931
+ return `개발 상점이 없습니다. npx sayren app dev-store create <이름>`;
944
932
  };
945
933
  /**
946
934
 
947
- * @param {Cli_Build_StageInputs} inputs
935
+ * @param {Cli_App_Dev_Store_EmptyInputs} inputs
948
936
  * @param {{ locale?: "ko" }} options
949
937
  * @returns {LocalizedString}
950
938
  */
951
- const cli_build_stage = ((inputs, options = {}) => {
939
+ const cli_app_dev_store_empty = ((inputs = {}, options = {}) => {
952
940
  experimentalStaticLocale ?? options.locale ?? getLocale();
953
- return ko_cli_build_stage(inputs);
941
+ return ko_cli_app_dev_store_empty(inputs);
954
942
  });
955
943
 
956
944
  //#endregion
957
- //#region ../i18n/src/paraglide/messages/cli_build_stage_unknown.js
945
+ //#region ../i18n/src/paraglide/messages/cli_app_dev_store_name_required.js
958
946
  /** @typedef {import('../runtime.js').LocalizedString} LocalizedString */
959
- /** @typedef {{}} Cli_Build_Stage_UnknownInputs */
960
- const ko_cli_build_stage_unknown = () => {
961
- return `알 수 없는 단계`;
947
+ /** @typedef {{}} Cli_App_Dev_Store_Name_RequiredInputs */
948
+ const ko_cli_app_dev_store_name_required = () => {
949
+ return `개발 상점 이름이 필요합니다(2~50자)`;
962
950
  };
963
951
  /**
964
952
 
965
- * @param {Cli_Build_Stage_UnknownInputs} inputs
953
+ * @param {Cli_App_Dev_Store_Name_RequiredInputs} inputs
966
954
  * @param {{ locale?: "ko" }} options
967
955
  * @returns {LocalizedString}
968
956
  */
969
- const cli_build_stage_unknown = ((inputs = {}, options = {}) => {
957
+ const cli_app_dev_store_name_required = ((inputs = {}, options = {}) => {
970
958
  experimentalStaticLocale ?? options.locale ?? getLocale();
971
- return ko_cli_build_stage_unknown(inputs);
959
+ return ko_cli_app_dev_store_name_required(inputs);
972
960
  });
973
961
 
974
962
  //#endregion
975
- //#region ../i18n/src/paraglide/messages/cli_build_timeout.js
963
+ //#region ../i18n/src/paraglide/messages/cli_app_dir_exists.js
976
964
  /** @typedef {import('../runtime.js').LocalizedString} LocalizedString */
977
- /** @typedef {{ minutes: NonNullable<unknown> }} Cli_Build_TimeoutInputs */
978
- const ko_cli_build_timeout = (i) => {
979
- return `빌드가 ${i?.minutes}분 안에 끝나지 않았습니다. npx sayren status로 결과를 확인하십시오`;
965
+ /** @typedef {{ dir: NonNullable<unknown> }} Cli_App_Dir_ExistsInputs */
966
+ const ko_cli_app_dir_exists = (i) => {
967
+ return `${i?.dir}에 이미 sayren.app.json이 있습니다`;
980
968
  };
981
969
  /**
982
970
 
983
- * @param {Cli_Build_TimeoutInputs} inputs
971
+ * @param {Cli_App_Dir_ExistsInputs} inputs
984
972
  * @param {{ locale?: "ko" }} options
985
973
  * @returns {LocalizedString}
986
974
  */
987
- const cli_build_timeout = ((inputs, options = {}) => {
975
+ const cli_app_dir_exists = ((inputs, options = {}) => {
988
976
  experimentalStaticLocale ?? options.locale ?? getLocale();
989
- return ko_cli_build_timeout(inputs);
977
+ return ko_cli_app_dir_exists(inputs);
990
978
  });
991
979
 
992
980
  //#endregion
993
- //#region ../i18n/src/paraglide/messages/cli_cancelled.js
981
+ //#region ../i18n/src/paraglide/messages/cli_app_entry_missing.js
994
982
  /** @typedef {import('../runtime.js').LocalizedString} LocalizedString */
995
- /** @typedef {{}} Cli_CancelledInputs */
996
- const ko_cli_cancelled = () => {
997
- return `취소했습니다`;
983
+ /** @typedef {{ entry: NonNullable<unknown> }} Cli_App_Entry_MissingInputs */
984
+ const ko_cli_app_entry_missing = (i) => {
985
+ return `서버 진입 파일(${i?.entry})이 없습니다`;
998
986
  };
999
987
  /**
1000
988
 
1001
- * @param {Cli_CancelledInputs} inputs
989
+ * @param {Cli_App_Entry_MissingInputs} inputs
1002
990
  * @param {{ locale?: "ko" }} options
1003
991
  * @returns {LocalizedString}
1004
992
  */
1005
- const cli_cancelled = ((inputs = {}, options = {}) => {
993
+ const cli_app_entry_missing = ((inputs, options = {}) => {
1006
994
  experimentalStaticLocale ?? options.locale ?? getLocale();
1007
- return ko_cli_cancelled(inputs);
995
+ return ko_cli_app_entry_missing(inputs);
1008
996
  });
1009
997
 
1010
998
  //#endregion
1011
- //#region ../i18n/src/paraglide/messages/cli_check_problem.js
999
+ //#region ../i18n/src/paraglide/messages/cli_app_handle_invalid.js
1012
1000
  /** @typedef {import('../runtime.js').LocalizedString} LocalizedString */
1013
- /** @typedef {{ problem: NonNullable<unknown> }} Cli_Check_ProblemInputs */
1014
- const ko_cli_check_problem = (i) => {
1015
- return `문제 ${i?.problem}`;
1001
+ /** @typedef {{}} Cli_App_Handle_InvalidInputs */
1002
+ const ko_cli_app_handle_invalid = () => {
1003
+ return `handle은 소문자·숫자·하이픈 3~40자입니다. 예: npx sayren app init order-mail`;
1016
1004
  };
1017
1005
  /**
1018
1006
 
1019
- * @param {Cli_Check_ProblemInputs} inputs
1007
+ * @param {Cli_App_Handle_InvalidInputs} inputs
1020
1008
  * @param {{ locale?: "ko" }} options
1021
1009
  * @returns {LocalizedString}
1022
1010
  */
1023
- const cli_check_problem = ((inputs, options = {}) => {
1011
+ const cli_app_handle_invalid = ((inputs = {}, options = {}) => {
1024
1012
  experimentalStaticLocale ?? options.locale ?? getLocale();
1025
- return ko_cli_check_problem(inputs);
1013
+ return ko_cli_app_handle_invalid(inputs);
1026
1014
  });
1027
1015
 
1028
1016
  //#endregion
1029
- //#region ../i18n/src/paraglide/messages/cli_check_warning.js
1017
+ //#region ../i18n/src/paraglide/messages/cli_app_handle_mismatch.js
1030
1018
  /** @typedef {import('../runtime.js').LocalizedString} LocalizedString */
1031
- /** @typedef {{ warning: NonNullable<unknown> }} Cli_Check_WarningInputs */
1032
- const ko_cli_check_warning = (i) => {
1033
- return `경고 ${i?.warning}`;
1019
+ /** @typedef {{ manifest: NonNullable<unknown>, registered: NonNullable<unknown> }} Cli_App_Handle_MismatchInputs */
1020
+ const ko_cli_app_handle_mismatch = (i) => {
1021
+ return `매니페스트 handle(${i?.manifest})이 등록된 앱(${i?.registered})과 다릅니다`;
1034
1022
  };
1035
1023
  /**
1036
1024
 
1037
- * @param {Cli_Check_WarningInputs} inputs
1025
+ * @param {Cli_App_Handle_MismatchInputs} inputs
1038
1026
  * @param {{ locale?: "ko" }} options
1039
1027
  * @returns {LocalizedString}
1040
1028
  */
1041
- const cli_check_warning = ((inputs, options = {}) => {
1029
+ const cli_app_handle_mismatch = ((inputs, options = {}) => {
1042
1030
  experimentalStaticLocale ?? options.locale ?? getLocale();
1043
- return ko_cli_check_warning(inputs);
1031
+ return ko_cli_app_handle_mismatch(inputs);
1044
1032
  });
1045
1033
 
1046
1034
  //#endregion
1047
- //#region ../i18n/src/paraglide/messages/cli_checks_lock_drift.js
1035
+ //#region ../i18n/src/paraglide/messages/cli_app_handler_missing.js
1048
1036
  /** @typedef {import('../runtime.js').LocalizedString} LocalizedString */
1049
- /** @typedef {{ names: NonNullable<unknown> }} Cli_Checks_Lock_DriftInputs */
1050
- const ko_cli_checks_lock_drift = (i) => {
1051
- return `package.json의 의존성이 pnpm-lock.yaml과 다릅니다(${i?.names}). 호스팅 빌드는 pnpm-lock.yaml대로 설치하므로 pnpm install로 잠금 파일을 갱신하십시오`;
1037
+ /** @typedef {{ events: NonNullable<unknown> }} Cli_App_Handler_MissingInputs */
1038
+ const ko_cli_app_handler_missing = (i) => {
1039
+ return `매니페스트 events에 있지만 이벤트 함수가 없습니다: ${i?.events} (HANDLER_MISSING)`;
1052
1040
  };
1053
1041
  /**
1054
1042
 
1055
- * @param {Cli_Checks_Lock_DriftInputs} inputs
1043
+ * @param {Cli_App_Handler_MissingInputs} inputs
1056
1044
  * @param {{ locale?: "ko" }} options
1057
1045
  * @returns {LocalizedString}
1058
1046
  */
1059
- const cli_checks_lock_drift = ((inputs, options = {}) => {
1047
+ const cli_app_handler_missing = ((inputs, options = {}) => {
1060
1048
  experimentalStaticLocale ?? options.locale ?? getLocale();
1061
- return ko_cli_checks_lock_drift(inputs);
1049
+ return ko_cli_app_handler_missing(inputs);
1062
1050
  });
1063
1051
 
1064
1052
  //#endregion
1065
- //#region ../i18n/src/paraglide/messages/cli_checks_lock_missing.js
1053
+ //#region ../i18n/src/paraglide/messages/cli_app_handler_unlisted.js
1066
1054
  /** @typedef {import('../runtime.js').LocalizedString} LocalizedString */
1067
- /** @typedef {{}} Cli_Checks_Lock_MissingInputs */
1068
- const ko_cli_checks_lock_missing = () => {
1069
- return `pnpm-lock.yaml이 없습니다. 호스팅 빌드의 설치가 실패할 수 있습니다`;
1055
+ /** @typedef {{ events: NonNullable<unknown> }} Cli_App_Handler_UnlistedInputs */
1056
+ const ko_cli_app_handler_unlisted = (i) => {
1057
+ return `이벤트 함수는 있지만 매니페스트 events에 없어 호출되지 않습니다: ${i?.events}`;
1070
1058
  };
1071
1059
  /**
1072
1060
 
1073
- * @param {Cli_Checks_Lock_MissingInputs} inputs
1061
+ * @param {Cli_App_Handler_UnlistedInputs} inputs
1074
1062
  * @param {{ locale?: "ko" }} options
1075
1063
  * @returns {LocalizedString}
1076
1064
  */
1077
- const cli_checks_lock_missing = ((inputs = {}, options = {}) => {
1065
+ const cli_app_handler_unlisted = ((inputs, options = {}) => {
1078
1066
  experimentalStaticLocale ?? options.locale ?? getLocale();
1079
- return ko_cli_checks_lock_missing(inputs);
1067
+ return ko_cli_app_handler_unlisted(inputs);
1080
1068
  });
1081
1069
 
1082
1070
  //#endregion
1083
- //#region ../i18n/src/paraglide/messages/cli_checks_summary.js
1071
+ //#region ../i18n/src/paraglide/messages/cli_app_init_done.js
1084
1072
  /** @typedef {import('../runtime.js').LocalizedString} LocalizedString */
1085
- /** @typedef {{ files: NonNullable<unknown>, size: NonNullable<unknown>, passed: NonNullable<unknown>, rules: NonNullable<unknown> }} Cli_Checks_SummaryInputs */
1086
- const ko_cli_checks_summary = (i) => {
1087
- return `로컬 검사 — 파일 ${i?.files}개(${i?.size}), 규칙 ${i?.passed}/${i?.rules} 통과`;
1073
+ /** @typedef {{ dir: NonNullable<unknown>, handle: NonNullable<unknown>, appId: NonNullable<unknown> }} Cli_App_Init_DoneInputs */
1074
+ const ko_cli_app_init_done = (i) => {
1075
+ return `앱을 만들었습니다: ${i?.dir} (${i?.handle}, ${i?.appId})
1076
+
1077
+ cd ${i?.dir}
1078
+ npm install
1079
+ npx sayren app dev --store <storeId>
1080
+ npx sayren app deploy -m "첫 버전"`;
1088
1081
  };
1089
1082
  /**
1090
1083
 
1091
- * @param {Cli_Checks_SummaryInputs} inputs
1084
+ * @param {Cli_App_Init_DoneInputs} inputs
1092
1085
  * @param {{ locale?: "ko" }} options
1093
1086
  * @returns {LocalizedString}
1094
1087
  */
1095
- const cli_checks_summary = ((inputs, options = {}) => {
1088
+ const cli_app_init_done = ((inputs, options = {}) => {
1096
1089
  experimentalStaticLocale ?? options.locale ?? getLocale();
1097
- return ko_cli_checks_summary(inputs);
1090
+ return ko_cli_app_init_done(inputs);
1098
1091
  });
1099
1092
 
1100
1093
  //#endregion
1101
- //#region ../i18n/src/paraglide/messages/cli_continue_confirm.js
1094
+ //#region ../i18n/src/paraglide/messages/cli_app_key_invalid.js
1102
1095
  /** @typedef {import('../runtime.js').LocalizedString} LocalizedString */
1103
- /** @typedef {{}} Cli_Continue_ConfirmInputs */
1104
- const ko_cli_continue_confirm = () => {
1105
- return `계속하시겠습니까?`;
1096
+ /** @typedef {{}} Cli_App_Key_InvalidInputs */
1097
+ const ko_cli_app_key_invalid = () => {
1098
+ return `앱 배포 키 형식이 아닙니다(sak_…). developer.sayren.app에서 발행한 키를 쓰십시오`;
1106
1099
  };
1107
1100
  /**
1108
1101
 
1109
- * @param {Cli_Continue_ConfirmInputs} inputs
1102
+ * @param {Cli_App_Key_InvalidInputs} inputs
1110
1103
  * @param {{ locale?: "ko" }} options
1111
1104
  * @returns {LocalizedString}
1112
1105
  */
1113
- const cli_continue_confirm = ((inputs = {}, options = {}) => {
1106
+ const cli_app_key_invalid = ((inputs = {}, options = {}) => {
1114
1107
  experimentalStaticLocale ?? options.locale ?? getLocale();
1115
- return ko_cli_continue_confirm(inputs);
1108
+ return ko_cli_app_key_invalid(inputs);
1116
1109
  });
1117
1110
 
1118
1111
  //#endregion
1119
- //#region ../i18n/src/paraglide/messages/cli_credentials_git_tracked.js
1112
+ //#region ../i18n/src/paraglide/messages/cli_app_logs_empty.js
1120
1113
  /** @typedef {import('../runtime.js').LocalizedString} LocalizedString */
1121
- /** @typedef {{ path: NonNullable<unknown> }} Cli_Credentials_Git_TrackedInputs */
1122
- const ko_cli_credentials_git_tracked = (i) => {
1123
- return `${i?.path}가 git에 커밋돼 있어 토큰을 쓰지 않았습니다. 추적을 해제하거나 XDG_CONFIG_HOME으로 다른 폴더를 지정하십시오`;
1114
+ /** @typedef {{}} Cli_App_Logs_EmptyInputs */
1115
+ const ko_cli_app_logs_empty = () => {
1116
+ return `실행 기록이 없습니다`;
1124
1117
  };
1125
1118
  /**
1126
1119
 
1127
- * @param {Cli_Credentials_Git_TrackedInputs} inputs
1120
+ * @param {Cli_App_Logs_EmptyInputs} inputs
1128
1121
  * @param {{ locale?: "ko" }} options
1129
1122
  * @returns {LocalizedString}
1130
1123
  */
1131
- const cli_credentials_git_tracked = ((inputs, options = {}) => {
1124
+ const cli_app_logs_empty = ((inputs = {}, options = {}) => {
1132
1125
  experimentalStaticLocale ?? options.locale ?? getLocale();
1133
- return ko_cli_credentials_git_tracked(inputs);
1126
+ return ko_cli_app_logs_empty(inputs);
1134
1127
  });
1135
1128
 
1136
1129
  //#endregion
1137
- //#region ../i18n/src/paraglide/messages/cli_credentials_lock_busy.js
1130
+ //#region ../i18n/src/paraglide/messages/cli_app_manifest_invalid.js
1138
1131
  /** @typedef {import('../runtime.js').LocalizedString} LocalizedString */
1139
- /** @typedef {{ lock: NonNullable<unknown> }} Cli_Credentials_Lock_BusyInputs */
1140
- const ko_cli_credentials_lock_busy = (i) => {
1141
- return `다른 sayren 명령이 로그인을 갱신하고 있습니다. 잠시 뒤 다시 시도하십시오(${i?.lock})`;
1132
+ /** @typedef {{ problems: NonNullable<unknown> }} Cli_App_Manifest_InvalidInputs */
1133
+ const ko_cli_app_manifest_invalid = (i) => {
1134
+ return `매니페스트가 올바르지 않습니다:
1135
+ ${i?.problems}`;
1142
1136
  };
1143
1137
  /**
1144
1138
 
1145
- * @param {Cli_Credentials_Lock_BusyInputs} inputs
1139
+ * @param {Cli_App_Manifest_InvalidInputs} inputs
1146
1140
  * @param {{ locale?: "ko" }} options
1147
1141
  * @returns {LocalizedString}
1148
1142
  */
1149
- const cli_credentials_lock_busy = ((inputs, options = {}) => {
1143
+ const cli_app_manifest_invalid = ((inputs, options = {}) => {
1150
1144
  experimentalStaticLocale ?? options.locale ?? getLocale();
1151
- return ko_cli_credentials_lock_busy(inputs);
1145
+ return ko_cli_app_manifest_invalid(inputs);
1152
1146
  });
1153
1147
 
1154
1148
  //#endregion
1155
- //#region ../i18n/src/paraglide/messages/cli_credentials_no_config_dir.js
1149
+ //#region ../i18n/src/paraglide/messages/cli_app_manifest_missing.js
1156
1150
  /** @typedef {import('../runtime.js').LocalizedString} LocalizedString */
1157
- /** @typedef {{}} Cli_Credentials_No_Config_DirInputs */
1158
- const ko_cli_credentials_no_config_dir = () => {
1159
- return `자격 증명을 저장할 폴더를 정하지 못했습니다(HOME·XDG_CONFIG_HOME 없음). SAYREN_TOKEN 환경 변수로 토큰을 주십시오`;
1151
+ /** @typedef {{ file: NonNullable<unknown> }} Cli_App_Manifest_MissingInputs */
1152
+ const ko_cli_app_manifest_missing = (i) => {
1153
+ return `${i?.file}이 없습니다. 앱 폴더에서 실행하거나 --dir을 주십시오`;
1160
1154
  };
1161
1155
  /**
1162
1156
 
1163
- * @param {Cli_Credentials_No_Config_DirInputs} inputs
1157
+ * @param {Cli_App_Manifest_MissingInputs} inputs
1164
1158
  * @param {{ locale?: "ko" }} options
1165
1159
  * @returns {LocalizedString}
1166
1160
  */
1167
- const cli_credentials_no_config_dir = ((inputs = {}, options = {}) => {
1161
+ const cli_app_manifest_missing = ((inputs, options = {}) => {
1168
1162
  experimentalStaticLocale ?? options.locale ?? getLocale();
1169
- return ko_cli_credentials_no_config_dir(inputs);
1163
+ return ko_cli_app_manifest_missing(inputs);
1170
1164
  });
1171
1165
 
1172
1166
  //#endregion
1173
- //#region ../i18n/src/paraglide/messages/cli_credentials_symlink.js
1167
+ //#region ../i18n/src/paraglide/messages/cli_app_not_registered.js
1174
1168
  /** @typedef {import('../runtime.js').LocalizedString} LocalizedString */
1175
- /** @typedef {{ path: NonNullable<unknown> }} Cli_Credentials_SymlinkInputs */
1176
- const ko_cli_credentials_symlink = (i) => {
1177
- return `${i?.path}가 심볼릭 링크라 읽지 않았습니다. 링크를 지운 뒤 다시 로그인하십시오`;
1169
+ /** @typedef {{ file: NonNullable<unknown> }} Cli_App_Not_RegisteredInputs */
1170
+ const ko_cli_app_not_registered = (i) => {
1171
+ return `등록된 앱이 아닙니다(${i?.file}은 있지만 .sayren/app.json이 없습니다). npx sayren app init <handle>로 만든 폴더에서 실행하십시오`;
1178
1172
  };
1179
1173
  /**
1180
1174
 
1181
- * @param {Cli_Credentials_SymlinkInputs} inputs
1175
+ * @param {Cli_App_Not_RegisteredInputs} inputs
1182
1176
  * @param {{ locale?: "ko" }} options
1183
1177
  * @returns {LocalizedString}
1184
1178
  */
1185
- const cli_credentials_symlink = ((inputs, options = {}) => {
1179
+ const cli_app_not_registered = ((inputs, options = {}) => {
1186
1180
  experimentalStaticLocale ?? options.locale ?? getLocale();
1187
- return ko_cli_credentials_symlink(inputs);
1181
+ return ko_cli_app_not_registered(inputs);
1188
1182
  });
1189
1183
 
1190
1184
  //#endregion
1191
- //#region ../i18n/src/paraglide/messages/cli_credentials_unreadable.js
1185
+ //#region ../i18n/src/paraglide/messages/cli_app_port_invalid.js
1192
1186
  /** @typedef {import('../runtime.js').LocalizedString} LocalizedString */
1193
- /** @typedef {{ path: NonNullable<unknown> }} Cli_Credentials_UnreadableInputs */
1194
- const ko_cli_credentials_unreadable = (i) => {
1195
- return `${i?.path}를 읽지 못했습니다. 파일을 지우고 다시 로그인하십시오`;
1187
+ /** @typedef {{ value: NonNullable<unknown> }} Cli_App_Port_InvalidInputs */
1188
+ const ko_cli_app_port_invalid = (i) => {
1189
+ return `--port가 올바르지 않습니다: ${i?.value}`;
1196
1190
  };
1197
1191
  /**
1198
1192
 
1199
- * @param {Cli_Credentials_UnreadableInputs} inputs
1193
+ * @param {Cli_App_Port_InvalidInputs} inputs
1200
1194
  * @param {{ locale?: "ko" }} options
1201
1195
  * @returns {LocalizedString}
1202
1196
  */
1203
- const cli_credentials_unreadable = ((inputs, options = {}) => {
1197
+ const cli_app_port_invalid = ((inputs, options = {}) => {
1204
1198
  experimentalStaticLocale ?? options.locale ?? getLocale();
1205
- return ko_cli_credentials_unreadable(inputs);
1199
+ return ko_cli_app_port_invalid(inputs);
1206
1200
  });
1207
1201
 
1208
1202
  //#endregion
1209
- //#region ../i18n/src/paraglide/messages/cli_dependency_check_unavailable.js
1203
+ //#region ../i18n/src/paraglide/messages/cli_app_release_done.js
1210
1204
  /** @typedef {import('../runtime.js').LocalizedString} LocalizedString */
1211
- /** @typedef {{}} Cli_Dependency_Check_UnavailableInputs */
1212
- const ko_cli_dependency_check_unavailable = () => {
1213
- return `의존성 확인을 지금 할 수 없습니다. 잠시 뒤 다시 시도하십시오`;
1205
+ /** @typedef {{ number: NonNullable<unknown>, applied: NonNullable<unknown>, pending: NonNullable<unknown> }} Cli_App_Release_DoneInputs */
1206
+ const ko_cli_app_release_done = (i) => {
1207
+ return `버전 ${i?.number}이 현재 버전입니다 — 곧바로 적용 ${i?.applied}, 재동의 대기 ${i?.pending}`;
1214
1208
  };
1215
1209
  /**
1216
1210
 
1217
- * @param {Cli_Dependency_Check_UnavailableInputs} inputs
1211
+ * @param {Cli_App_Release_DoneInputs} inputs
1218
1212
  * @param {{ locale?: "ko" }} options
1219
1213
  * @returns {LocalizedString}
1220
1214
  */
1221
- const cli_dependency_check_unavailable = ((inputs = {}, options = {}) => {
1215
+ const cli_app_release_done = ((inputs, options = {}) => {
1222
1216
  experimentalStaticLocale ?? options.locale ?? getLocale();
1223
- return ko_cli_dependency_check_unavailable(inputs);
1217
+ return ko_cli_app_release_done(inputs);
1224
1218
  });
1225
1219
 
1226
1220
  //#endregion
1227
- //#region ../i18n/src/paraglide/messages/cli_dependency_rejected.js
1221
+ //#region ../i18n/src/paraglide/messages/cli_app_secret_deleted.js
1228
1222
  /** @typedef {import('../runtime.js').LocalizedString} LocalizedString */
1229
- /** @typedef {{ items: NonNullable<unknown> }} Cli_Dependency_RejectedInputs */
1230
- const ko_cli_dependency_rejected = (i) => {
1231
- return `쓸 수 없는 npm 의존성이 있어 올리지 않았습니다.
1232
- ${i?.items}`;
1223
+ /** @typedef {{ name: NonNullable<unknown> }} Cli_App_Secret_DeletedInputs */
1224
+ const ko_cli_app_secret_deleted = (i) => {
1225
+ return `비밀 값 ${i?.name}을 지웠습니다`;
1233
1226
  };
1234
1227
  /**
1235
1228
 
1236
- * @param {Cli_Dependency_RejectedInputs} inputs
1229
+ * @param {Cli_App_Secret_DeletedInputs} inputs
1237
1230
  * @param {{ locale?: "ko" }} options
1238
1231
  * @returns {LocalizedString}
1239
1232
  */
1240
- const cli_dependency_rejected = ((inputs, options = {}) => {
1233
+ const cli_app_secret_deleted = ((inputs, options = {}) => {
1241
1234
  experimentalStaticLocale ?? options.locale ?? getLocale();
1242
- return ko_cli_dependency_rejected(inputs);
1235
+ return ko_cli_app_secret_deleted(inputs);
1243
1236
  });
1244
1237
 
1245
1238
  //#endregion
1246
- //#region ../i18n/src/paraglide/messages/cli_dependency_warning.js
1239
+ //#region ../i18n/src/paraglide/messages/cli_app_secret_empty.js
1247
1240
  /** @typedef {import('../runtime.js').LocalizedString} LocalizedString */
1248
- /** @typedef {{ finding: NonNullable<unknown> }} Cli_Dependency_WarningInputs */
1249
- const ko_cli_dependency_warning = (i) => {
1250
- return `의존성 경고 ${i?.finding}`;
1241
+ /** @typedef {{}} Cli_App_Secret_EmptyInputs */
1242
+ const ko_cli_app_secret_empty = () => {
1243
+ return `비밀 값이 없습니다`;
1251
1244
  };
1252
1245
  /**
1253
1246
 
1254
- * @param {Cli_Dependency_WarningInputs} inputs
1247
+ * @param {Cli_App_Secret_EmptyInputs} inputs
1255
1248
  * @param {{ locale?: "ko" }} options
1256
1249
  * @returns {LocalizedString}
1257
1250
  */
1258
- const cli_dependency_warning = ((inputs, options = {}) => {
1251
+ const cli_app_secret_empty = ((inputs = {}, options = {}) => {
1259
1252
  experimentalStaticLocale ?? options.locale ?? getLocale();
1260
- return ko_cli_dependency_warning(inputs);
1253
+ return ko_cli_app_secret_empty(inputs);
1261
1254
  });
1262
1255
 
1263
1256
  //#endregion
1264
- //#region ../i18n/src/paraglide/messages/cli_deploy_build_in_progress.js
1257
+ //#region ../i18n/src/paraglide/messages/cli_app_secret_in_source.js
1265
1258
  /** @typedef {import('../runtime.js').LocalizedString} LocalizedString */
1266
- /** @typedef {{}} Cli_Deploy_Build_In_ProgressInputs */
1267
- const ko_cli_deploy_build_in_progress = () => {
1268
- return `이 사이트에 끝나지 않은 빌드가 있습니다(상점 플랫폼·AI 또는 다른 배포). 작업 트리는 올렸습니다 — npx sayren status로 확인한 뒤 다시 배포하십시오`;
1259
+ /** @typedef {{}} Cli_App_Secret_In_SourceInputs */
1260
+ const ko_cli_app_secret_in_source = () => {
1261
+ return `번들에 액세스 토큰·PG 키·개인 키·앱 배포 키 모양의 값이 들어 있습니다. 비밀 값은 npx sayren app secret put <이름>으로 넣으십시오 (SECRET_IN_SOURCE)`;
1269
1262
  };
1270
1263
  /**
1271
1264
 
1272
- * @param {Cli_Deploy_Build_In_ProgressInputs} inputs
1265
+ * @param {Cli_App_Secret_In_SourceInputs} inputs
1273
1266
  * @param {{ locale?: "ko" }} options
1274
1267
  * @returns {LocalizedString}
1275
1268
  */
1276
- const cli_deploy_build_in_progress = ((inputs = {}, options = {}) => {
1269
+ const cli_app_secret_in_source = ((inputs = {}, options = {}) => {
1277
1270
  experimentalStaticLocale ?? options.locale ?? getLocale();
1278
- return ko_cli_deploy_build_in_progress(inputs);
1271
+ return ko_cli_app_secret_in_source(inputs);
1279
1272
  });
1280
1273
 
1281
1274
  //#endregion
1282
- //#region ../i18n/src/paraglide/messages/cli_deploy_build_started.js
1275
+ //#region ../i18n/src/paraglide/messages/cli_app_secret_name_required.js
1283
1276
  /** @typedef {import('../runtime.js').LocalizedString} LocalizedString */
1284
- /** @typedef {{ version: NonNullable<unknown> }} Cli_Deploy_Build_StartedInputs */
1285
- const ko_cli_deploy_build_started = (i) => {
1286
- return `버전 v${i?.version} 빌드 시작`;
1277
+ /** @typedef {{}} Cli_App_Secret_Name_RequiredInputs */
1278
+ const ko_cli_app_secret_name_required = () => {
1279
+ return `비밀 값 이름이 필요합니다. 예: npx sayren app secret put RESEND_API_KEY`;
1287
1280
  };
1288
1281
  /**
1289
1282
 
1290
- * @param {Cli_Deploy_Build_StartedInputs} inputs
1283
+ * @param {Cli_App_Secret_Name_RequiredInputs} inputs
1291
1284
  * @param {{ locale?: "ko" }} options
1292
1285
  * @returns {LocalizedString}
1293
1286
  */
1294
- const cli_deploy_build_started = ((inputs, options = {}) => {
1287
+ const cli_app_secret_name_required = ((inputs = {}, options = {}) => {
1295
1288
  experimentalStaticLocale ?? options.locale ?? getLocale();
1296
- return ko_cli_deploy_build_started(inputs);
1289
+ return ko_cli_app_secret_name_required(inputs);
1297
1290
  });
1298
1291
 
1299
1292
  //#endregion
1300
- //#region ../i18n/src/paraglide/messages/cli_deploy_build_succeeded.js
1293
+ //#region ../i18n/src/paraglide/messages/cli_app_secret_saved.js
1301
1294
  /** @typedef {import('../runtime.js').LocalizedString} LocalizedString */
1302
- /** @typedef {{ version: NonNullable<unknown> }} Cli_Deploy_Build_SucceededInputs */
1303
- const ko_cli_deploy_build_succeeded = (i) => {
1304
- return `빌드 성공 — v${i?.version}`;
1295
+ /** @typedef {{ name: NonNullable<unknown> }} Cli_App_Secret_SavedInputs */
1296
+ const ko_cli_app_secret_saved = (i) => {
1297
+ return `비밀 값 ${i?.name}을 저장했습니다`;
1305
1298
  };
1306
1299
  /**
1307
1300
 
1308
- * @param {Cli_Deploy_Build_SucceededInputs} inputs
1301
+ * @param {Cli_App_Secret_SavedInputs} inputs
1309
1302
  * @param {{ locale?: "ko" }} options
1310
1303
  * @returns {LocalizedString}
1311
1304
  */
1312
- const cli_deploy_build_succeeded = ((inputs, options = {}) => {
1305
+ const cli_app_secret_saved = ((inputs, options = {}) => {
1313
1306
  experimentalStaticLocale ?? options.locale ?? getLocale();
1314
- return ko_cli_deploy_build_succeeded(inputs);
1307
+ return ko_cli_app_secret_saved(inputs);
1315
1308
  });
1316
1309
 
1317
1310
  //#endregion
1318
- //#region ../i18n/src/paraglide/messages/cli_deploy_build_succeeded_duration.js
1311
+ //#region ../i18n/src/paraglide/messages/cli_app_secret_value_required.js
1319
1312
  /** @typedef {import('../runtime.js').LocalizedString} LocalizedString */
1320
- /** @typedef {{ version: NonNullable<unknown>, seconds: NonNullable<unknown> }} Cli_Deploy_Build_Succeeded_DurationInputs */
1321
- const ko_cli_deploy_build_succeeded_duration = (i) => {
1322
- return `빌드 성공 — v${i?.version} (${i?.seconds}초)`;
1313
+ /** @typedef {{ name: NonNullable<unknown> }} Cli_App_Secret_Value_RequiredInputs */
1314
+ const ko_cli_app_secret_value_required = (i) => {
1315
+ return `값을 표준 입력으로 주십시오. 예: printf '%s' "$VALUE" | npx sayren app secret put ${i?.name}`;
1323
1316
  };
1324
1317
  /**
1325
1318
 
1326
- * @param {Cli_Deploy_Build_Succeeded_DurationInputs} inputs
1319
+ * @param {Cli_App_Secret_Value_RequiredInputs} inputs
1327
1320
  * @param {{ locale?: "ko" }} options
1328
1321
  * @returns {LocalizedString}
1329
1322
  */
1330
- const cli_deploy_build_succeeded_duration = ((inputs, options = {}) => {
1323
+ const cli_app_secret_value_required = ((inputs, options = {}) => {
1331
1324
  experimentalStaticLocale ?? options.locale ?? getLocale();
1332
- return ko_cli_deploy_build_succeeded_duration(inputs);
1325
+ return ko_cli_app_secret_value_required(inputs);
1333
1326
  });
1334
1327
 
1335
1328
  //#endregion
1336
- //#region ../i18n/src/paraglide/messages/cli_deploy_checks_failed.js
1329
+ //#region ../i18n/src/paraglide/messages/cli_app_since_invalid.js
1337
1330
  /** @typedef {import('../runtime.js').LocalizedString} LocalizedString */
1338
- /** @typedef {{}} Cli_Deploy_Checks_FailedInputs */
1339
- const ko_cli_deploy_checks_failed = () => {
1340
- return `로컬 검사를 통과하지 못해 배포하지 않았습니다. 위 항목을 고친 뒤 다시 시도하십시오`;
1331
+ /** @typedef {{ value: NonNullable<unknown> }} Cli_App_Since_InvalidInputs */
1332
+ const ko_cli_app_since_invalid = (i) => {
1333
+ return `--since 형식이 아닙니다: ${i?.value} (예: 30m, 1h, 2d)`;
1341
1334
  };
1342
1335
  /**
1343
1336
 
1344
- * @param {Cli_Deploy_Checks_FailedInputs} inputs
1337
+ * @param {Cli_App_Since_InvalidInputs} inputs
1345
1338
  * @param {{ locale?: "ko" }} options
1346
1339
  * @returns {LocalizedString}
1347
1340
  */
1348
- const cli_deploy_checks_failed = ((inputs = {}, options = {}) => {
1341
+ const cli_app_since_invalid = ((inputs, options = {}) => {
1349
1342
  experimentalStaticLocale ?? options.locale ?? getLocale();
1350
- return ko_cli_deploy_checks_failed(inputs);
1343
+ return ko_cli_app_since_invalid(inputs);
1351
1344
  });
1352
1345
 
1353
1346
  //#endregion
1354
- //#region ../i18n/src/paraglide/messages/cli_deploy_force_confirm.js
1347
+ //#region ../i18n/src/paraglide/messages/cli_app_state_invalid.js
1355
1348
  /** @typedef {import('../runtime.js').LocalizedString} LocalizedString */
1356
- /** @typedef {{}} Cli_Deploy_Force_ConfirmInputs */
1357
- const ko_cli_deploy_force_confirm = () => {
1358
- return `원격 작업 트리(상점 플랫폼·AI 편집 포함)를 이 폴더 내용으로 덮어쓰고, 열린 편집 환경을 끕니다. 계속하시겠습니까?`;
1349
+ /** @typedef {{ file: NonNullable<unknown> }} Cli_App_State_InvalidInputs */
1350
+ const ko_cli_app_state_invalid = (i) => {
1351
+ return `${i?.file}을 읽을 수 없습니다. 파일을 지우고 npx sayren app init을 다시 실행하십시오`;
1359
1352
  };
1360
1353
  /**
1361
1354
 
1362
- * @param {Cli_Deploy_Force_ConfirmInputs} inputs
1355
+ * @param {Cli_App_State_InvalidInputs} inputs
1363
1356
  * @param {{ locale?: "ko" }} options
1364
1357
  * @returns {LocalizedString}
1365
1358
  */
1366
- const cli_deploy_force_confirm = ((inputs = {}, options = {}) => {
1359
+ const cli_app_state_invalid = ((inputs, options = {}) => {
1367
1360
  experimentalStaticLocale ?? options.locale ?? getLocale();
1368
- return ko_cli_deploy_force_confirm(inputs);
1361
+ return ko_cli_app_state_invalid(inputs);
1362
+ });
1363
+
1364
+ //#endregion
1365
+ //#region ../i18n/src/paraglide/messages/cli_app_status.js
1366
+ /** @typedef {import('../runtime.js').LocalizedString} LocalizedString */
1367
+ /** @typedef {{ name: NonNullable<unknown>, handle: NonNullable<unknown>, appId: NonNullable<unknown>, status: NonNullable<unknown>, current: NonNullable<unknown>, active: NonNullable<unknown>, pending: NonNullable<unknown> }} Cli_App_StatusInputs */
1368
+ const ko_cli_app_status = (i) => {
1369
+ return `${i?.name} (${i?.handle}, ${i?.appId})
1370
+ 상태 ${i?.status} · 현재 버전 ${i?.current} · 설치 ${i?.active} · 재동의 대기 ${i?.pending}
1371
+ 최근 버전:`;
1372
+ };
1373
+ /**
1374
+
1375
+ * @param {Cli_App_StatusInputs} inputs
1376
+ * @param {{ locale?: "ko" }} options
1377
+ * @returns {LocalizedString}
1378
+ */
1379
+ const cli_app_status = ((inputs, options = {}) => {
1380
+ experimentalStaticLocale ?? options.locale ?? getLocale();
1381
+ return ko_cli_app_status(inputs);
1382
+ });
1383
+
1384
+ //#endregion
1385
+ //#region ../i18n/src/paraglide/messages/cli_app_subcommand_unknown.js
1386
+ /** @typedef {import('../runtime.js').LocalizedString} LocalizedString */
1387
+ /** @typedef {{ command: NonNullable<unknown> }} Cli_App_Subcommand_UnknownInputs */
1388
+ const ko_cli_app_subcommand_unknown = (i) => {
1389
+ return `알 수 없는 앱 명령: ${i?.command}
1390
+
1391
+ 사용법: npx sayren app <init|dev|trigger|verify|deploy|release|status|logs|secret|dev-store>`;
1392
+ };
1393
+ /**
1394
+
1395
+ * @param {Cli_App_Subcommand_UnknownInputs} inputs
1396
+ * @param {{ locale?: "ko" }} options
1397
+ * @returns {LocalizedString}
1398
+ */
1399
+ const cli_app_subcommand_unknown = ((inputs, options = {}) => {
1400
+ experimentalStaticLocale ?? options.locale ?? getLocale();
1401
+ return ko_cli_app_subcommand_unknown(inputs);
1402
+ });
1403
+
1404
+ //#endregion
1405
+ //#region ../i18n/src/paraglide/messages/cli_app_trigger_data_invalid.js
1406
+ /** @typedef {import('../runtime.js').LocalizedString} LocalizedString */
1407
+ /** @typedef {{}} Cli_App_Trigger_Data_InvalidInputs */
1408
+ const ko_cli_app_trigger_data_invalid = () => {
1409
+ return `--data가 JSON이 아닙니다`;
1410
+ };
1411
+ /**
1412
+
1413
+ * @param {Cli_App_Trigger_Data_InvalidInputs} inputs
1414
+ * @param {{ locale?: "ko" }} options
1415
+ * @returns {LocalizedString}
1416
+ */
1417
+ const cli_app_trigger_data_invalid = ((inputs = {}, options = {}) => {
1418
+ experimentalStaticLocale ?? options.locale ?? getLocale();
1419
+ return ko_cli_app_trigger_data_invalid(inputs);
1420
+ });
1421
+
1422
+ //#endregion
1423
+ //#region ../i18n/src/paraglide/messages/cli_app_trigger_failed.js
1424
+ /** @typedef {import('../runtime.js').LocalizedString} LocalizedString */
1425
+ /** @typedef {{ status: NonNullable<unknown> }} Cli_App_Trigger_FailedInputs */
1426
+ const ko_cli_app_trigger_failed = (i) => {
1427
+ return `로컬 실행에 보내지 못했습니다(HTTP ${i?.status}). npx sayren app dev가 떠 있는지 확인하십시오`;
1428
+ };
1429
+ /**
1430
+
1431
+ * @param {Cli_App_Trigger_FailedInputs} inputs
1432
+ * @param {{ locale?: "ko" }} options
1433
+ * @returns {LocalizedString}
1434
+ */
1435
+ const cli_app_trigger_failed = ((inputs, options = {}) => {
1436
+ experimentalStaticLocale ?? options.locale ?? getLocale();
1437
+ return ko_cli_app_trigger_failed(inputs);
1438
+ });
1439
+
1440
+ //#endregion
1441
+ //#region ../i18n/src/paraglide/messages/cli_app_trigger_type_required.js
1442
+ /** @typedef {import('../runtime.js').LocalizedString} LocalizedString */
1443
+ /** @typedef {{}} Cli_App_Trigger_Type_RequiredInputs */
1444
+ const ko_cli_app_trigger_type_required = () => {
1445
+ return `이벤트 종류가 필요합니다. 예: npx sayren app trigger ORDER.PAID --order ord_…`;
1446
+ };
1447
+ /**
1448
+
1449
+ * @param {Cli_App_Trigger_Type_RequiredInputs} inputs
1450
+ * @param {{ locale?: "ko" }} options
1451
+ * @returns {LocalizedString}
1452
+ */
1453
+ const cli_app_trigger_type_required = ((inputs = {}, options = {}) => {
1454
+ experimentalStaticLocale ?? options.locale ?? getLocale();
1455
+ return ko_cli_app_trigger_type_required(inputs);
1456
+ });
1457
+
1458
+ //#endregion
1459
+ //#region ../i18n/src/paraglide/messages/cli_app_ui_index_missing.js
1460
+ /** @typedef {import('../runtime.js').LocalizedString} LocalizedString */
1461
+ /** @typedef {{ dir: NonNullable<unknown> }} Cli_App_Ui_Index_MissingInputs */
1462
+ const ko_cli_app_ui_index_missing = (i) => {
1463
+ return `매니페스트에 ui.adminPage가 있지만 ${i?.dir}/index.html이 없습니다`;
1464
+ };
1465
+ /**
1466
+
1467
+ * @param {Cli_App_Ui_Index_MissingInputs} inputs
1468
+ * @param {{ locale?: "ko" }} options
1469
+ * @returns {LocalizedString}
1470
+ */
1471
+ const cli_app_ui_index_missing = ((inputs, options = {}) => {
1472
+ experimentalStaticLocale ?? options.locale ?? getLocale();
1473
+ return ko_cli_app_ui_index_missing(inputs);
1474
+ });
1475
+
1476
+ //#endregion
1477
+ //#region ../i18n/src/paraglide/messages/cli_app_ui_too_large.js
1478
+ /** @typedef {import('../runtime.js').LocalizedString} LocalizedString */
1479
+ /** @typedef {{ limit: NonNullable<unknown> }} Cli_App_Ui_Too_LargeInputs */
1480
+ const ko_cli_app_ui_too_large = (i) => {
1481
+ return `앱 화면 파일이 상한(${i?.limit})을 넘습니다 (ARTIFACT_TOO_LARGE)`;
1482
+ };
1483
+ /**
1484
+
1485
+ * @param {Cli_App_Ui_Too_LargeInputs} inputs
1486
+ * @param {{ locale?: "ko" }} options
1487
+ * @returns {LocalizedString}
1488
+ */
1489
+ const cli_app_ui_too_large = ((inputs, options = {}) => {
1490
+ experimentalStaticLocale ?? options.locale ?? getLocale();
1491
+ return ko_cli_app_ui_too_large(inputs);
1492
+ });
1493
+
1494
+ //#endregion
1495
+ //#region ../i18n/src/paraglide/messages/cli_app_uploading.js
1496
+ /** @typedef {import('../runtime.js').LocalizedString} LocalizedString */
1497
+ /** @typedef {{ size: NonNullable<unknown>, ui: NonNullable<unknown> }} Cli_App_UploadingInputs */
1498
+ const ko_cli_app_uploading = (i) => {
1499
+ return `올리는 중 — 서버 번들 ${i?.size}(gzip), 화면 파일 ${i?.ui}개`;
1500
+ };
1501
+ /**
1502
+
1503
+ * @param {Cli_App_UploadingInputs} inputs
1504
+ * @param {{ locale?: "ko" }} options
1505
+ * @returns {LocalizedString}
1506
+ */
1507
+ const cli_app_uploading = ((inputs, options = {}) => {
1508
+ experimentalStaticLocale ?? options.locale ?? getLocale();
1509
+ return ko_cli_app_uploading(inputs);
1510
+ });
1511
+
1512
+ //#endregion
1513
+ //#region ../i18n/src/paraglide/messages/cli_app_verify_ok.js
1514
+ /** @typedef {import('../runtime.js').LocalizedString} LocalizedString */
1515
+ /** @typedef {{ events: NonNullable<unknown>, http: NonNullable<unknown>, size: NonNullable<unknown>, ui: NonNullable<unknown> }} Cli_App_Verify_OkInputs */
1516
+ const ko_cli_app_verify_ok = (i) => {
1517
+ return `검사 통과 — 이벤트 ${i?.events} · HTTP ${i?.http} · 서버 번들 ${i?.size}(gzip) · 화면 파일 ${i?.ui}개`;
1518
+ };
1519
+ /**
1520
+
1521
+ * @param {Cli_App_Verify_OkInputs} inputs
1522
+ * @param {{ locale?: "ko" }} options
1523
+ * @returns {LocalizedString}
1524
+ */
1525
+ const cli_app_verify_ok = ((inputs, options = {}) => {
1526
+ experimentalStaticLocale ?? options.locale ?? getLocale();
1527
+ return ko_cli_app_verify_ok(inputs);
1528
+ });
1529
+
1530
+ //#endregion
1531
+ //#region ../i18n/src/paraglide/messages/cli_app_version_number_required.js
1532
+ /** @typedef {import('../runtime.js').LocalizedString} LocalizedString */
1533
+ /** @typedef {{}} Cli_App_Version_Number_RequiredInputs */
1534
+ const ko_cli_app_version_number_required = () => {
1535
+ return `버전 번호가 필요합니다. 예: npx sayren app release 1`;
1536
+ };
1537
+ /**
1538
+
1539
+ * @param {Cli_App_Version_Number_RequiredInputs} inputs
1540
+ * @param {{ locale?: "ko" }} options
1541
+ * @returns {LocalizedString}
1542
+ */
1543
+ const cli_app_version_number_required = ((inputs = {}, options = {}) => {
1544
+ experimentalStaticLocale ?? options.locale ?? getLocale();
1545
+ return ko_cli_app_version_number_required(inputs);
1546
+ });
1547
+
1548
+ //#endregion
1549
+ //#region ../i18n/src/paraglide/messages/cli_app_warning.js
1550
+ /** @typedef {import('../runtime.js').LocalizedString} LocalizedString */
1551
+ /** @typedef {{ message: NonNullable<unknown> }} Cli_App_WarningInputs */
1552
+ const ko_cli_app_warning = (i) => {
1553
+ return `경고: ${i?.message}`;
1554
+ };
1555
+ /**
1556
+
1557
+ * @param {Cli_App_WarningInputs} inputs
1558
+ * @param {{ locale?: "ko" }} options
1559
+ * @returns {LocalizedString}
1560
+ */
1561
+ const cli_app_warning = ((inputs, options = {}) => {
1562
+ experimentalStaticLocale ?? options.locale ?? getLocale();
1563
+ return ko_cli_app_warning(inputs);
1564
+ });
1565
+
1566
+ //#endregion
1567
+ //#region ../i18n/src/paraglide/messages/cli_approval_id.js
1568
+ /** @typedef {import('../runtime.js').LocalizedString} LocalizedString */
1569
+ /** @typedef {{ id: NonNullable<unknown> }} Cli_Approval_IdInputs */
1570
+ const ko_cli_approval_id = (i) => {
1571
+ return `승인 요청 id: ${i?.id} (상점 플랫폼 › 설정 › 보안 › 승인 요청)`;
1572
+ };
1573
+ /**
1574
+
1575
+ * @param {Cli_Approval_IdInputs} inputs
1576
+ * @param {{ locale?: "ko" }} options
1577
+ * @returns {LocalizedString}
1578
+ */
1579
+ const cli_approval_id = ((inputs, options = {}) => {
1580
+ experimentalStaticLocale ?? options.locale ?? getLocale();
1581
+ return ko_cli_approval_id(inputs);
1582
+ });
1583
+
1584
+ //#endregion
1585
+ //#region ../i18n/src/paraglide/messages/cli_approval_url.js
1586
+ /** @typedef {import('../runtime.js').LocalizedString} LocalizedString */
1587
+ /** @typedef {{ url: NonNullable<unknown> }} Cli_Approval_UrlInputs */
1588
+ const ko_cli_approval_url = (i) => {
1589
+ return `승인 요청: ${i?.url}`;
1590
+ };
1591
+ /**
1592
+
1593
+ * @param {Cli_Approval_UrlInputs} inputs
1594
+ * @param {{ locale?: "ko" }} options
1595
+ * @returns {LocalizedString}
1596
+ */
1597
+ const cli_approval_url = ((inputs, options = {}) => {
1598
+ experimentalStaticLocale ?? options.locale ?? getLocale();
1599
+ return ko_cli_approval_url(inputs);
1600
+ });
1601
+
1602
+ //#endregion
1603
+ //#region ../i18n/src/paraglide/messages/cli_auth_login_missing.js
1604
+ /** @typedef {import('../runtime.js').LocalizedString} LocalizedString */
1605
+ /** @typedef {{}} Cli_Auth_Login_MissingInputs */
1606
+ const ko_cli_auth_login_missing = () => {
1607
+ return `로그인 정보가 없습니다. npx sayren login으로 다시 로그인하십시오`;
1608
+ };
1609
+ /**
1610
+
1611
+ * @param {Cli_Auth_Login_MissingInputs} inputs
1612
+ * @param {{ locale?: "ko" }} options
1613
+ * @returns {LocalizedString}
1614
+ */
1615
+ const cli_auth_login_missing = ((inputs = {}, options = {}) => {
1616
+ experimentalStaticLocale ?? options.locale ?? getLocale();
1617
+ return ko_cli_auth_login_missing(inputs);
1618
+ });
1619
+
1620
+ //#endregion
1621
+ //#region ../i18n/src/paraglide/messages/cli_blobs_missing.js
1622
+ /** @typedef {import('../runtime.js').LocalizedString} LocalizedString */
1623
+ /** @typedef {{}} Cli_Blobs_MissingInputs */
1624
+ const ko_cli_blobs_missing = () => {
1625
+ return `파일 내용을 올렸지만 서버가 찾지 못했습니다. 잠시 뒤 다시 배포하십시오`;
1626
+ };
1627
+ /**
1628
+
1629
+ * @param {Cli_Blobs_MissingInputs} inputs
1630
+ * @param {{ locale?: "ko" }} options
1631
+ * @returns {LocalizedString}
1632
+ */
1633
+ const cli_blobs_missing = ((inputs = {}, options = {}) => {
1634
+ experimentalStaticLocale ?? options.locale ?? getLocale();
1635
+ return ko_cli_blobs_missing(inputs);
1636
+ });
1637
+
1638
+ //#endregion
1639
+ //#region ../i18n/src/paraglide/messages/cli_blobs_uploaded.js
1640
+ /** @typedef {import('../runtime.js').LocalizedString} LocalizedString */
1641
+ /** @typedef {{ count: NonNullable<unknown> }} Cli_Blobs_UploadedInputs */
1642
+ const ko_cli_blobs_uploaded = (i) => {
1643
+ return `바뀐 파일 ${i?.count}개 올림`;
1644
+ };
1645
+ /**
1646
+
1647
+ * @param {Cli_Blobs_UploadedInputs} inputs
1648
+ * @param {{ locale?: "ko" }} options
1649
+ * @returns {LocalizedString}
1650
+ */
1651
+ const cli_blobs_uploaded = ((inputs, options = {}) => {
1652
+ experimentalStaticLocale ?? options.locale ?? getLocale();
1653
+ return ko_cli_blobs_uploaded(inputs);
1654
+ });
1655
+
1656
+ //#endregion
1657
+ //#region ../i18n/src/paraglide/messages/cli_build_dependencies_blocked.js
1658
+ /** @typedef {import('../runtime.js').LocalizedString} LocalizedString */
1659
+ /** @typedef {{}} Cli_Build_Dependencies_BlockedInputs */
1660
+ const ko_cli_build_dependencies_blocked = () => {
1661
+ return `npm 의존성 검사에서 막혔습니다. 아래 사유의 패키지를 빼거나 바꾼 뒤 다시 배포하십시오`;
1662
+ };
1663
+ /**
1664
+
1665
+ * @param {Cli_Build_Dependencies_BlockedInputs} inputs
1666
+ * @param {{ locale?: "ko" }} options
1667
+ * @returns {LocalizedString}
1668
+ */
1669
+ const cli_build_dependencies_blocked = ((inputs = {}, options = {}) => {
1670
+ experimentalStaticLocale ?? options.locale ?? getLocale();
1671
+ return ko_cli_build_dependencies_blocked(inputs);
1672
+ });
1673
+
1674
+ //#endregion
1675
+ //#region ../i18n/src/paraglide/messages/cli_build_failed.js
1676
+ /** @typedef {import('../runtime.js').LocalizedString} LocalizedString */
1677
+ /** @typedef {{ stage: NonNullable<unknown> }} Cli_Build_FailedInputs */
1678
+ const ko_cli_build_failed = (i) => {
1679
+ return `빌드 실패 — ${i?.stage}`;
1680
+ };
1681
+ /**
1682
+
1683
+ * @param {Cli_Build_FailedInputs} inputs
1684
+ * @param {{ locale?: "ko" }} options
1685
+ * @returns {LocalizedString}
1686
+ */
1687
+ const cli_build_failed = ((inputs, options = {}) => {
1688
+ experimentalStaticLocale ?? options.locale ?? getLocale();
1689
+ return ko_cli_build_failed(inputs);
1690
+ });
1691
+
1692
+ //#endregion
1693
+ //#region ../i18n/src/paraglide/messages/cli_build_failed_code.js
1694
+ /** @typedef {import('../runtime.js').LocalizedString} LocalizedString */
1695
+ /** @typedef {{ stage: NonNullable<unknown>, code: NonNullable<unknown> }} Cli_Build_Failed_CodeInputs */
1696
+ const ko_cli_build_failed_code = (i) => {
1697
+ return `빌드 실패 — ${i?.stage} (${i?.code})`;
1698
+ };
1699
+ /**
1700
+
1701
+ * @param {Cli_Build_Failed_CodeInputs} inputs
1702
+ * @param {{ locale?: "ko" }} options
1703
+ * @returns {LocalizedString}
1704
+ */
1705
+ const cli_build_failed_code = ((inputs, options = {}) => {
1706
+ experimentalStaticLocale ?? options.locale ?? getLocale();
1707
+ return ko_cli_build_failed_code(inputs);
1708
+ });
1709
+
1710
+ //#endregion
1711
+ //#region ../i18n/src/paraglide/messages/cli_build_log_tail.js
1712
+ /** @typedef {import('../runtime.js').LocalizedString} LocalizedString */
1713
+ /** @typedef {{}} Cli_Build_Log_TailInputs */
1714
+ const ko_cli_build_log_tail = () => {
1715
+ return `로그 꼬리:`;
1716
+ };
1717
+ /**
1718
+
1719
+ * @param {Cli_Build_Log_TailInputs} inputs
1720
+ * @param {{ locale?: "ko" }} options
1721
+ * @returns {LocalizedString}
1722
+ */
1723
+ const cli_build_log_tail = ((inputs = {}, options = {}) => {
1724
+ experimentalStaticLocale ?? options.locale ?? getLocale();
1725
+ return ko_cli_build_log_tail(inputs);
1726
+ });
1727
+
1728
+ //#endregion
1729
+ //#region ../i18n/src/paraglide/messages/cli_build_stage.js
1730
+ /** @typedef {import('../runtime.js').LocalizedString} LocalizedString */
1731
+ /** @typedef {{ mark: NonNullable<unknown>, stage: NonNullable<unknown>, seconds: NonNullable<unknown> }} Cli_Build_StageInputs */
1732
+ const ko_cli_build_stage = (i) => {
1733
+ return `${i?.mark} ${i?.stage} ${i?.seconds}초`;
1734
+ };
1735
+ /**
1736
+
1737
+ * @param {Cli_Build_StageInputs} inputs
1738
+ * @param {{ locale?: "ko" }} options
1739
+ * @returns {LocalizedString}
1740
+ */
1741
+ const cli_build_stage = ((inputs, options = {}) => {
1742
+ experimentalStaticLocale ?? options.locale ?? getLocale();
1743
+ return ko_cli_build_stage(inputs);
1744
+ });
1745
+
1746
+ //#endregion
1747
+ //#region ../i18n/src/paraglide/messages/cli_build_stage_unknown.js
1748
+ /** @typedef {import('../runtime.js').LocalizedString} LocalizedString */
1749
+ /** @typedef {{}} Cli_Build_Stage_UnknownInputs */
1750
+ const ko_cli_build_stage_unknown = () => {
1751
+ return `알 수 없는 단계`;
1752
+ };
1753
+ /**
1754
+
1755
+ * @param {Cli_Build_Stage_UnknownInputs} inputs
1756
+ * @param {{ locale?: "ko" }} options
1757
+ * @returns {LocalizedString}
1758
+ */
1759
+ const cli_build_stage_unknown = ((inputs = {}, options = {}) => {
1760
+ experimentalStaticLocale ?? options.locale ?? getLocale();
1761
+ return ko_cli_build_stage_unknown(inputs);
1762
+ });
1763
+
1764
+ //#endregion
1765
+ //#region ../i18n/src/paraglide/messages/cli_build_timeout.js
1766
+ /** @typedef {import('../runtime.js').LocalizedString} LocalizedString */
1767
+ /** @typedef {{ minutes: NonNullable<unknown> }} Cli_Build_TimeoutInputs */
1768
+ const ko_cli_build_timeout = (i) => {
1769
+ return `빌드가 ${i?.minutes}분 안에 끝나지 않았습니다. npx sayren status로 결과를 확인하십시오`;
1770
+ };
1771
+ /**
1772
+
1773
+ * @param {Cli_Build_TimeoutInputs} inputs
1774
+ * @param {{ locale?: "ko" }} options
1775
+ * @returns {LocalizedString}
1776
+ */
1777
+ const cli_build_timeout = ((inputs, options = {}) => {
1778
+ experimentalStaticLocale ?? options.locale ?? getLocale();
1779
+ return ko_cli_build_timeout(inputs);
1780
+ });
1781
+
1782
+ //#endregion
1783
+ //#region ../i18n/src/paraglide/messages/cli_cancelled.js
1784
+ /** @typedef {import('../runtime.js').LocalizedString} LocalizedString */
1785
+ /** @typedef {{}} Cli_CancelledInputs */
1786
+ const ko_cli_cancelled = () => {
1787
+ return `취소했습니다`;
1788
+ };
1789
+ /**
1790
+
1791
+ * @param {Cli_CancelledInputs} inputs
1792
+ * @param {{ locale?: "ko" }} options
1793
+ * @returns {LocalizedString}
1794
+ */
1795
+ const cli_cancelled = ((inputs = {}, options = {}) => {
1796
+ experimentalStaticLocale ?? options.locale ?? getLocale();
1797
+ return ko_cli_cancelled(inputs);
1798
+ });
1799
+
1800
+ //#endregion
1801
+ //#region ../i18n/src/paraglide/messages/cli_check_problem.js
1802
+ /** @typedef {import('../runtime.js').LocalizedString} LocalizedString */
1803
+ /** @typedef {{ problem: NonNullable<unknown> }} Cli_Check_ProblemInputs */
1804
+ const ko_cli_check_problem = (i) => {
1805
+ return `문제 ${i?.problem}`;
1806
+ };
1807
+ /**
1808
+
1809
+ * @param {Cli_Check_ProblemInputs} inputs
1810
+ * @param {{ locale?: "ko" }} options
1811
+ * @returns {LocalizedString}
1812
+ */
1813
+ const cli_check_problem = ((inputs, options = {}) => {
1814
+ experimentalStaticLocale ?? options.locale ?? getLocale();
1815
+ return ko_cli_check_problem(inputs);
1816
+ });
1817
+
1818
+ //#endregion
1819
+ //#region ../i18n/src/paraglide/messages/cli_check_warning.js
1820
+ /** @typedef {import('../runtime.js').LocalizedString} LocalizedString */
1821
+ /** @typedef {{ warning: NonNullable<unknown> }} Cli_Check_WarningInputs */
1822
+ const ko_cli_check_warning = (i) => {
1823
+ return `경고 ${i?.warning}`;
1824
+ };
1825
+ /**
1826
+
1827
+ * @param {Cli_Check_WarningInputs} inputs
1828
+ * @param {{ locale?: "ko" }} options
1829
+ * @returns {LocalizedString}
1830
+ */
1831
+ const cli_check_warning = ((inputs, options = {}) => {
1832
+ experimentalStaticLocale ?? options.locale ?? getLocale();
1833
+ return ko_cli_check_warning(inputs);
1834
+ });
1835
+
1836
+ //#endregion
1837
+ //#region ../i18n/src/paraglide/messages/cli_checks_lock_drift.js
1838
+ /** @typedef {import('../runtime.js').LocalizedString} LocalizedString */
1839
+ /** @typedef {{ names: NonNullable<unknown> }} Cli_Checks_Lock_DriftInputs */
1840
+ const ko_cli_checks_lock_drift = (i) => {
1841
+ return `package.json의 의존성이 pnpm-lock.yaml과 다릅니다(${i?.names}). 호스팅 빌드는 pnpm-lock.yaml대로 설치하므로 pnpm install로 잠금 파일을 갱신하십시오`;
1842
+ };
1843
+ /**
1844
+
1845
+ * @param {Cli_Checks_Lock_DriftInputs} inputs
1846
+ * @param {{ locale?: "ko" }} options
1847
+ * @returns {LocalizedString}
1848
+ */
1849
+ const cli_checks_lock_drift = ((inputs, options = {}) => {
1850
+ experimentalStaticLocale ?? options.locale ?? getLocale();
1851
+ return ko_cli_checks_lock_drift(inputs);
1852
+ });
1853
+
1854
+ //#endregion
1855
+ //#region ../i18n/src/paraglide/messages/cli_checks_lock_missing.js
1856
+ /** @typedef {import('../runtime.js').LocalizedString} LocalizedString */
1857
+ /** @typedef {{}} Cli_Checks_Lock_MissingInputs */
1858
+ const ko_cli_checks_lock_missing = () => {
1859
+ return `pnpm-lock.yaml이 없습니다. 호스팅 빌드의 설치가 실패할 수 있습니다`;
1860
+ };
1861
+ /**
1862
+
1863
+ * @param {Cli_Checks_Lock_MissingInputs} inputs
1864
+ * @param {{ locale?: "ko" }} options
1865
+ * @returns {LocalizedString}
1866
+ */
1867
+ const cli_checks_lock_missing = ((inputs = {}, options = {}) => {
1868
+ experimentalStaticLocale ?? options.locale ?? getLocale();
1869
+ return ko_cli_checks_lock_missing(inputs);
1870
+ });
1871
+
1872
+ //#endregion
1873
+ //#region ../i18n/src/paraglide/messages/cli_checks_summary.js
1874
+ /** @typedef {import('../runtime.js').LocalizedString} LocalizedString */
1875
+ /** @typedef {{ files: NonNullable<unknown>, size: NonNullable<unknown>, passed: NonNullable<unknown>, rules: NonNullable<unknown> }} Cli_Checks_SummaryInputs */
1876
+ const ko_cli_checks_summary = (i) => {
1877
+ return `로컬 검사 — 파일 ${i?.files}개(${i?.size}), 규칙 ${i?.passed}/${i?.rules} 통과`;
1878
+ };
1879
+ /**
1880
+
1881
+ * @param {Cli_Checks_SummaryInputs} inputs
1882
+ * @param {{ locale?: "ko" }} options
1883
+ * @returns {LocalizedString}
1884
+ */
1885
+ const cli_checks_summary = ((inputs, options = {}) => {
1886
+ experimentalStaticLocale ?? options.locale ?? getLocale();
1887
+ return ko_cli_checks_summary(inputs);
1888
+ });
1889
+
1890
+ //#endregion
1891
+ //#region ../i18n/src/paraglide/messages/cli_continue_confirm.js
1892
+ /** @typedef {import('../runtime.js').LocalizedString} LocalizedString */
1893
+ /** @typedef {{}} Cli_Continue_ConfirmInputs */
1894
+ const ko_cli_continue_confirm = () => {
1895
+ return `계속하시겠습니까?`;
1896
+ };
1897
+ /**
1898
+
1899
+ * @param {Cli_Continue_ConfirmInputs} inputs
1900
+ * @param {{ locale?: "ko" }} options
1901
+ * @returns {LocalizedString}
1902
+ */
1903
+ const cli_continue_confirm = ((inputs = {}, options = {}) => {
1904
+ experimentalStaticLocale ?? options.locale ?? getLocale();
1905
+ return ko_cli_continue_confirm(inputs);
1906
+ });
1907
+
1908
+ //#endregion
1909
+ //#region ../i18n/src/paraglide/messages/cli_credentials_git_tracked.js
1910
+ /** @typedef {import('../runtime.js').LocalizedString} LocalizedString */
1911
+ /** @typedef {{ path: NonNullable<unknown> }} Cli_Credentials_Git_TrackedInputs */
1912
+ const ko_cli_credentials_git_tracked = (i) => {
1913
+ return `${i?.path}가 git에 커밋돼 있어 토큰을 쓰지 않았습니다. 추적을 해제하거나 XDG_CONFIG_HOME으로 다른 폴더를 지정하십시오`;
1914
+ };
1915
+ /**
1916
+
1917
+ * @param {Cli_Credentials_Git_TrackedInputs} inputs
1918
+ * @param {{ locale?: "ko" }} options
1919
+ * @returns {LocalizedString}
1920
+ */
1921
+ const cli_credentials_git_tracked = ((inputs, options = {}) => {
1922
+ experimentalStaticLocale ?? options.locale ?? getLocale();
1923
+ return ko_cli_credentials_git_tracked(inputs);
1924
+ });
1925
+
1926
+ //#endregion
1927
+ //#region ../i18n/src/paraglide/messages/cli_credentials_lock_busy.js
1928
+ /** @typedef {import('../runtime.js').LocalizedString} LocalizedString */
1929
+ /** @typedef {{ lock: NonNullable<unknown> }} Cli_Credentials_Lock_BusyInputs */
1930
+ const ko_cli_credentials_lock_busy = (i) => {
1931
+ return `다른 sayren 명령이 로그인을 갱신하고 있습니다. 잠시 뒤 다시 시도하십시오(${i?.lock})`;
1932
+ };
1933
+ /**
1934
+
1935
+ * @param {Cli_Credentials_Lock_BusyInputs} inputs
1936
+ * @param {{ locale?: "ko" }} options
1937
+ * @returns {LocalizedString}
1938
+ */
1939
+ const cli_credentials_lock_busy = ((inputs, options = {}) => {
1940
+ experimentalStaticLocale ?? options.locale ?? getLocale();
1941
+ return ko_cli_credentials_lock_busy(inputs);
1942
+ });
1943
+
1944
+ //#endregion
1945
+ //#region ../i18n/src/paraglide/messages/cli_credentials_no_config_dir.js
1946
+ /** @typedef {import('../runtime.js').LocalizedString} LocalizedString */
1947
+ /** @typedef {{}} Cli_Credentials_No_Config_DirInputs */
1948
+ const ko_cli_credentials_no_config_dir = () => {
1949
+ return `자격 증명을 저장할 폴더를 정하지 못했습니다(HOME·XDG_CONFIG_HOME 없음). SAYREN_TOKEN 환경 변수로 토큰을 주십시오`;
1950
+ };
1951
+ /**
1952
+
1953
+ * @param {Cli_Credentials_No_Config_DirInputs} inputs
1954
+ * @param {{ locale?: "ko" }} options
1955
+ * @returns {LocalizedString}
1956
+ */
1957
+ const cli_credentials_no_config_dir = ((inputs = {}, options = {}) => {
1958
+ experimentalStaticLocale ?? options.locale ?? getLocale();
1959
+ return ko_cli_credentials_no_config_dir(inputs);
1960
+ });
1961
+
1962
+ //#endregion
1963
+ //#region ../i18n/src/paraglide/messages/cli_credentials_symlink.js
1964
+ /** @typedef {import('../runtime.js').LocalizedString} LocalizedString */
1965
+ /** @typedef {{ path: NonNullable<unknown> }} Cli_Credentials_SymlinkInputs */
1966
+ const ko_cli_credentials_symlink = (i) => {
1967
+ return `${i?.path}가 심볼릭 링크라 읽지 않았습니다. 링크를 지운 뒤 다시 로그인하십시오`;
1968
+ };
1969
+ /**
1970
+
1971
+ * @param {Cli_Credentials_SymlinkInputs} inputs
1972
+ * @param {{ locale?: "ko" }} options
1973
+ * @returns {LocalizedString}
1974
+ */
1975
+ const cli_credentials_symlink = ((inputs, options = {}) => {
1976
+ experimentalStaticLocale ?? options.locale ?? getLocale();
1977
+ return ko_cli_credentials_symlink(inputs);
1978
+ });
1979
+
1980
+ //#endregion
1981
+ //#region ../i18n/src/paraglide/messages/cli_credentials_unreadable.js
1982
+ /** @typedef {import('../runtime.js').LocalizedString} LocalizedString */
1983
+ /** @typedef {{ path: NonNullable<unknown> }} Cli_Credentials_UnreadableInputs */
1984
+ const ko_cli_credentials_unreadable = (i) => {
1985
+ return `${i?.path}를 읽지 못했습니다. 파일을 지우고 다시 로그인하십시오`;
1986
+ };
1987
+ /**
1988
+
1989
+ * @param {Cli_Credentials_UnreadableInputs} inputs
1990
+ * @param {{ locale?: "ko" }} options
1991
+ * @returns {LocalizedString}
1992
+ */
1993
+ const cli_credentials_unreadable = ((inputs, options = {}) => {
1994
+ experimentalStaticLocale ?? options.locale ?? getLocale();
1995
+ return ko_cli_credentials_unreadable(inputs);
1996
+ });
1997
+
1998
+ //#endregion
1999
+ //#region ../i18n/src/paraglide/messages/cli_dependency_check_unavailable.js
2000
+ /** @typedef {import('../runtime.js').LocalizedString} LocalizedString */
2001
+ /** @typedef {{}} Cli_Dependency_Check_UnavailableInputs */
2002
+ const ko_cli_dependency_check_unavailable = () => {
2003
+ return `의존성 확인을 지금 할 수 없습니다. 잠시 뒤 다시 시도하십시오`;
2004
+ };
2005
+ /**
2006
+
2007
+ * @param {Cli_Dependency_Check_UnavailableInputs} inputs
2008
+ * @param {{ locale?: "ko" }} options
2009
+ * @returns {LocalizedString}
2010
+ */
2011
+ const cli_dependency_check_unavailable = ((inputs = {}, options = {}) => {
2012
+ experimentalStaticLocale ?? options.locale ?? getLocale();
2013
+ return ko_cli_dependency_check_unavailable(inputs);
2014
+ });
2015
+
2016
+ //#endregion
2017
+ //#region ../i18n/src/paraglide/messages/cli_dependency_rejected.js
2018
+ /** @typedef {import('../runtime.js').LocalizedString} LocalizedString */
2019
+ /** @typedef {{ items: NonNullable<unknown> }} Cli_Dependency_RejectedInputs */
2020
+ const ko_cli_dependency_rejected = (i) => {
2021
+ return `쓸 수 없는 npm 의존성이 있어 올리지 않았습니다.
2022
+ ${i?.items}`;
2023
+ };
2024
+ /**
2025
+
2026
+ * @param {Cli_Dependency_RejectedInputs} inputs
2027
+ * @param {{ locale?: "ko" }} options
2028
+ * @returns {LocalizedString}
2029
+ */
2030
+ const cli_dependency_rejected = ((inputs, options = {}) => {
2031
+ experimentalStaticLocale ?? options.locale ?? getLocale();
2032
+ return ko_cli_dependency_rejected(inputs);
2033
+ });
2034
+
2035
+ //#endregion
2036
+ //#region ../i18n/src/paraglide/messages/cli_dependency_warning.js
2037
+ /** @typedef {import('../runtime.js').LocalizedString} LocalizedString */
2038
+ /** @typedef {{ finding: NonNullable<unknown> }} Cli_Dependency_WarningInputs */
2039
+ const ko_cli_dependency_warning = (i) => {
2040
+ return `의존성 경고 ${i?.finding}`;
2041
+ };
2042
+ /**
2043
+
2044
+ * @param {Cli_Dependency_WarningInputs} inputs
2045
+ * @param {{ locale?: "ko" }} options
2046
+ * @returns {LocalizedString}
2047
+ */
2048
+ const cli_dependency_warning = ((inputs, options = {}) => {
2049
+ experimentalStaticLocale ?? options.locale ?? getLocale();
2050
+ return ko_cli_dependency_warning(inputs);
2051
+ });
2052
+
2053
+ //#endregion
2054
+ //#region ../i18n/src/paraglide/messages/cli_deploy_build_in_progress.js
2055
+ /** @typedef {import('../runtime.js').LocalizedString} LocalizedString */
2056
+ /** @typedef {{}} Cli_Deploy_Build_In_ProgressInputs */
2057
+ const ko_cli_deploy_build_in_progress = () => {
2058
+ return `이 사이트에 끝나지 않은 빌드가 있습니다(상점 플랫폼·AI 또는 다른 배포). 작업 트리는 올렸습니다 — npx sayren status로 확인한 뒤 다시 배포하십시오`;
2059
+ };
2060
+ /**
2061
+
2062
+ * @param {Cli_Deploy_Build_In_ProgressInputs} inputs
2063
+ * @param {{ locale?: "ko" }} options
2064
+ * @returns {LocalizedString}
2065
+ */
2066
+ const cli_deploy_build_in_progress = ((inputs = {}, options = {}) => {
2067
+ experimentalStaticLocale ?? options.locale ?? getLocale();
2068
+ return ko_cli_deploy_build_in_progress(inputs);
2069
+ });
2070
+
2071
+ //#endregion
2072
+ //#region ../i18n/src/paraglide/messages/cli_deploy_build_local_failed.js
2073
+ /** @typedef {import('../runtime.js').LocalizedString} LocalizedString */
2074
+ /** @typedef {{ code: NonNullable<unknown> }} Cli_Deploy_Build_Local_FailedInputs */
2075
+ const ko_cli_deploy_build_local_failed = (i) => {
2076
+ return `로컬 빌드가 실패해 올리지 않았습니다(종료 코드 ${i?.code}). 위 출력을 확인해 고친 뒤 다시 배포하십시오. 빌드를 확인하지 않고 올리려면 --skip-build를 붙이십시오`;
2077
+ };
2078
+ /**
2079
+
2080
+ * @param {Cli_Deploy_Build_Local_FailedInputs} inputs
2081
+ * @param {{ locale?: "ko" }} options
2082
+ * @returns {LocalizedString}
2083
+ */
2084
+ const cli_deploy_build_local_failed = ((inputs, options = {}) => {
2085
+ experimentalStaticLocale ?? options.locale ?? getLocale();
2086
+ return ko_cli_deploy_build_local_failed(inputs);
2087
+ });
2088
+
2089
+ //#endregion
2090
+ //#region ../i18n/src/paraglide/messages/cli_deploy_build_local_no_deps.js
2091
+ /** @typedef {import('../runtime.js').LocalizedString} LocalizedString */
2092
+ /** @typedef {{}} Cli_Deploy_Build_Local_No_DepsInputs */
2093
+ const ko_cli_deploy_build_local_no_deps = () => {
2094
+ return `의존성이 설치되지 않아(node_modules 없음) 로컬 빌드를 건너뜁니다. npm install --ignore-scripts 뒤 배포하면 올리기 전에 빌드를 확인합니다`;
2095
+ };
2096
+ /**
2097
+
2098
+ * @param {Cli_Deploy_Build_Local_No_DepsInputs} inputs
2099
+ * @param {{ locale?: "ko" }} options
2100
+ * @returns {LocalizedString}
2101
+ */
2102
+ const cli_deploy_build_local_no_deps = ((inputs = {}, options = {}) => {
2103
+ experimentalStaticLocale ?? options.locale ?? getLocale();
2104
+ return ko_cli_deploy_build_local_no_deps(inputs);
2105
+ });
2106
+
2107
+ //#endregion
2108
+ //#region ../i18n/src/paraglide/messages/cli_deploy_build_local_no_script.js
2109
+ /** @typedef {import('../runtime.js').LocalizedString} LocalizedString */
2110
+ /** @typedef {{}} Cli_Deploy_Build_Local_No_ScriptInputs */
2111
+ const ko_cli_deploy_build_local_no_script = () => {
2112
+ return `package.json에 build 스크립트가 없어 로컬 빌드를 건너뜁니다`;
2113
+ };
2114
+ /**
2115
+
2116
+ * @param {Cli_Deploy_Build_Local_No_ScriptInputs} inputs
2117
+ * @param {{ locale?: "ko" }} options
2118
+ * @returns {LocalizedString}
2119
+ */
2120
+ const cli_deploy_build_local_no_script = ((inputs = {}, options = {}) => {
2121
+ experimentalStaticLocale ?? options.locale ?? getLocale();
2122
+ return ko_cli_deploy_build_local_no_script(inputs);
2123
+ });
2124
+
2125
+ //#endregion
2126
+ //#region ../i18n/src/paraglide/messages/cli_deploy_build_local_output.js
2127
+ /** @typedef {import('../runtime.js').LocalizedString} LocalizedString */
2128
+ /** @typedef {{ count: NonNullable<unknown> }} Cli_Deploy_Build_Local_OutputInputs */
2129
+ const ko_cli_deploy_build_local_output = (i) => {
2130
+ return `빌드 출력(마지막 ${i?.count}줄):`;
2131
+ };
2132
+ /**
2133
+
2134
+ * @param {Cli_Deploy_Build_Local_OutputInputs} inputs
2135
+ * @param {{ locale?: "ko" }} options
2136
+ * @returns {LocalizedString}
2137
+ */
2138
+ const cli_deploy_build_local_output = ((inputs, options = {}) => {
2139
+ experimentalStaticLocale ?? options.locale ?? getLocale();
2140
+ return ko_cli_deploy_build_local_output(inputs);
2141
+ });
2142
+
2143
+ //#endregion
2144
+ //#region ../i18n/src/paraglide/messages/cli_deploy_build_local_passed.js
2145
+ /** @typedef {import('../runtime.js').LocalizedString} LocalizedString */
2146
+ /** @typedef {{ seconds: NonNullable<unknown> }} Cli_Deploy_Build_Local_PassedInputs */
2147
+ const ko_cli_deploy_build_local_passed = (i) => {
2148
+ return `로컬 빌드 통과(${i?.seconds}초)`;
2149
+ };
2150
+ /**
2151
+
2152
+ * @param {Cli_Deploy_Build_Local_PassedInputs} inputs
2153
+ * @param {{ locale?: "ko" }} options
2154
+ * @returns {LocalizedString}
2155
+ */
2156
+ const cli_deploy_build_local_passed = ((inputs, options = {}) => {
2157
+ experimentalStaticLocale ?? options.locale ?? getLocale();
2158
+ return ko_cli_deploy_build_local_passed(inputs);
2159
+ });
2160
+
2161
+ //#endregion
2162
+ //#region ../i18n/src/paraglide/messages/cli_deploy_build_local_running.js
2163
+ /** @typedef {import('../runtime.js').LocalizedString} LocalizedString */
2164
+ /** @typedef {{}} Cli_Deploy_Build_Local_RunningInputs */
2165
+ const ko_cli_deploy_build_local_running = () => {
2166
+ return `로컬 빌드(npm run build)를 실행합니다. 서버 빌드가 실패할 것을 올리기 전에 확인합니다`;
2167
+ };
2168
+ /**
2169
+
2170
+ * @param {Cli_Deploy_Build_Local_RunningInputs} inputs
2171
+ * @param {{ locale?: "ko" }} options
2172
+ * @returns {LocalizedString}
2173
+ */
2174
+ const cli_deploy_build_local_running = ((inputs = {}, options = {}) => {
2175
+ experimentalStaticLocale ?? options.locale ?? getLocale();
2176
+ return ko_cli_deploy_build_local_running(inputs);
2177
+ });
2178
+
2179
+ //#endregion
2180
+ //#region ../i18n/src/paraglide/messages/cli_deploy_build_local_skipped_flag.js
2181
+ /** @typedef {import('../runtime.js').LocalizedString} LocalizedString */
2182
+ /** @typedef {{}} Cli_Deploy_Build_Local_Skipped_FlagInputs */
2183
+ const ko_cli_deploy_build_local_skipped_flag = () => {
2184
+ return `로컬 빌드를 건너뜁니다(--skip-build). 서버 빌드가 같은 빌드를 다시 합니다`;
2185
+ };
2186
+ /**
2187
+
2188
+ * @param {Cli_Deploy_Build_Local_Skipped_FlagInputs} inputs
2189
+ * @param {{ locale?: "ko" }} options
2190
+ * @returns {LocalizedString}
2191
+ */
2192
+ const cli_deploy_build_local_skipped_flag = ((inputs = {}, options = {}) => {
2193
+ experimentalStaticLocale ?? options.locale ?? getLocale();
2194
+ return ko_cli_deploy_build_local_skipped_flag(inputs);
2195
+ });
2196
+
2197
+ //#endregion
2198
+ //#region ../i18n/src/paraglide/messages/cli_deploy_build_local_spawn_failed.js
2199
+ /** @typedef {import('../runtime.js').LocalizedString} LocalizedString */
2200
+ /** @typedef {{ message: NonNullable<unknown> }} Cli_Deploy_Build_Local_Spawn_FailedInputs */
2201
+ const ko_cli_deploy_build_local_spawn_failed = (i) => {
2202
+ return `로컬 빌드를 시작하지 못해 올리지 않았습니다(${i?.message}). npm이 PATH에 있는지 확인하거나 --skip-build를 붙이십시오`;
2203
+ };
2204
+ /**
2205
+
2206
+ * @param {Cli_Deploy_Build_Local_Spawn_FailedInputs} inputs
2207
+ * @param {{ locale?: "ko" }} options
2208
+ * @returns {LocalizedString}
2209
+ */
2210
+ const cli_deploy_build_local_spawn_failed = ((inputs, options = {}) => {
2211
+ experimentalStaticLocale ?? options.locale ?? getLocale();
2212
+ return ko_cli_deploy_build_local_spawn_failed(inputs);
2213
+ });
2214
+
2215
+ //#endregion
2216
+ //#region ../i18n/src/paraglide/messages/cli_deploy_build_started.js
2217
+ /** @typedef {import('../runtime.js').LocalizedString} LocalizedString */
2218
+ /** @typedef {{ version: NonNullable<unknown> }} Cli_Deploy_Build_StartedInputs */
2219
+ const ko_cli_deploy_build_started = (i) => {
2220
+ return `버전 v${i?.version} 빌드 시작`;
2221
+ };
2222
+ /**
2223
+
2224
+ * @param {Cli_Deploy_Build_StartedInputs} inputs
2225
+ * @param {{ locale?: "ko" }} options
2226
+ * @returns {LocalizedString}
2227
+ */
2228
+ const cli_deploy_build_started = ((inputs, options = {}) => {
2229
+ experimentalStaticLocale ?? options.locale ?? getLocale();
2230
+ return ko_cli_deploy_build_started(inputs);
2231
+ });
2232
+
2233
+ //#endregion
2234
+ //#region ../i18n/src/paraglide/messages/cli_deploy_build_succeeded.js
2235
+ /** @typedef {import('../runtime.js').LocalizedString} LocalizedString */
2236
+ /** @typedef {{ version: NonNullable<unknown> }} Cli_Deploy_Build_SucceededInputs */
2237
+ const ko_cli_deploy_build_succeeded = (i) => {
2238
+ return `빌드 성공 — v${i?.version}`;
2239
+ };
2240
+ /**
2241
+
2242
+ * @param {Cli_Deploy_Build_SucceededInputs} inputs
2243
+ * @param {{ locale?: "ko" }} options
2244
+ * @returns {LocalizedString}
2245
+ */
2246
+ const cli_deploy_build_succeeded = ((inputs, options = {}) => {
2247
+ experimentalStaticLocale ?? options.locale ?? getLocale();
2248
+ return ko_cli_deploy_build_succeeded(inputs);
2249
+ });
2250
+
2251
+ //#endregion
2252
+ //#region ../i18n/src/paraglide/messages/cli_deploy_build_succeeded_duration.js
2253
+ /** @typedef {import('../runtime.js').LocalizedString} LocalizedString */
2254
+ /** @typedef {{ version: NonNullable<unknown>, seconds: NonNullable<unknown> }} Cli_Deploy_Build_Succeeded_DurationInputs */
2255
+ const ko_cli_deploy_build_succeeded_duration = (i) => {
2256
+ return `빌드 성공 — v${i?.version} (${i?.seconds}초)`;
2257
+ };
2258
+ /**
2259
+
2260
+ * @param {Cli_Deploy_Build_Succeeded_DurationInputs} inputs
2261
+ * @param {{ locale?: "ko" }} options
2262
+ * @returns {LocalizedString}
2263
+ */
2264
+ const cli_deploy_build_succeeded_duration = ((inputs, options = {}) => {
2265
+ experimentalStaticLocale ?? options.locale ?? getLocale();
2266
+ return ko_cli_deploy_build_succeeded_duration(inputs);
2267
+ });
2268
+
2269
+ //#endregion
2270
+ //#region ../i18n/src/paraglide/messages/cli_deploy_checks_failed.js
2271
+ /** @typedef {import('../runtime.js').LocalizedString} LocalizedString */
2272
+ /** @typedef {{}} Cli_Deploy_Checks_FailedInputs */
2273
+ const ko_cli_deploy_checks_failed = () => {
2274
+ return `로컬 검사를 통과하지 못해 배포하지 않았습니다. 위 항목을 고친 뒤 다시 시도하십시오`;
2275
+ };
2276
+ /**
2277
+
2278
+ * @param {Cli_Deploy_Checks_FailedInputs} inputs
2279
+ * @param {{ locale?: "ko" }} options
2280
+ * @returns {LocalizedString}
2281
+ */
2282
+ const cli_deploy_checks_failed = ((inputs = {}, options = {}) => {
2283
+ experimentalStaticLocale ?? options.locale ?? getLocale();
2284
+ return ko_cli_deploy_checks_failed(inputs);
2285
+ });
2286
+
2287
+ //#endregion
2288
+ //#region ../i18n/src/paraglide/messages/cli_deploy_force_confirm.js
2289
+ /** @typedef {import('../runtime.js').LocalizedString} LocalizedString */
2290
+ /** @typedef {{}} Cli_Deploy_Force_ConfirmInputs */
2291
+ const ko_cli_deploy_force_confirm = () => {
2292
+ return `원격 작업 트리(상점 플랫폼·AI 편집 포함)를 이 폴더 내용으로 덮어쓰고, 열린 편집 환경을 끕니다. 계속하시겠습니까?`;
2293
+ };
2294
+ /**
2295
+
2296
+ * @param {Cli_Deploy_Force_ConfirmInputs} inputs
2297
+ * @param {{ locale?: "ko" }} options
2298
+ * @returns {LocalizedString}
2299
+ */
2300
+ const cli_deploy_force_confirm = ((inputs = {}, options = {}) => {
2301
+ experimentalStaticLocale ?? options.locale ?? getLocale();
2302
+ return ko_cli_deploy_force_confirm(inputs);
1369
2303
  });
1370
2304
 
1371
2305
  //#endregion
1372
2306
  //#region ../i18n/src/paraglide/messages/cli_deploy_force_yes_required.js
1373
2307
  /** @typedef {import('../runtime.js').LocalizedString} LocalizedString */
1374
- /** @typedef {{}} Cli_Deploy_Force_Yes_RequiredInputs */
1375
- const ko_cli_deploy_force_yes_required = () => {
1376
- return `--force는 원격 작업 트리를 덮어씁니다. 확인할 수 없는 환경이면 --yes를 함께 주십시오`;
2308
+ /** @typedef {{}} Cli_Deploy_Force_Yes_RequiredInputs */
2309
+ const ko_cli_deploy_force_yes_required = () => {
2310
+ return `--force는 원격 작업 트리를 덮어씁니다. 확인할 수 없는 환경이면 --yes를 함께 주십시오`;
2311
+ };
2312
+ /**
2313
+
2314
+ * @param {Cli_Deploy_Force_Yes_RequiredInputs} inputs
2315
+ * @param {{ locale?: "ko" }} options
2316
+ * @returns {LocalizedString}
2317
+ */
2318
+ const cli_deploy_force_yes_required = ((inputs = {}, options = {}) => {
2319
+ experimentalStaticLocale ?? options.locale ?? getLocale();
2320
+ return ko_cli_deploy_force_yes_required(inputs);
2321
+ });
2322
+
2323
+ //#endregion
2324
+ //#region ../i18n/src/paraglide/messages/cli_deploy_no_state.js
2325
+ /** @typedef {import('../runtime.js').LocalizedString} LocalizedString */
2326
+ /** @typedef {{ stateFile: NonNullable<unknown>, storeId: NonNullable<unknown>, dir: NonNullable<unknown> }} Cli_Deploy_No_StateInputs */
2327
+ const ko_cli_deploy_no_state = (i) => {
2328
+ return `${i?.stateFile}가 없습니다. 이 사이트 소스를 clone한 폴더면 npx sayren pull --force --project ${i?.storeId} --dir ${i?.dir}로 이 폴더를 원격 작업 트리에 맞춘 뒤(로컬 변경은 먼저 커밋·백업하십시오) 다시 배포하십시오. 처음이면 npx sayren pull로 받으십시오`;
2329
+ };
2330
+ /**
2331
+
2332
+ * @param {Cli_Deploy_No_StateInputs} inputs
2333
+ * @param {{ locale?: "ko" }} options
2334
+ * @returns {LocalizedString}
2335
+ */
2336
+ const cli_deploy_no_state = ((inputs, options = {}) => {
2337
+ experimentalStaticLocale ?? options.locale ?? getLocale();
2338
+ return ko_cli_deploy_no_state(inputs);
2339
+ });
2340
+
2341
+ //#endregion
2342
+ //#region ../i18n/src/paraglide/messages/cli_deploy_not_published.js
2343
+ /** @typedef {import('../runtime.js').LocalizedString} LocalizedString */
2344
+ /** @typedef {{ version: NonNullable<unknown> }} Cli_Deploy_Not_PublishedInputs */
2345
+ const ko_cli_deploy_not_published = (i) => {
2346
+ return `발행하지 않았습니다(--no-publish). 상점 플랫폼 › 스토어프론트 › 버전에서 v${i?.version}를 발행할 수 있습니다`;
2347
+ };
2348
+ /**
2349
+
2350
+ * @param {Cli_Deploy_Not_PublishedInputs} inputs
2351
+ * @param {{ locale?: "ko" }} options
2352
+ * @returns {LocalizedString}
2353
+ */
2354
+ const cli_deploy_not_published = ((inputs, options = {}) => {
2355
+ experimentalStaticLocale ?? options.locale ?? getLocale();
2356
+ return ko_cli_deploy_not_published(inputs);
2357
+ });
2358
+
2359
+ //#endregion
2360
+ //#region ../i18n/src/paraglide/messages/cli_deploy_publish_approval.js
2361
+ /** @typedef {import('../runtime.js').LocalizedString} LocalizedString */
2362
+ /** @typedef {{ version: NonNullable<unknown> }} Cli_Deploy_Publish_ApprovalInputs */
2363
+ const ko_cli_deploy_publish_approval = (i) => {
2364
+ return `발행은 승인이 필요합니다(에이전트 토큰). 셀러가 승인하면 v${i?.version}가 발행됩니다`;
2365
+ };
2366
+ /**
2367
+
2368
+ * @param {Cli_Deploy_Publish_ApprovalInputs} inputs
2369
+ * @param {{ locale?: "ko" }} options
2370
+ * @returns {LocalizedString}
2371
+ */
2372
+ const cli_deploy_publish_approval = ((inputs, options = {}) => {
2373
+ experimentalStaticLocale ?? options.locale ?? getLocale();
2374
+ return ko_cli_deploy_publish_approval(inputs);
2375
+ });
2376
+
2377
+ //#endregion
2378
+ //#region ../i18n/src/paraglide/messages/cli_deploy_publish_delay.js
2379
+ /** @typedef {import('../runtime.js').LocalizedString} LocalizedString */
2380
+ /** @typedef {{}} Cli_Deploy_Publish_DelayInputs */
2381
+ const ko_cli_deploy_publish_delay = () => {
2382
+ return `반영까지 1분 안팎이 걸립니다`;
2383
+ };
2384
+ /**
2385
+
2386
+ * @param {Cli_Deploy_Publish_DelayInputs} inputs
2387
+ * @param {{ locale?: "ko" }} options
2388
+ * @returns {LocalizedString}
2389
+ */
2390
+ const cli_deploy_publish_delay = ((inputs = {}, options = {}) => {
2391
+ experimentalStaticLocale ?? options.locale ?? getLocale();
2392
+ return ko_cli_deploy_publish_delay(inputs);
2393
+ });
2394
+
2395
+ //#endregion
2396
+ //#region ../i18n/src/paraglide/messages/cli_deploy_published.js
2397
+ /** @typedef {import('../runtime.js').LocalizedString} LocalizedString */
2398
+ /** @typedef {{ version: NonNullable<unknown>, url: NonNullable<unknown> }} Cli_Deploy_PublishedInputs */
2399
+ const ko_cli_deploy_published = (i) => {
2400
+ return `발행 — v${i?.version} → ${i?.url}`;
2401
+ };
2402
+ /**
2403
+
2404
+ * @param {Cli_Deploy_PublishedInputs} inputs
2405
+ * @param {{ locale?: "ko" }} options
2406
+ * @returns {LocalizedString}
2407
+ */
2408
+ const cli_deploy_published = ((inputs, options = {}) => {
2409
+ experimentalStaticLocale ?? options.locale ?? getLocale();
2410
+ return ko_cli_deploy_published(inputs);
2411
+ });
2412
+
2413
+ //#endregion
2414
+ //#region ../i18n/src/paraglide/messages/cli_deploy_site_changed.js
2415
+ /** @typedef {import('../runtime.js').LocalizedString} LocalizedString */
2416
+ /** @typedef {{ version: NonNullable<unknown> }} Cli_Deploy_Site_ChangedInputs */
2417
+ const ko_cli_deploy_site_changed = (i) => {
2418
+ return `다른 사람이 그 사이 다른 버전을 발행했습니다. v${i?.version}는 만들어 뒀습니다 — 상점 플랫폼에서 확인한 뒤 발행하십시오`;
2419
+ };
2420
+ /**
2421
+
2422
+ * @param {Cli_Deploy_Site_ChangedInputs} inputs
2423
+ * @param {{ locale?: "ko" }} options
2424
+ * @returns {LocalizedString}
2425
+ */
2426
+ const cli_deploy_site_changed = ((inputs, options = {}) => {
2427
+ experimentalStaticLocale ?? options.locale ?? getLocale();
2428
+ return ko_cli_deploy_site_changed(inputs);
2429
+ });
2430
+
2431
+ //#endregion
2432
+ //#region ../i18n/src/paraglide/messages/cli_deploy_site_mismatch.js
2433
+ /** @typedef {import('../runtime.js').LocalizedString} LocalizedString */
2434
+ /** @typedef {{ siteId: NonNullable<unknown> }} Cli_Deploy_Site_MismatchInputs */
2435
+ const ko_cli_deploy_site_mismatch = (i) => {
2436
+ return `이 폴더의 사이트(${i?.siteId})가 상점의 지금 사이트와 다릅니다. npx sayren pull로 다시 받으십시오`;
2437
+ };
2438
+ /**
2439
+
2440
+ * @param {Cli_Deploy_Site_MismatchInputs} inputs
2441
+ * @param {{ locale?: "ko" }} options
2442
+ * @returns {LocalizedString}
2443
+ */
2444
+ const cli_deploy_site_mismatch = ((inputs, options = {}) => {
2445
+ experimentalStaticLocale ?? options.locale ?? getLocale();
2446
+ return ko_cli_deploy_site_mismatch(inputs);
2447
+ });
2448
+
2449
+ //#endregion
2450
+ //#region ../i18n/src/paraglide/messages/cli_deploy_source_approval.js
2451
+ /** @typedef {import('../runtime.js').LocalizedString} LocalizedString */
2452
+ /** @typedef {{}} Cli_Deploy_Source_ApprovalInputs */
2453
+ const ko_cli_deploy_source_approval = () => {
2454
+ return `작업 트리 바꾸기는 승인이 필요합니다(에이전트 토큰이 package.json·vite.config.ts를 바꿉니다). 승인된 뒤 npx sayren deploy를 다시 돌리면 빌드·발행합니다`;
2455
+ };
2456
+ /**
2457
+
2458
+ * @param {Cli_Deploy_Source_ApprovalInputs} inputs
2459
+ * @param {{ locale?: "ko" }} options
2460
+ * @returns {LocalizedString}
2461
+ */
2462
+ const cli_deploy_source_approval = ((inputs = {}, options = {}) => {
2463
+ experimentalStaticLocale ?? options.locale ?? getLocale();
2464
+ return ko_cli_deploy_source_approval(inputs);
2465
+ });
2466
+
2467
+ //#endregion
2468
+ //#region ../i18n/src/paraglide/messages/cli_deploy_source_changed_after_upload.js
2469
+ /** @typedef {import('../runtime.js').LocalizedString} LocalizedString */
2470
+ /** @typedef {{}} Cli_Deploy_Source_Changed_After_UploadInputs */
2471
+ const ko_cli_deploy_source_changed_after_upload = () => {
2472
+ return `올린 직후 다른 편집이 끼어 버전을 만들지 않았습니다. npx sayren pull --force로 받아 합친 뒤 다시 배포하십시오`;
2473
+ };
2474
+ /**
2475
+
2476
+ * @param {Cli_Deploy_Source_Changed_After_UploadInputs} inputs
2477
+ * @param {{ locale?: "ko" }} options
2478
+ * @returns {LocalizedString}
2479
+ */
2480
+ const cli_deploy_source_changed_after_upload = ((inputs = {}, options = {}) => {
2481
+ experimentalStaticLocale ?? options.locale ?? getLocale();
2482
+ return ko_cli_deploy_source_changed_after_upload(inputs);
2483
+ });
2484
+
2485
+ //#endregion
2486
+ //#region ../i18n/src/paraglide/messages/cli_deploy_unchanged.js
2487
+ /** @typedef {import('../runtime.js').LocalizedString} LocalizedString */
2488
+ /** @typedef {{}} Cli_Deploy_UnchangedInputs */
2489
+ const ko_cli_deploy_unchanged = () => {
2490
+ return `작업 트리가 원격과 같습니다 — 그대로 빌드합니다`;
2491
+ };
2492
+ /**
2493
+
2494
+ * @param {Cli_Deploy_UnchangedInputs} inputs
2495
+ * @param {{ locale?: "ko" }} options
2496
+ * @returns {LocalizedString}
2497
+ */
2498
+ const cli_deploy_unchanged = ((inputs = {}, options = {}) => {
2499
+ experimentalStaticLocale ?? options.locale ?? getLocale();
2500
+ return ko_cli_deploy_unchanged(inputs);
2501
+ });
2502
+
2503
+ //#endregion
2504
+ //#region ../i18n/src/paraglide/messages/cli_deploy_uploaded.js
2505
+ /** @typedef {import('../runtime.js').LocalizedString} LocalizedString */
2506
+ /** @typedef {{ files: NonNullable<unknown> }} Cli_Deploy_UploadedInputs */
2507
+ const ko_cli_deploy_uploaded = (i) => {
2508
+ return `작업 트리 올림 — ${i?.files}개 파일`;
1377
2509
  };
1378
2510
  /**
1379
2511
 
1380
- * @param {Cli_Deploy_Force_Yes_RequiredInputs} inputs
2512
+ * @param {Cli_Deploy_UploadedInputs} inputs
1381
2513
  * @param {{ locale?: "ko" }} options
1382
2514
  * @returns {LocalizedString}
1383
2515
  */
1384
- const cli_deploy_force_yes_required = ((inputs = {}, options = {}) => {
2516
+ const cli_deploy_uploaded = ((inputs, options = {}) => {
1385
2517
  experimentalStaticLocale ?? options.locale ?? getLocale();
1386
- return ko_cli_deploy_force_yes_required(inputs);
2518
+ return ko_cli_deploy_uploaded(inputs);
1387
2519
  });
1388
2520
 
1389
2521
  //#endregion
1390
- //#region ../i18n/src/paraglide/messages/cli_deploy_no_state.js
2522
+ //#region ../i18n/src/paraglide/messages/cli_deploy_uploaded_edit_ended.js
1391
2523
  /** @typedef {import('../runtime.js').LocalizedString} LocalizedString */
1392
- /** @typedef {{ stateFile: NonNullable<unknown>, storeId: NonNullable<unknown>, dir: NonNullable<unknown> }} Cli_Deploy_No_StateInputs */
1393
- const ko_cli_deploy_no_state = (i) => {
1394
- return `${i?.stateFile}가 없습니다. 이 사이트 소스를 clone한 폴더면 npx sayren pull --force --project ${i?.storeId} --dir ${i?.dir}로 이 폴더를 원격 작업 트리에 맞춘 뒤(로컬 변경은 먼저 커밋·백업하십시오) 다시 배포하십시오. 처음이면 npx sayren pull로 받으십시오`;
2524
+ /** @typedef {{ files: NonNullable<unknown> }} Cli_Deploy_Uploaded_Edit_EndedInputs */
2525
+ const ko_cli_deploy_uploaded_edit_ended = (i) => {
2526
+ return `작업 트리 올림 — ${i?.files}개 파일(열린 편집 환경을 껐습니다)`;
1395
2527
  };
1396
2528
  /**
1397
2529
 
1398
- * @param {Cli_Deploy_No_StateInputs} inputs
2530
+ * @param {Cli_Deploy_Uploaded_Edit_EndedInputs} inputs
1399
2531
  * @param {{ locale?: "ko" }} options
1400
2532
  * @returns {LocalizedString}
1401
2533
  */
1402
- const cli_deploy_no_state = ((inputs, options = {}) => {
2534
+ const cli_deploy_uploaded_edit_ended = ((inputs, options = {}) => {
1403
2535
  experimentalStaticLocale ?? options.locale ?? getLocale();
1404
- return ko_cli_deploy_no_state(inputs);
2536
+ return ko_cli_deploy_uploaded_edit_ended(inputs);
1405
2537
  });
1406
2538
 
1407
2539
  //#endregion
1408
- //#region ../i18n/src/paraglide/messages/cli_deploy_not_published.js
2540
+ //#region ../i18n/src/paraglide/messages/cli_device_code.js
1409
2541
  /** @typedef {import('../runtime.js').LocalizedString} LocalizedString */
1410
- /** @typedef {{ version: NonNullable<unknown> }} Cli_Deploy_Not_PublishedInputs */
1411
- const ko_cli_deploy_not_published = (i) => {
1412
- return `발행하지 않았습니다(--no-publish). 상점 플랫폼 › 스토어프론트 › 버전에서 v${i?.version}를 발행할 수 있습니다`;
2542
+ /** @typedef {{ code: NonNullable<unknown> }} Cli_Device_CodeInputs */
2543
+ const ko_cli_device_code = (i) => {
2544
+ return `코드: ${i?.code}`;
1413
2545
  };
1414
2546
  /**
1415
2547
 
1416
- * @param {Cli_Deploy_Not_PublishedInputs} inputs
2548
+ * @param {Cli_Device_CodeInputs} inputs
1417
2549
  * @param {{ locale?: "ko" }} options
1418
2550
  * @returns {LocalizedString}
1419
2551
  */
1420
- const cli_deploy_not_published = ((inputs, options = {}) => {
2552
+ const cli_device_code = ((inputs, options = {}) => {
1421
2553
  experimentalStaticLocale ?? options.locale ?? getLocale();
1422
- return ko_cli_deploy_not_published(inputs);
2554
+ return ko_cli_device_code(inputs);
1423
2555
  });
1424
2556
 
1425
2557
  //#endregion
1426
- //#region ../i18n/src/paraglide/messages/cli_deploy_publish_approval.js
2558
+ //#region ../i18n/src/paraglide/messages/cli_device_denied.js
1427
2559
  /** @typedef {import('../runtime.js').LocalizedString} LocalizedString */
1428
- /** @typedef {{ version: NonNullable<unknown> }} Cli_Deploy_Publish_ApprovalInputs */
1429
- const ko_cli_deploy_publish_approval = (i) => {
1430
- return `발행은 승인이 필요합니다(에이전트 토큰). 셀러가 승인하면 v${i?.version}가 발행됩니다`;
2560
+ /** @typedef {{}} Cli_Device_DeniedInputs */
2561
+ const ko_cli_device_denied = () => {
2562
+ return `기기 연결을 거부했습니다`;
1431
2563
  };
1432
2564
  /**
1433
2565
 
1434
- * @param {Cli_Deploy_Publish_ApprovalInputs} inputs
2566
+ * @param {Cli_Device_DeniedInputs} inputs
1435
2567
  * @param {{ locale?: "ko" }} options
1436
2568
  * @returns {LocalizedString}
1437
2569
  */
1438
- const cli_deploy_publish_approval = ((inputs, options = {}) => {
2570
+ const cli_device_denied = ((inputs = {}, options = {}) => {
1439
2571
  experimentalStaticLocale ?? options.locale ?? getLocale();
1440
- return ko_cli_deploy_publish_approval(inputs);
2572
+ return ko_cli_device_denied(inputs);
1441
2573
  });
1442
2574
 
1443
2575
  //#endregion
1444
- //#region ../i18n/src/paraglide/messages/cli_deploy_publish_delay.js
2576
+ //#region ../i18n/src/paraglide/messages/cli_device_expired.js
1445
2577
  /** @typedef {import('../runtime.js').LocalizedString} LocalizedString */
1446
- /** @typedef {{}} Cli_Deploy_Publish_DelayInputs */
1447
- const ko_cli_deploy_publish_delay = () => {
1448
- return `반영까지 1분 안팎이 걸립니다`;
2578
+ /** @typedef {{}} Cli_Device_ExpiredInputs */
2579
+ const ko_cli_device_expired = () => {
2580
+ return `코드가 만료됐습니다. 다시 로그인하십시오`;
1449
2581
  };
1450
2582
  /**
1451
2583
 
1452
- * @param {Cli_Deploy_Publish_DelayInputs} inputs
2584
+ * @param {Cli_Device_ExpiredInputs} inputs
1453
2585
  * @param {{ locale?: "ko" }} options
1454
2586
  * @returns {LocalizedString}
1455
2587
  */
1456
- const cli_deploy_publish_delay = ((inputs = {}, options = {}) => {
2588
+ const cli_device_expired = ((inputs = {}, options = {}) => {
1457
2589
  experimentalStaticLocale ?? options.locale ?? getLocale();
1458
- return ko_cli_deploy_publish_delay(inputs);
2590
+ return ko_cli_device_expired(inputs);
1459
2591
  });
1460
2592
 
1461
2593
  //#endregion
1462
- //#region ../i18n/src/paraglide/messages/cli_deploy_published.js
2594
+ //#region ../i18n/src/paraglide/messages/cli_device_failed.js
1463
2595
  /** @typedef {import('../runtime.js').LocalizedString} LocalizedString */
1464
- /** @typedef {{ version: NonNullable<unknown>, url: NonNullable<unknown> }} Cli_Deploy_PublishedInputs */
1465
- const ko_cli_deploy_published = (i) => {
1466
- return `발행 — v${i?.version} → ${i?.url}`;
2596
+ /** @typedef {{ error: NonNullable<unknown> }} Cli_Device_FailedInputs */
2597
+ const ko_cli_device_failed = (i) => {
2598
+ return `기기 로그인을 마치지 못했습니다(${i?.error})`;
1467
2599
  };
1468
2600
  /**
1469
2601
 
1470
- * @param {Cli_Deploy_PublishedInputs} inputs
2602
+ * @param {Cli_Device_FailedInputs} inputs
1471
2603
  * @param {{ locale?: "ko" }} options
1472
2604
  * @returns {LocalizedString}
1473
2605
  */
1474
- const cli_deploy_published = ((inputs, options = {}) => {
2606
+ const cli_device_failed = ((inputs, options = {}) => {
1475
2607
  experimentalStaticLocale ?? options.locale ?? getLocale();
1476
- return ko_cli_deploy_published(inputs);
2608
+ return ko_cli_device_failed(inputs);
1477
2609
  });
1478
2610
 
1479
2611
  //#endregion
1480
- //#region ../i18n/src/paraglide/messages/cli_deploy_site_changed.js
2612
+ //#region ../i18n/src/paraglide/messages/cli_device_prompt.js
1481
2613
  /** @typedef {import('../runtime.js').LocalizedString} LocalizedString */
1482
- /** @typedef {{ version: NonNullable<unknown> }} Cli_Deploy_Site_ChangedInputs */
1483
- const ko_cli_deploy_site_changed = (i) => {
1484
- return `다른 사람이 그 사이 다른 버전을 발행했습니다. v${i?.version}는 만들어 뒀습니다 — 상점 플랫폼에서 확인한 뒤 발행하십시오`;
2614
+ /** @typedef {{}} Cli_Device_PromptInputs */
2615
+ const ko_cli_device_prompt = () => {
2616
+ return `다른 기기의 브라우저에서 아래 주소를 열고 코드를 확인하십시오:`;
1485
2617
  };
1486
2618
  /**
1487
2619
 
1488
- * @param {Cli_Deploy_Site_ChangedInputs} inputs
2620
+ * @param {Cli_Device_PromptInputs} inputs
1489
2621
  * @param {{ locale?: "ko" }} options
1490
2622
  * @returns {LocalizedString}
1491
2623
  */
1492
- const cli_deploy_site_changed = ((inputs, options = {}) => {
2624
+ const cli_device_prompt = ((inputs = {}, options = {}) => {
1493
2625
  experimentalStaticLocale ?? options.locale ?? getLocale();
1494
- return ko_cli_deploy_site_changed(inputs);
2626
+ return ko_cli_device_prompt(inputs);
1495
2627
  });
1496
2628
 
1497
2629
  //#endregion
1498
- //#region ../i18n/src/paraglide/messages/cli_deploy_site_mismatch.js
2630
+ //#region ../i18n/src/paraglide/messages/cli_device_start_failed.js
1499
2631
  /** @typedef {import('../runtime.js').LocalizedString} LocalizedString */
1500
- /** @typedef {{ siteId: NonNullable<unknown> }} Cli_Deploy_Site_MismatchInputs */
1501
- const ko_cli_deploy_site_mismatch = (i) => {
1502
- return `이 폴더의 사이트(${i?.siteId})가 상점의 지금 사이트와 다릅니다. npx sayren pull로 다시 받으십시오`;
2632
+ /** @typedef {{ status: NonNullable<unknown> }} Cli_Device_Start_FailedInputs */
2633
+ const ko_cli_device_start_failed = (i) => {
2634
+ return `기기 로그인을 시작하지 못했습니다(HTTP ${i?.status})`;
1503
2635
  };
1504
2636
  /**
1505
2637
 
1506
- * @param {Cli_Deploy_Site_MismatchInputs} inputs
2638
+ * @param {Cli_Device_Start_FailedInputs} inputs
1507
2639
  * @param {{ locale?: "ko" }} options
1508
2640
  * @returns {LocalizedString}
1509
2641
  */
1510
- const cli_deploy_site_mismatch = ((inputs, options = {}) => {
2642
+ const cli_device_start_failed = ((inputs, options = {}) => {
1511
2643
  experimentalStaticLocale ?? options.locale ?? getLocale();
1512
- return ko_cli_deploy_site_mismatch(inputs);
2644
+ return ko_cli_device_start_failed(inputs);
1513
2645
  });
1514
2646
 
1515
2647
  //#endregion
1516
- //#region ../i18n/src/paraglide/messages/cli_deploy_source_approval.js
2648
+ //#region ../i18n/src/paraglide/messages/cli_edit_session_open.js
1517
2649
  /** @typedef {import('../runtime.js').LocalizedString} LocalizedString */
1518
- /** @typedef {{}} Cli_Deploy_Source_ApprovalInputs */
1519
- const ko_cli_deploy_source_approval = () => {
1520
- return `작업 트리 바꾸기는 승인이 필요합니다(에이전트 토큰이 package.json·vite.config.ts를 바꿉니다). 승인된 뒤 npx sayren deploy를 다시 돌리면 빌드·발행합니다`;
2650
+ /** @typedef {{}} Cli_Edit_Session_OpenInputs */
2651
+ const ko_cli_edit_session_open = () => {
2652
+ return `상점 플랫폼·AI 편집 환경이 열려 있어 올리지 않았습니다. 편집을 끝낸 뒤 다시 시도하거나 --force로 편집 환경을 끄고 진행하십시오`;
1521
2653
  };
1522
2654
  /**
1523
2655
 
1524
- * @param {Cli_Deploy_Source_ApprovalInputs} inputs
2656
+ * @param {Cli_Edit_Session_OpenInputs} inputs
1525
2657
  * @param {{ locale?: "ko" }} options
1526
2658
  * @returns {LocalizedString}
1527
2659
  */
1528
- const cli_deploy_source_approval = ((inputs = {}, options = {}) => {
2660
+ const cli_edit_session_open = ((inputs = {}, options = {}) => {
1529
2661
  experimentalStaticLocale ?? options.locale ?? getLocale();
1530
- return ko_cli_deploy_source_approval(inputs);
2662
+ return ko_cli_edit_session_open(inputs);
1531
2663
  });
1532
2664
 
1533
2665
  //#endregion
1534
- //#region ../i18n/src/paraglide/messages/cli_deploy_source_changed_after_upload.js
2666
+ //#region ../i18n/src/paraglide/messages/cli_error_api_unreachable.js
1535
2667
  /** @typedef {import('../runtime.js').LocalizedString} LocalizedString */
1536
- /** @typedef {{}} Cli_Deploy_Source_Changed_After_UploadInputs */
1537
- const ko_cli_deploy_source_changed_after_upload = () => {
1538
- return `올린 직후 다른 편집이 끼어 버전을 만들지 않았습니다. npx sayren pull --force로 받아 합친 뒤 다시 배포하십시오`;
2668
+ /** @typedef {{}} Cli_Error_Api_UnreachableInputs */
2669
+ const ko_cli_error_api_unreachable = () => {
2670
+ return `api에 연결하지 못했습니다. 네트워크와 --api-origin을 확인하십시오`;
1539
2671
  };
1540
2672
  /**
1541
2673
 
1542
- * @param {Cli_Deploy_Source_Changed_After_UploadInputs} inputs
2674
+ * @param {Cli_Error_Api_UnreachableInputs} inputs
1543
2675
  * @param {{ locale?: "ko" }} options
1544
2676
  * @returns {LocalizedString}
1545
2677
  */
1546
- const cli_deploy_source_changed_after_upload = ((inputs = {}, options = {}) => {
2678
+ const cli_error_api_unreachable = ((inputs = {}, options = {}) => {
1547
2679
  experimentalStaticLocale ?? options.locale ?? getLocale();
1548
- return ko_cli_deploy_source_changed_after_upload(inputs);
2680
+ return ko_cli_error_api_unreachable(inputs);
1549
2681
  });
1550
2682
 
1551
2683
  //#endregion
1552
- //#region ../i18n/src/paraglide/messages/cli_deploy_unchanged.js
2684
+ //#region ../i18n/src/paraglide/messages/cli_error_insufficient_scope.js
1553
2685
  /** @typedef {import('../runtime.js').LocalizedString} LocalizedString */
1554
- /** @typedef {{}} Cli_Deploy_UnchangedInputs */
1555
- const ko_cli_deploy_unchanged = () => {
1556
- return `작업 트리가 원격과 같습니다 — 그대로 빌드합니다`;
2686
+ /** @typedef {{}} Cli_Error_Insufficient_ScopeInputs */
2687
+ const ko_cli_error_insufficient_scope = () => {
2688
+ return `토큰에 storefront:rw 스코프가 없습니다. 스코프를 더한 토큰을 쓰십시오`;
1557
2689
  };
1558
2690
  /**
1559
2691
 
1560
- * @param {Cli_Deploy_UnchangedInputs} inputs
2692
+ * @param {Cli_Error_Insufficient_ScopeInputs} inputs
1561
2693
  * @param {{ locale?: "ko" }} options
1562
2694
  * @returns {LocalizedString}
1563
2695
  */
1564
- const cli_deploy_unchanged = ((inputs = {}, options = {}) => {
2696
+ const cli_error_insufficient_scope = ((inputs = {}, options = {}) => {
1565
2697
  experimentalStaticLocale ?? options.locale ?? getLocale();
1566
- return ko_cli_deploy_unchanged(inputs);
2698
+ return ko_cli_error_insufficient_scope(inputs);
1567
2699
  });
1568
2700
 
1569
2701
  //#endregion
1570
- //#region ../i18n/src/paraglide/messages/cli_deploy_uploaded.js
2702
+ //#region ../i18n/src/paraglide/messages/cli_error_prefix.js
1571
2703
  /** @typedef {import('../runtime.js').LocalizedString} LocalizedString */
1572
- /** @typedef {{ files: NonNullable<unknown> }} Cli_Deploy_UploadedInputs */
1573
- const ko_cli_deploy_uploaded = (i) => {
1574
- return `작업 트리 올림 — ${i?.files}개 파일`;
2704
+ /** @typedef {{ message: NonNullable<unknown> }} Cli_Error_PrefixInputs */
2705
+ const ko_cli_error_prefix = (i) => {
2706
+ return `오류: ${i?.message}`;
2707
+ };
2708
+ /**
2709
+
2710
+ * @param {Cli_Error_PrefixInputs} inputs
2711
+ * @param {{ locale?: "ko" }} options
2712
+ * @returns {LocalizedString}
2713
+ */
2714
+ const cli_error_prefix = ((inputs, options = {}) => {
2715
+ experimentalStaticLocale ?? options.locale ?? getLocale();
2716
+ return ko_cli_error_prefix(inputs);
2717
+ });
2718
+
2719
+ //#endregion
2720
+ //#region ../i18n/src/paraglide/messages/cli_error_store_not_granted.js
2721
+ /** @typedef {import('../runtime.js').LocalizedString} LocalizedString */
2722
+ /** @typedef {{}} Cli_Error_Store_Not_GrantedInputs */
2723
+ const ko_cli_error_store_not_granted = () => {
2724
+ return `이 토큰의 상점 범위 밖입니다. 그 상점을 포함해 다시 로그인하십시오(npx sayren login)`;
2725
+ };
2726
+ /**
2727
+
2728
+ * @param {Cli_Error_Store_Not_GrantedInputs} inputs
2729
+ * @param {{ locale?: "ko" }} options
2730
+ * @returns {LocalizedString}
2731
+ */
2732
+ const cli_error_store_not_granted = ((inputs = {}, options = {}) => {
2733
+ experimentalStaticLocale ?? options.locale ?? getLocale();
2734
+ return ko_cli_error_store_not_granted(inputs);
2735
+ });
2736
+
2737
+ //#endregion
2738
+ //#region ../i18n/src/paraglide/messages/cli_error_too_many_requests.js
2739
+ /** @typedef {import('../runtime.js').LocalizedString} LocalizedString */
2740
+ /** @typedef {{}} Cli_Error_Too_Many_RequestsInputs */
2741
+ const ko_cli_error_too_many_requests = () => {
2742
+ return `요청이 너무 많습니다. 잠시 뒤 다시 시도하십시오`;
2743
+ };
2744
+ /**
2745
+
2746
+ * @param {Cli_Error_Too_Many_RequestsInputs} inputs
2747
+ * @param {{ locale?: "ko" }} options
2748
+ * @returns {LocalizedString}
2749
+ */
2750
+ const cli_error_too_many_requests = ((inputs = {}, options = {}) => {
2751
+ experimentalStaticLocale ?? options.locale ?? getLocale();
2752
+ return ko_cli_error_too_many_requests(inputs);
2753
+ });
2754
+
2755
+ //#endregion
2756
+ //#region ../i18n/src/paraglide/messages/cli_error_unauthorized.js
2757
+ /** @typedef {import('../runtime.js').LocalizedString} LocalizedString */
2758
+ /** @typedef {{}} Cli_Error_UnauthorizedInputs */
2759
+ const ko_cli_error_unauthorized = () => {
2760
+ return `토큰이 올바르지 않거나 만료됐습니다(401). npx sayren login으로 다시 로그인하거나 새 액세스 토큰을 쓰십시오`;
2761
+ };
2762
+ /**
2763
+
2764
+ * @param {Cli_Error_UnauthorizedInputs} inputs
2765
+ * @param {{ locale?: "ko" }} options
2766
+ * @returns {LocalizedString}
2767
+ */
2768
+ const cli_error_unauthorized = ((inputs = {}, options = {}) => {
2769
+ experimentalStaticLocale ?? options.locale ?? getLocale();
2770
+ return ko_cli_error_unauthorized(inputs);
2771
+ });
2772
+
2773
+ //#endregion
2774
+ //#region ../i18n/src/paraglide/messages/cli_finding_advisory.js
2775
+ /** @typedef {import('../runtime.js').LocalizedString} LocalizedString */
2776
+ /** @typedef {{}} Cli_Finding_AdvisoryInputs */
2777
+ const ko_cli_finding_advisory = () => {
2778
+ return `권고`;
2779
+ };
2780
+ /**
2781
+
2782
+ * @param {Cli_Finding_AdvisoryInputs} inputs
2783
+ * @param {{ locale?: "ko" }} options
2784
+ * @returns {LocalizedString}
2785
+ */
2786
+ const cli_finding_advisory = ((inputs = {}, options = {}) => {
2787
+ experimentalStaticLocale ?? options.locale ?? getLocale();
2788
+ return ko_cli_finding_advisory(inputs);
2789
+ });
2790
+
2791
+ //#endregion
2792
+ //#region ../i18n/src/paraglide/messages/cli_finding_violation.js
2793
+ /** @typedef {import('../runtime.js').LocalizedString} LocalizedString */
2794
+ /** @typedef {{}} Cli_Finding_ViolationInputs */
2795
+ const ko_cli_finding_violation = () => {
2796
+ return `위반`;
1575
2797
  };
1576
2798
  /**
1577
2799
 
1578
- * @param {Cli_Deploy_UploadedInputs} inputs
2800
+ * @param {Cli_Finding_ViolationInputs} inputs
1579
2801
  * @param {{ locale?: "ko" }} options
1580
2802
  * @returns {LocalizedString}
1581
2803
  */
1582
- const cli_deploy_uploaded = ((inputs, options = {}) => {
2804
+ const cli_finding_violation = ((inputs = {}, options = {}) => {
1583
2805
  experimentalStaticLocale ?? options.locale ?? getLocale();
1584
- return ko_cli_deploy_uploaded(inputs);
2806
+ return ko_cli_finding_violation(inputs);
1585
2807
  });
1586
2808
 
1587
2809
  //#endregion
1588
- //#region ../i18n/src/paraglide/messages/cli_deploy_uploaded_edit_ended.js
2810
+ //#region ../i18n/src/paraglide/messages/cli_flag_value_required.js
1589
2811
  /** @typedef {import('../runtime.js').LocalizedString} LocalizedString */
1590
- /** @typedef {{ files: NonNullable<unknown> }} Cli_Deploy_Uploaded_Edit_EndedInputs */
1591
- const ko_cli_deploy_uploaded_edit_ended = (i) => {
1592
- return `작업 트리 올림 — ${i?.files}개 파일(열린 편집 환경을 껐습니다)`;
2812
+ /** @typedef {{ name: NonNullable<unknown> }} Cli_Flag_Value_RequiredInputs */
2813
+ const ko_cli_flag_value_required = (i) => {
2814
+ return `--${i?.name}에 값이 필요합니다`;
1593
2815
  };
1594
2816
  /**
1595
2817
 
1596
- * @param {Cli_Deploy_Uploaded_Edit_EndedInputs} inputs
2818
+ * @param {Cli_Flag_Value_RequiredInputs} inputs
1597
2819
  * @param {{ locale?: "ko" }} options
1598
2820
  * @returns {LocalizedString}
1599
2821
  */
1600
- const cli_deploy_uploaded_edit_ended = ((inputs, options = {}) => {
2822
+ const cli_flag_value_required = ((inputs, options = {}) => {
1601
2823
  experimentalStaticLocale ?? options.locale ?? getLocale();
1602
- return ko_cli_deploy_uploaded_edit_ended(inputs);
2824
+ return ko_cli_flag_value_required(inputs);
1603
2825
  });
1604
2826
 
1605
2827
  //#endregion
1606
- //#region ../i18n/src/paraglide/messages/cli_device_code.js
2828
+ //#region ../i18n/src/paraglide/messages/cli_init_confirm.js
1607
2829
  /** @typedef {import('../runtime.js').LocalizedString} LocalizedString */
1608
- /** @typedef {{ code: NonNullable<unknown> }} Cli_Device_CodeInputs */
1609
- const ko_cli_device_code = (i) => {
1610
- return `코드: ${i?.code}`;
2830
+ /** @typedef {{}} Cli_Init_ConfirmInputs */
2831
+ const ko_cli_init_confirm = () => {
2832
+ return `사이트를 만드시겠습니까?`;
1611
2833
  };
1612
2834
  /**
1613
2835
 
1614
- * @param {Cli_Device_CodeInputs} inputs
2836
+ * @param {Cli_Init_ConfirmInputs} inputs
1615
2837
  * @param {{ locale?: "ko" }} options
1616
2838
  * @returns {LocalizedString}
1617
2839
  */
1618
- const cli_device_code = ((inputs, options = {}) => {
2840
+ const cli_init_confirm = ((inputs = {}, options = {}) => {
1619
2841
  experimentalStaticLocale ?? options.locale ?? getLocale();
1620
- return ko_cli_device_code(inputs);
2842
+ return ko_cli_init_confirm(inputs);
1621
2843
  });
1622
2844
 
1623
2845
  //#endregion
1624
- //#region ../i18n/src/paraglide/messages/cli_device_denied.js
2846
+ //#region ../i18n/src/paraglide/messages/cli_init_created.js
1625
2847
  /** @typedef {import('../runtime.js').LocalizedString} LocalizedString */
1626
- /** @typedef {{}} Cli_Device_DeniedInputs */
1627
- const ko_cli_device_denied = () => {
1628
- return `기기 연결을 거부했습니다`;
2848
+ /** @typedef {{ url: NonNullable<unknown> }} Cli_Init_CreatedInputs */
2849
+ const ko_cli_init_created = (i) => {
2850
+ return `사이트를 만들었습니다 — ${i?.url} (오픈 준비 중, 반영까지 1분 안팎)`;
1629
2851
  };
1630
2852
  /**
1631
2853
 
1632
- * @param {Cli_Device_DeniedInputs} inputs
2854
+ * @param {Cli_Init_CreatedInputs} inputs
1633
2855
  * @param {{ locale?: "ko" }} options
1634
2856
  * @returns {LocalizedString}
1635
2857
  */
1636
- const cli_device_denied = ((inputs = {}, options = {}) => {
2858
+ const cli_init_created = ((inputs, options = {}) => {
1637
2859
  experimentalStaticLocale ?? options.locale ?? getLocale();
1638
- return ko_cli_device_denied(inputs);
2860
+ return ko_cli_init_created(inputs);
1639
2861
  });
1640
2862
 
1641
2863
  //#endregion
1642
- //#region ../i18n/src/paraglide/messages/cli_device_expired.js
2864
+ //#region ../i18n/src/paraglide/messages/cli_init_dir_not_empty.js
1643
2865
  /** @typedef {import('../runtime.js').LocalizedString} LocalizedString */
1644
- /** @typedef {{}} Cli_Device_ExpiredInputs */
1645
- const ko_cli_device_expired = () => {
1646
- return `코드가 만료됐습니다. 다시 로그인하십시오`;
2866
+ /** @typedef {{ dir: NonNullable<unknown> }} Cli_Init_Dir_Not_EmptyInputs */
2867
+ const ko_cli_init_dir_not_empty = (i) => {
2868
+ return `폴더가 비어 있지 않습니다: ${i?.dir}. 빈 폴더나 새 폴더 이름을 주십시오`;
1647
2869
  };
1648
2870
  /**
1649
2871
 
1650
- * @param {Cli_Device_ExpiredInputs} inputs
2872
+ * @param {Cli_Init_Dir_Not_EmptyInputs} inputs
1651
2873
  * @param {{ locale?: "ko" }} options
1652
2874
  * @returns {LocalizedString}
1653
2875
  */
1654
- const cli_device_expired = ((inputs = {}, options = {}) => {
2876
+ const cli_init_dir_not_empty = ((inputs, options = {}) => {
1655
2877
  experimentalStaticLocale ?? options.locale ?? getLocale();
1656
- return ko_cli_device_expired(inputs);
2878
+ return ko_cli_init_dir_not_empty(inputs);
1657
2879
  });
1658
2880
 
1659
2881
  //#endregion
1660
- //#region ../i18n/src/paraglide/messages/cli_device_failed.js
2882
+ //#region ../i18n/src/paraglide/messages/cli_init_hosting_disabled.js
1661
2883
  /** @typedef {import('../runtime.js').LocalizedString} LocalizedString */
1662
- /** @typedef {{ error: NonNullable<unknown> }} Cli_Device_FailedInputs */
1663
- const ko_cli_device_failed = (i) => {
1664
- return `기기 로그인을 마치지 못했습니다(${i?.error})`;
2884
+ /** @typedef {{}} Cli_Init_Hosting_DisabledInputs */
2885
+ const ko_cli_init_hosting_disabled = () => {
2886
+ return `지금은 새 호스팅 사이트를 만들 수 없습니다(호스팅 기능이 꺼져 있습니다)`;
1665
2887
  };
1666
2888
  /**
1667
2889
 
1668
- * @param {Cli_Device_FailedInputs} inputs
2890
+ * @param {Cli_Init_Hosting_DisabledInputs} inputs
1669
2891
  * @param {{ locale?: "ko" }} options
1670
2892
  * @returns {LocalizedString}
1671
2893
  */
1672
- const cli_device_failed = ((inputs, options = {}) => {
2894
+ const cli_init_hosting_disabled = ((inputs = {}, options = {}) => {
1673
2895
  experimentalStaticLocale ?? options.locale ?? getLocale();
1674
- return ko_cli_device_failed(inputs);
2896
+ return ko_cli_init_hosting_disabled(inputs);
1675
2897
  });
1676
2898
 
1677
2899
  //#endregion
1678
- //#region ../i18n/src/paraglide/messages/cli_device_prompt.js
2900
+ //#region ../i18n/src/paraglide/messages/cli_init_inside_pulled.js
1679
2901
  /** @typedef {import('../runtime.js').LocalizedString} LocalizedString */
1680
- /** @typedef {{}} Cli_Device_PromptInputs */
1681
- const ko_cli_device_prompt = () => {
1682
- return `다른 기기의 브라우저에서 아래 주소를 열고 코드를 확인하십시오:`;
2902
+ /** @typedef {{}} Cli_Init_Inside_PulledInputs */
2903
+ const ko_cli_init_inside_pulled = () => {
2904
+ return `지금 폴더는 이미 받은 사이트 폴더입니다. 새 사이트는 다른 폴더에서 npx sayren init <폴더>로 만들고, 이 사이트를 다시 받으려면 npx sayren pull --force를 쓰십시오`;
1683
2905
  };
1684
2906
  /**
1685
2907
 
1686
- * @param {Cli_Device_PromptInputs} inputs
2908
+ * @param {Cli_Init_Inside_PulledInputs} inputs
1687
2909
  * @param {{ locale?: "ko" }} options
1688
2910
  * @returns {LocalizedString}
1689
2911
  */
1690
- const cli_device_prompt = ((inputs = {}, options = {}) => {
2912
+ const cli_init_inside_pulled = ((inputs = {}, options = {}) => {
1691
2913
  experimentalStaticLocale ?? options.locale ?? getLocale();
1692
- return ko_cli_device_prompt(inputs);
2914
+ return ko_cli_init_inside_pulled(inputs);
1693
2915
  });
1694
2916
 
1695
2917
  //#endregion
1696
- //#region ../i18n/src/paraglide/messages/cli_device_start_failed.js
2918
+ //#region ../i18n/src/paraglide/messages/cli_init_no_templates.js
1697
2919
  /** @typedef {import('../runtime.js').LocalizedString} LocalizedString */
1698
- /** @typedef {{ status: NonNullable<unknown> }} Cli_Device_Start_FailedInputs */
1699
- const ko_cli_device_start_failed = (i) => {
1700
- return `기기 로그인을 시작하지 못했습니다(HTTP ${i?.status})`;
2920
+ /** @typedef {{}} Cli_Init_No_TemplatesInputs */
2921
+ const ko_cli_init_no_templates = () => {
2922
+ return `쓸 수 있는 템플릿이 없습니다`;
1701
2923
  };
1702
2924
  /**
1703
2925
 
1704
- * @param {Cli_Device_Start_FailedInputs} inputs
2926
+ * @param {Cli_Init_No_TemplatesInputs} inputs
1705
2927
  * @param {{ locale?: "ko" }} options
1706
2928
  * @returns {LocalizedString}
1707
2929
  */
1708
- const cli_device_start_failed = ((inputs, options = {}) => {
2930
+ const cli_init_no_templates = ((inputs = {}, options = {}) => {
1709
2931
  experimentalStaticLocale ?? options.locale ?? getLocale();
1710
- return ko_cli_device_start_failed(inputs);
2932
+ return ko_cli_init_no_templates(inputs);
1711
2933
  });
1712
2934
 
1713
2935
  //#endregion
1714
- //#region ../i18n/src/paraglide/messages/cli_edit_session_open.js
2936
+ //#region ../i18n/src/paraglide/messages/cli_init_pull_failed.js
1715
2937
  /** @typedef {import('../runtime.js').LocalizedString} LocalizedString */
1716
- /** @typedef {{}} Cli_Edit_Session_OpenInputs */
1717
- const ko_cli_edit_session_open = () => {
1718
- return `상점 플랫폼·AI 편집 환경이 열려 있어 올리지 않았습니다. 편집을 끝낸 뒤 다시 시도하거나 --force로 편집 환경을 끄고 진행하십시오`;
2938
+ /** @typedef {{ storeId: NonNullable<unknown> }} Cli_Init_Pull_FailedInputs */
2939
+ const ko_cli_init_pull_failed = (i) => {
2940
+ return `사이트는 만들었지만 소스를 받지 못했습니다. 다시 만들지 말고 npx sayren pull --project ${i?.storeId}로 받으십시오`;
1719
2941
  };
1720
2942
  /**
1721
2943
 
1722
- * @param {Cli_Edit_Session_OpenInputs} inputs
2944
+ * @param {Cli_Init_Pull_FailedInputs} inputs
1723
2945
  * @param {{ locale?: "ko" }} options
1724
2946
  * @returns {LocalizedString}
1725
2947
  */
1726
- const cli_edit_session_open = ((inputs = {}, options = {}) => {
2948
+ const cli_init_pull_failed = ((inputs, options = {}) => {
1727
2949
  experimentalStaticLocale ?? options.locale ?? getLocale();
1728
- return ko_cli_edit_session_open(inputs);
2950
+ return ko_cli_init_pull_failed(inputs);
1729
2951
  });
1730
2952
 
1731
2953
  //#endregion
1732
- //#region ../i18n/src/paraglide/messages/cli_error_api_unreachable.js
2954
+ //#region ../i18n/src/paraglide/messages/cli_init_site_exists.js
1733
2955
  /** @typedef {import('../runtime.js').LocalizedString} LocalizedString */
1734
- /** @typedef {{}} Cli_Error_Api_UnreachableInputs */
1735
- const ko_cli_error_api_unreachable = () => {
1736
- return `api에 연결하지 못했습니다. 네트워크와 --api-origin을 확인하십시오`;
2956
+ /** @typedef {{ storeId: NonNullable<unknown> }} Cli_Init_Site_ExistsInputs */
2957
+ const ko_cli_init_site_exists = (i) => {
2958
+ return `이 상점에는 이미 호스팅 사이트가 있어 새로 만들지 않았습니다. npx sayren pull --project ${i?.storeId}로 소스를 받으십시오`;
1737
2959
  };
1738
2960
  /**
1739
2961
 
1740
- * @param {Cli_Error_Api_UnreachableInputs} inputs
2962
+ * @param {Cli_Init_Site_ExistsInputs} inputs
1741
2963
  * @param {{ locale?: "ko" }} options
1742
2964
  * @returns {LocalizedString}
1743
2965
  */
1744
- const cli_error_api_unreachable = ((inputs = {}, options = {}) => {
2966
+ const cli_init_site_exists = ((inputs, options = {}) => {
1745
2967
  experimentalStaticLocale ?? options.locale ?? getLocale();
1746
- return ko_cli_error_api_unreachable(inputs);
2968
+ return ko_cli_init_site_exists(inputs);
1747
2969
  });
1748
2970
 
1749
2971
  //#endregion
1750
- //#region ../i18n/src/paraglide/messages/cli_error_insufficient_scope.js
2972
+ //#region ../i18n/src/paraglide/messages/cli_init_site_url.js
1751
2973
  /** @typedef {import('../runtime.js').LocalizedString} LocalizedString */
1752
- /** @typedef {{}} Cli_Error_Insufficient_ScopeInputs */
1753
- const ko_cli_error_insufficient_scope = () => {
1754
- return `토큰에 storefront:rw 스코프가 없습니다. 스코프를 더한 토큰을 쓰십시오`;
2974
+ /** @typedef {{ url: NonNullable<unknown> }} Cli_Init_Site_UrlInputs */
2975
+ const ko_cli_init_site_url = (i) => {
2976
+ return `지금 사이트: ${i?.url}`;
1755
2977
  };
1756
2978
  /**
1757
2979
 
1758
- * @param {Cli_Error_Insufficient_ScopeInputs} inputs
2980
+ * @param {Cli_Init_Site_UrlInputs} inputs
1759
2981
  * @param {{ locale?: "ko" }} options
1760
2982
  * @returns {LocalizedString}
1761
2983
  */
1762
- const cli_error_insufficient_scope = ((inputs = {}, options = {}) => {
2984
+ const cli_init_site_url = ((inputs, options = {}) => {
1763
2985
  experimentalStaticLocale ?? options.locale ?? getLocale();
1764
- return ko_cli_error_insufficient_scope(inputs);
2986
+ return ko_cli_init_site_url(inputs);
1765
2987
  });
1766
2988
 
1767
2989
  //#endregion
1768
- //#region ../i18n/src/paraglide/messages/cli_error_prefix.js
2990
+ //#region ../i18n/src/paraglide/messages/cli_init_slug_taken.js
1769
2991
  /** @typedef {import('../runtime.js').LocalizedString} LocalizedString */
1770
- /** @typedef {{ message: NonNullable<unknown> }} Cli_Error_PrefixInputs */
1771
- const ko_cli_error_prefix = (i) => {
1772
- return `오류: ${i?.message}`;
2992
+ /** @typedef {{}} Cli_Init_Slug_TakenInputs */
2993
+ const ko_cli_init_slug_taken = () => {
2994
+ return `상점 코드와 같은 주소를 다른 사이트가 쓰고 있어 만들지 못했습니다. 상점 플랫폼 › 스토어프론트에서 다른 주소로 만든 뒤 npx sayren pull로 받으십시오`;
1773
2995
  };
1774
2996
  /**
1775
2997
 
1776
- * @param {Cli_Error_PrefixInputs} inputs
2998
+ * @param {Cli_Init_Slug_TakenInputs} inputs
1777
2999
  * @param {{ locale?: "ko" }} options
1778
3000
  * @returns {LocalizedString}
1779
3001
  */
1780
- const cli_error_prefix = ((inputs, options = {}) => {
3002
+ const cli_init_slug_taken = ((inputs = {}, options = {}) => {
1781
3003
  experimentalStaticLocale ?? options.locale ?? getLocale();
1782
- return ko_cli_error_prefix(inputs);
3004
+ return ko_cli_init_slug_taken(inputs);
1783
3005
  });
1784
3006
 
1785
3007
  //#endregion
1786
- //#region ../i18n/src/paraglide/messages/cli_error_store_not_granted.js
3008
+ //#region ../i18n/src/paraglide/messages/cli_init_summary.js
1787
3009
  /** @typedef {import('../runtime.js').LocalizedString} LocalizedString */
1788
- /** @typedef {{}} Cli_Error_Store_Not_GrantedInputs */
1789
- const ko_cli_error_store_not_granted = () => {
1790
- return `이 토큰의 상점 범위 밖입니다. 그 상점을 포함해 다시 로그인하십시오(npx sayren login)`;
3010
+ /** @typedef {{ storeId: NonNullable<unknown>, name: NonNullable<unknown>, templateId: NonNullable<unknown>, version: NonNullable<unknown> }} Cli_Init_SummaryInputs */
3011
+ const ko_cli_init_summary = (i) => {
3012
+ return `상점 ${i?.storeId}에 템플릿 ${i?.name}(${i?.templateId} v${i?.version})로 호스팅 사이트를 만듭니다. 주소는 상점 코드이고 오픈 준비 중으로 시작합니다. 만들기는 상점당 30일에 3번까지입니다`;
1791
3013
  };
1792
3014
  /**
1793
3015
 
1794
- * @param {Cli_Error_Store_Not_GrantedInputs} inputs
3016
+ * @param {Cli_Init_SummaryInputs} inputs
1795
3017
  * @param {{ locale?: "ko" }} options
1796
3018
  * @returns {LocalizedString}
1797
3019
  */
1798
- const cli_error_store_not_granted = ((inputs = {}, options = {}) => {
3020
+ const cli_init_summary = ((inputs, options = {}) => {
1799
3021
  experimentalStaticLocale ?? options.locale ?? getLocale();
1800
- return ko_cli_error_store_not_granted(inputs);
3022
+ return ko_cli_init_summary(inputs);
1801
3023
  });
1802
3024
 
1803
3025
  //#endregion
1804
- //#region ../i18n/src/paraglide/messages/cli_error_too_many_requests.js
3026
+ //#region ../i18n/src/paraglide/messages/cli_init_template_option.js
1805
3027
  /** @typedef {import('../runtime.js').LocalizedString} LocalizedString */
1806
- /** @typedef {{}} Cli_Error_Too_Many_RequestsInputs */
1807
- const ko_cli_error_too_many_requests = () => {
1808
- return `요청이 너무 많습니다. 잠시 뒤 다시 시도하십시오`;
3028
+ /** @typedef {{ templateId: NonNullable<unknown>, name: NonNullable<unknown>, version: NonNullable<unknown>, description: NonNullable<unknown> }} Cli_Init_Template_OptionInputs */
3029
+ const ko_cli_init_template_option = (i) => {
3030
+ return `${i?.templateId} — ${i?.name} v${i?.version}: ${i?.description}`;
1809
3031
  };
1810
3032
  /**
1811
3033
 
1812
- * @param {Cli_Error_Too_Many_RequestsInputs} inputs
3034
+ * @param {Cli_Init_Template_OptionInputs} inputs
1813
3035
  * @param {{ locale?: "ko" }} options
1814
3036
  * @returns {LocalizedString}
1815
3037
  */
1816
- const cli_error_too_many_requests = ((inputs = {}, options = {}) => {
3038
+ const cli_init_template_option = ((inputs, options = {}) => {
1817
3039
  experimentalStaticLocale ?? options.locale ?? getLocale();
1818
- return ko_cli_error_too_many_requests(inputs);
3040
+ return ko_cli_init_template_option(inputs);
1819
3041
  });
1820
3042
 
1821
3043
  //#endregion
1822
- //#region ../i18n/src/paraglide/messages/cli_error_unauthorized.js
3044
+ //#region ../i18n/src/paraglide/messages/cli_init_template_prompt.js
1823
3045
  /** @typedef {import('../runtime.js').LocalizedString} LocalizedString */
1824
- /** @typedef {{}} Cli_Error_UnauthorizedInputs */
1825
- const ko_cli_error_unauthorized = () => {
1826
- return `토큰이 올바르지 않거나 만료됐습니다(401). npx sayren login으로 다시 로그인하거나 새 액세스 토큰을 쓰십시오`;
3046
+ /** @typedef {{}} Cli_Init_Template_PromptInputs */
3047
+ const ko_cli_init_template_prompt = () => {
3048
+ return `템플릿을 고르십시오:`;
1827
3049
  };
1828
3050
  /**
1829
3051
 
1830
- * @param {Cli_Error_UnauthorizedInputs} inputs
3052
+ * @param {Cli_Init_Template_PromptInputs} inputs
1831
3053
  * @param {{ locale?: "ko" }} options
1832
3054
  * @returns {LocalizedString}
1833
3055
  */
1834
- const cli_error_unauthorized = ((inputs = {}, options = {}) => {
3056
+ const cli_init_template_prompt = ((inputs = {}, options = {}) => {
1835
3057
  experimentalStaticLocale ?? options.locale ?? getLocale();
1836
- return ko_cli_error_unauthorized(inputs);
3058
+ return ko_cli_init_template_prompt(inputs);
1837
3059
  });
1838
3060
 
1839
3061
  //#endregion
1840
- //#region ../i18n/src/paraglide/messages/cli_finding_advisory.js
3062
+ //#region ../i18n/src/paraglide/messages/cli_init_template_required.js
1841
3063
  /** @typedef {import('../runtime.js').LocalizedString} LocalizedString */
1842
- /** @typedef {{}} Cli_Finding_AdvisoryInputs */
1843
- const ko_cli_finding_advisory = () => {
1844
- return `권고`;
3064
+ /** @typedef {{ list: NonNullable<unknown> }} Cli_Init_Template_RequiredInputs */
3065
+ const ko_cli_init_template_required = (i) => {
3066
+ return `템플릿을 고르지 않았습니다. --template <id>로 주십시오(비대화형은 필수입니다):
3067
+ ${i?.list}`;
1845
3068
  };
1846
3069
  /**
1847
3070
 
1848
- * @param {Cli_Finding_AdvisoryInputs} inputs
3071
+ * @param {Cli_Init_Template_RequiredInputs} inputs
1849
3072
  * @param {{ locale?: "ko" }} options
1850
3073
  * @returns {LocalizedString}
1851
3074
  */
1852
- const cli_finding_advisory = ((inputs = {}, options = {}) => {
3075
+ const cli_init_template_required = ((inputs, options = {}) => {
1853
3076
  experimentalStaticLocale ?? options.locale ?? getLocale();
1854
- return ko_cli_finding_advisory(inputs);
3077
+ return ko_cli_init_template_required(inputs);
1855
3078
  });
1856
3079
 
1857
3080
  //#endregion
1858
- //#region ../i18n/src/paraglide/messages/cli_finding_violation.js
3081
+ //#region ../i18n/src/paraglide/messages/cli_init_template_unknown.js
1859
3082
  /** @typedef {import('../runtime.js').LocalizedString} LocalizedString */
1860
- /** @typedef {{}} Cli_Finding_ViolationInputs */
1861
- const ko_cli_finding_violation = () => {
1862
- return `위반`;
3083
+ /** @typedef {{ templateId: NonNullable<unknown>, ids: NonNullable<unknown> }} Cli_Init_Template_UnknownInputs */
3084
+ const ko_cli_init_template_unknown = (i) => {
3085
+ return `템플릿을 찾지 못했습니다: ${i?.templateId}. 쓸 수 있는 템플릿: ${i?.ids}`;
1863
3086
  };
1864
3087
  /**
1865
3088
 
1866
- * @param {Cli_Finding_ViolationInputs} inputs
3089
+ * @param {Cli_Init_Template_UnknownInputs} inputs
1867
3090
  * @param {{ locale?: "ko" }} options
1868
3091
  * @returns {LocalizedString}
1869
3092
  */
1870
- const cli_finding_violation = ((inputs = {}, options = {}) => {
3093
+ const cli_init_template_unknown = ((inputs, options = {}) => {
1871
3094
  experimentalStaticLocale ?? options.locale ?? getLocale();
1872
- return ko_cli_finding_violation(inputs);
3095
+ return ko_cli_init_template_unknown(inputs);
1873
3096
  });
1874
3097
 
1875
3098
  //#endregion
1876
- //#region ../i18n/src/paraglide/messages/cli_flag_value_required.js
3099
+ //#region ../i18n/src/paraglide/messages/cli_init_yes_required.js
1877
3100
  /** @typedef {import('../runtime.js').LocalizedString} LocalizedString */
1878
- /** @typedef {{ name: NonNullable<unknown> }} Cli_Flag_Value_RequiredInputs */
1879
- const ko_cli_flag_value_required = (i) => {
1880
- return `--${i?.name}에 값이 필요합니다`;
3101
+ /** @typedef {{}} Cli_Init_Yes_RequiredInputs */
3102
+ const ko_cli_init_yes_required = () => {
3103
+ return `사이트 만들기를 확인할 수 없는 환경입니다. --yes를 함께 주십시오`;
1881
3104
  };
1882
3105
  /**
1883
3106
 
1884
- * @param {Cli_Flag_Value_RequiredInputs} inputs
3107
+ * @param {Cli_Init_Yes_RequiredInputs} inputs
1885
3108
  * @param {{ locale?: "ko" }} options
1886
3109
  * @returns {LocalizedString}
1887
3110
  */
1888
- const cli_flag_value_required = ((inputs, options = {}) => {
3111
+ const cli_init_yes_required = ((inputs = {}, options = {}) => {
1889
3112
  experimentalStaticLocale ?? options.locale ?? getLocale();
1890
- return ko_cli_flag_value_required(inputs);
3113
+ return ko_cli_init_yes_required(inputs);
1891
3114
  });
1892
3115
 
1893
3116
  //#endregion
@@ -2908,7 +4131,7 @@ const cli_pull_next_steps = ((inputs, options = {}) => {
2908
4131
  /** @typedef {import('../runtime.js').LocalizedString} LocalizedString */
2909
4132
  /** @typedef {{}} Cli_Pull_No_SiteInputs */
2910
4133
  const ko_cli_pull_no_site = () => {
2911
- return `이 상점에는 호스팅 사이트가 없습니다. 상점 플랫폼 › 스토어프론트에서 사이트를 만든 뒤 다시 받으십시오`;
4134
+ return `이 상점에는 호스팅 사이트가 없습니다. npx sayren init으로 만들거나 상점 플랫폼 › 스토어프론트에서 만든 뒤 다시 받으십시오`;
2912
4135
  };
2913
4136
  /**
2914
4137
 
@@ -3894,19 +5117,23 @@ const ko_cli_usage = (i) => {
3894
5117
  npx sayren login --paste # 액세스 토큰을 입력받아 저장(셸 기록에 남지 않습니다)
3895
5118
  npx sayren logout
3896
5119
  npx sayren whoami
5120
+ npx sayren init [폴더] [--template <id>] [--store <storeId>] [--yes]
3897
5121
  npx sayren pull --project <storeId> [폴더] [--force [--yes]]
3898
- npx sayren deploy [--no-publish] [--message <메모>] [--force [--yes]]
5122
+ npx sayren deploy [--no-publish] [--skip-build] [--message <메모>] [--force [--yes]]
3899
5123
  npx sayren status
3900
5124
  npx sayren verify
5125
+ npx sayren app <명령> # 서드파티 앱(init·dev·trigger·verify·deploy·release·status·logs·secret·dev-store)
3901
5126
 
3902
5127
  명령:
3903
5128
  login Sayren 계정으로 로그인합니다. 로그인 토큰은 사용자 설정 폴더(~/.config/sayren/credentials.json)에 둡니다
3904
5129
  logout 로그인을 폐기하고 이 컴퓨터의 토큰을 지웁니다
3905
5130
  whoami 쓰는 계정·토큰 종류·상점 범위
5131
+ init 템플릿을 골라 호스팅 사이트를 만들고 pull과 같은 폴더(기본: 상점 코드)로 받습니다. 사이트가 이미 있으면 만들지 않습니다
3906
5132
  pull 호스팅 중인 사이트의 작업 트리를 폴더(기본: 상점 코드)로 받고 .mcp.json·.env·.sayren/state.json을 씁니다
3907
- deploy 로컬 검사 → 작업 트리 올리기 → 빌드 → 발행. 원격이 pull 이후 바뀌었으면 덮어쓰지 않습니다
5133
+ deploy 로컬 검사 → 로컬 빌드 → 작업 트리 올리기 → 빌드 → 발행. 원격이 pull 이후 바뀌었으면 덮어쓰지 않습니다
3908
5134
  status 사이트·발행 버전·최근 빌드·편집 환경
3909
5135
  verify 로컬 규칙·경로·크기 검사(서버 빌드와 같은 규칙)
5136
+ app 서드파티 앱 — init <handle>로 만들고 dev로 로컬 실행, deploy로 버전을 올리고 release로 적용합니다. 자세히: https://docs.sayren.app/guides/apps-getting-started
3910
5137
 
3911
5138
  토큰은 Sayren 계정 토큰만 받고 --token → SAYREN_TOKEN 환경 변수 → 로그인(credentials.json) 순서로 읽습니다.
3912
5139
  계정 토큰은 계정에 발급됩니다 — 상점은 --store → SAYREN_STORE_ID → 폴더 설정 순서로 고릅니다(하나면 자동).
@@ -3915,11 +5142,13 @@ const ko_cli_usage = (i) => {
3915
5142
 
3916
5143
  옵션:
3917
5144
  --project <storeId> pull: 받을 상점(--store와 같습니다)
3918
- --dir <폴더> 작업 폴더(기본: 지금 폴더, pull은 상점 코드)
5145
+ --template <id> init: 템플릿 id(비대화형은 필수)
5146
+ --dir <폴더> 작업 폴더(기본: 지금 폴더, pull·init은 상점 코드)
3919
5147
  --force pull: 같은 사이트를 받은 폴더에 원격을 다시 받습니다(지울·덮을 파일을 보여 주고 묻습니다)
3920
5148
  deploy: 원격 변경·열린 편집 환경을 무시하고 덮어씁니다(확인을 묻습니다)
3921
- --yes --force의 확인을 묻지 않습니다(비대화형)
5149
+ --yes --force·init의 확인을 묻지 않습니다(비대화형)
3922
5150
  --no-publish deploy: 버전까지만 만들고 발행하지 않습니다
5151
+ --skip-build deploy: 올리기 전 로컬 빌드(npm run build)를 건너뜁니다
3923
5152
  --message <메모> deploy: 버전 메모
3924
5153
  --store <storeId> 다룰 상점(SAYREN_STORE_ID)
3925
5154
  --device login: 브라우저 대신 기기 코드로 로그인합니다(SSH 등)
@@ -3927,6 +5156,14 @@ const ko_cli_usage = (i) => {
3927
5156
  --api-origin <주소> api 주소(기본 https://api.sayren.app, SAYREN_API_ORIGIN). https만, localhost만 http
3928
5157
  --accounts-origin <주소> 계정 서버 주소(기본: api 주소에 맞춘 값, SAYREN_ACCOUNTS_ORIGIN)
3929
5158
  --token <토큰> 토큰을 직접 줍니다. 셸 기록·프로세스 목록에 남으니 login·SAYREN_TOKEN을 권합니다
5159
+ --key <키> app: 앱 배포 키(developer.sayren.app에서 발행, SAYREN_APP_KEY). CI에서 deploy·release·status·logs·secret에 씁니다
5160
+ -m, --message <메모> app deploy: 버전 메모
5161
+ --name <이름> app init: 앱 이름(기본: handle)
5162
+ --port <포트> app dev·trigger: 로컬 포트(기본 4020)
5163
+ --since <기간> app logs: 최근 기간만(30m·1h·2d)
5164
+ --tail app logs: 새 기록을 계속 봅니다
5165
+ --data <json> app trigger: 이벤트 데이터
5166
+ --order <orderId> app trigger: 주문 id를 데이터에 넣습니다
3930
5167
  --lang <로케일> 메시지 언어(기본: SAYREN_LANG → 시스템 로케일 → ko)
3931
5168
 
3932
5169
  종료 코드: 0 성공 · 1 실패 · 3 승인 대기(에이전트 토큰)`;
@@ -4433,7 +5670,7 @@ const mcp_report_template_hint_local = ((inputs, options = {}) => {
4433
5670
  /** @typedef {import('../runtime.js').LocalizedString} LocalizedString */
4434
5671
  /** @typedef {{ files: NonNullable<unknown> }} Mcp_Report_Template_Hint_RemoteInputs */
4435
5672
  const ko_mcp_report_template_hint_remote = (i) => {
4436
- return `손대지 않아야 하는 파일을 고친 결과일 수 있다 — ${i?.files}을(를) \`read_file\`로 읽어 규칙의 \`example\`과 대조하고 되돌린다.`;
5673
+ return `손대지 않아야 하는 파일을 고친 결과일 수 있다 — ${i?.files}을(를) \`read_file\`로 읽어 \`get_template_file\`의 템플릿 원본(지금 카탈로그 버전)이나 규칙의 \`example\`과 대조하고 되돌린다.`;
4437
5674
  };
4438
5675
  /**
4439
5676
 
@@ -5000,7 +6237,7 @@ const mcp_rule_checkout_availability_title = ((inputs = {}, options = {}) => {
5000
6237
  /** @typedef {import('../runtime.js').LocalizedString} LocalizedString */
5001
6238
  /** @typedef {{}} Mcp_Rule_Checkout_Availability_WhyInputs */
5002
6239
  const ko_mcp_rule_checkout_availability_why = () => {
5003
- return `결제 수단이 없거나 공개한 쇼핑몰의 실결제가 아직 열리지 않은 상점은 결제 요청이 409 \`PAYMENT_NOT_CONFIGURED\`다. 버튼을 그대로 두면 구매자가 담고 주문서까지 가서야 결제가 안 된다는 것을 안다`;
6240
+ return `결제수단이 없거나 공개한 쇼핑몰의 실결제가 아직 열리지 않은 상점은 결제 요청이 409 \`PAYMENT_NOT_CONFIGURED\`다. 버튼을 그대로 두면 구매자가 담고 주문서까지 가서야 결제가 안 된다는 것을 안다`;
5004
6241
  };
5005
6242
  /**
5006
6243
 
@@ -5318,7 +6555,7 @@ const mcp_rule_local_import_exists_example = ((inputs = {}, options = {}) => {
5318
6555
  /** @typedef {import('../runtime.js').LocalizedString} LocalizedString */
5319
6556
  /** @typedef {{}} Mcp_Rule_Local_Import_Exists_FixInputs */
5320
6557
  const ko_mcp_rule_local_import_exists_fix = () => {
5321
- return `빠진 파일을 템플릿 원본(로컬 \`get_template_file\`, 또는 \`npx @sayren/mcp create\`로 받은 사본)에서 가져와 같은 경로에 둔다. 호스팅 사이트는 \`write_files\`(\`expectedHash: null\`)나 \`sayren deploy\`로 올린다. 쓰지 않는 import면 지운다. 템플릿의 화면 문구는 \`messages/ko.json\`이다`;
6558
+ return `빠진 파일을 템플릿 원본(\`get_template_file\`, 또는 \`npx @sayren/mcp create\`로 받은 사본)에서 가져와 같은 경로에 둔다. 호스팅 사이트는 \`write_files\`(\`expectedHash: null\`)나 \`sayren deploy\`로 올린다. 쓰지 않는 import면 지운다. 템플릿의 화면 문구는 \`messages/ko.json\`이다`;
5322
6559
  };
5323
6560
  /**
5324
6561
 
@@ -5877,6 +7114,82 @@ const mcp_rule_payment_return_route_why = ((inputs = {}, options = {}) => {
5877
7114
  return ko_mcp_rule_payment_return_route_why(inputs);
5878
7115
  });
5879
7116
 
7117
+ //#endregion
7118
+ //#region ../i18n/src/paraglide/messages/mcp_rule_product_link_example.js
7119
+ /** @typedef {import('../runtime.js').LocalizedString} LocalizedString */
7120
+ /** @typedef {{}} Mcp_Rule_Product_Link_ExampleInputs */
7121
+ const ko_mcp_rule_product_link_example = () => {
7122
+ return `import { productPathParam } from "../lib/product-path";
7123
+
7124
+ <Link to="/products/$productId" params={{ productId: productPathParam(product) }}>
7125
+ {product.name}
7126
+ </Link>`;
7127
+ };
7128
+ /**
7129
+
7130
+ * @param {Mcp_Rule_Product_Link_ExampleInputs} inputs
7131
+ * @param {{ locale?: "ko" }} options
7132
+ * @returns {LocalizedString}
7133
+ */
7134
+ const mcp_rule_product_link_example = ((inputs = {}, options = {}) => {
7135
+ experimentalStaticLocale ?? options.locale ?? getLocale();
7136
+ return ko_mcp_rule_product_link_example(inputs);
7137
+ });
7138
+
7139
+ //#endregion
7140
+ //#region ../i18n/src/paraglide/messages/mcp_rule_product_link_fix.js
7141
+ /** @typedef {import('../runtime.js').LocalizedString} LocalizedString */
7142
+ /** @typedef {{}} Mcp_Rule_Product_Link_FixInputs */
7143
+ const ko_mcp_rule_product_link_fix = () => {
7144
+ return `링크의 경로 값을 \`productPathParam(product)\`(\`src/lib/product-path.ts\`)로 만든다. 상품번호가 있으면 번호, 없는 옛 응답이면 상품 id다. 장바구니 담기·주문서 같은 서버 요청에는 계속 \`productId\`를 보낸다`;
7145
+ };
7146
+ /**
7147
+
7148
+ * @param {Mcp_Rule_Product_Link_FixInputs} inputs
7149
+ * @param {{ locale?: "ko" }} options
7150
+ * @returns {LocalizedString}
7151
+ */
7152
+ const mcp_rule_product_link_fix = ((inputs = {}, options = {}) => {
7153
+ experimentalStaticLocale ?? options.locale ?? getLocale();
7154
+ return ko_mcp_rule_product_link_fix(inputs);
7155
+ });
7156
+
7157
+ //#endregion
7158
+ //#region ../i18n/src/paraglide/messages/mcp_rule_product_link_title.js
7159
+ /** @typedef {import('../runtime.js').LocalizedString} LocalizedString */
7160
+ /** @typedef {{}} Mcp_Rule_Product_Link_TitleInputs */
7161
+ const ko_mcp_rule_product_link_title = () => {
7162
+ return `상품 링크는 상품번호 주소로 그린다(\`/products/{productNo}\`)`;
7163
+ };
7164
+ /**
7165
+
7166
+ * @param {Mcp_Rule_Product_Link_TitleInputs} inputs
7167
+ * @param {{ locale?: "ko" }} options
7168
+ * @returns {LocalizedString}
7169
+ */
7170
+ const mcp_rule_product_link_title = ((inputs = {}, options = {}) => {
7171
+ experimentalStaticLocale ?? options.locale ?? getLocale();
7172
+ return ko_mcp_rule_product_link_title(inputs);
7173
+ });
7174
+
7175
+ //#endregion
7176
+ //#region ../i18n/src/paraglide/messages/mcp_rule_product_link_why.js
7177
+ /** @typedef {import('../runtime.js').LocalizedString} LocalizedString */
7178
+ /** @typedef {{}} Mcp_Rule_Product_Link_WhyInputs */
7179
+ const ko_mcp_rule_product_link_why = () => {
7180
+ return `상품 주소는 상점 안에서 유일한 숫자 상품번호다. 상품 id(\`prod_…\`) 주소도 열리지만 상세 화면이 상품번호 주소로 301 이동시키므로 링크마다 왕복이 한 번 더 생기고 공유·검색 주소가 둘로 갈린다`;
7181
+ };
7182
+ /**
7183
+
7184
+ * @param {Mcp_Rule_Product_Link_WhyInputs} inputs
7185
+ * @param {{ locale?: "ko" }} options
7186
+ * @returns {LocalizedString}
7187
+ */
7188
+ const mcp_rule_product_link_why = ((inputs = {}, options = {}) => {
7189
+ experimentalStaticLocale ?? options.locale ?? getLocale();
7190
+ return ko_mcp_rule_product_link_why(inputs);
7191
+ });
7192
+
5880
7193
  //#endregion
5881
7194
  //#region ../i18n/src/paraglide/messages/mcp_rule_server_only_env_example.js
5882
7195
  /** @typedef {import('../runtime.js').LocalizedString} LocalizedString */
@@ -6626,6 +7939,24 @@ const mcp_verify_payment_return_route = ((inputs = {}, options = {}) => {
6626
7939
  return ko_mcp_verify_payment_return_route(inputs);
6627
7940
  });
6628
7941
 
7942
+ //#endregion
7943
+ //#region ../i18n/src/paraglide/messages/mcp_verify_product_link.js
7944
+ /** @typedef {import('../runtime.js').LocalizedString} LocalizedString */
7945
+ /** @typedef {{}} Mcp_Verify_Product_LinkInputs */
7946
+ const ko_mcp_verify_product_link = () => {
7947
+ return `상품 링크의 경로 값이 상품 id다 — \`productPathParam(product)\`로 상품번호 주소를 쓴다`;
7948
+ };
7949
+ /**
7950
+
7951
+ * @param {Mcp_Verify_Product_LinkInputs} inputs
7952
+ * @param {{ locale?: "ko" }} options
7953
+ * @returns {LocalizedString}
7954
+ */
7955
+ const mcp_verify_product_link = ((inputs = {}, options = {}) => {
7956
+ experimentalStaticLocale ?? options.locale ?? getLocale();
7957
+ return ko_mcp_verify_product_link(inputs);
7958
+ });
7959
+
6629
7960
  //#endregion
6630
7961
  //#region ../i18n/src/paraglide/messages/mcp_verify_server_only_env.js
6631
7962
  /** @typedef {import('../runtime.js').LocalizedString} LocalizedString */
@@ -6716,6 +8047,26 @@ const mcp_verify_whole_project = ((inputs = {}, options = {}) => {
6716
8047
  return ko_mcp_verify_whole_project(inputs);
6717
8048
  });
6718
8049
 
8050
+ //#endregion
8051
+ //#region ../i18n/src/lazy-messages.ts
8052
+ /**
8053
+ * 라벨 표 — 값을 읽을 때마다 메시지 함수를 불러 그 순간의 로케일 문구를 돌려준다(이슈 #73).
8054
+ * 모듈을 읽을 때 문구를 만들면 서버 렌더링에서 요청 로케일이 아니라 기동 시점 로케일로 굳는다.
8055
+ * 타입은 `Record<K, string>`이라 호출부(`LABEL[key]`, `Object.entries(LABEL)`)를 바꾸지 않는다.
8056
+ *
8057
+ * ```ts
8058
+ * export const ROLE_LABEL = lazyMessages<StoreRole>({ OWNER: m.store_shell_role_owner, ... });
8059
+ * ```
8060
+ */
8061
+ function lazyMessages(table) {
8062
+ const labels = {};
8063
+ for (const key of Object.keys(table)) Object.defineProperty(labels, key, {
8064
+ enumerable: true,
8065
+ get: () => table[key]()
8066
+ });
8067
+ return Object.freeze(labels);
8068
+ }
8069
+
6719
8070
  //#endregion
6720
8071
  //#region ../i18n/src/process-locale.ts
6721
8072
  /**
@@ -6754,56 +8105,15 @@ function takeLangFlag(argv) {
6754
8105
  for (let i = 0; i < argv.length; i++) {
6755
8106
  const arg = argv[i];
6756
8107
  if (arg === "--lang") {
6757
- lang = argv[i + 1];
6758
- i++;
6759
- } else if (arg.startsWith("--lang=")) lang = arg.slice(7);
6760
- else rest.push(arg);
6761
- }
6762
- return {
6763
- lang,
6764
- rest
6765
- };
6766
- }
6767
-
6768
- //#endregion
6769
- //#region package.json
6770
- var version = "0.3.4";
6771
-
6772
- //#endregion
6773
- //#region src/client.ts
6774
- /**
6775
- * 관리 API 클라이언트 — `@sayren/store-sdk`(계약의 원천)를 쓴다. User-Agent `sayren-cli/{버전}`은 api가 버전의 만든 경로
6776
- * (`createdVia: CLI`)를 적는 표시다(권한과 무관하다. 에이전트용 액세스 토큰이면 행위자는 여전히 에이전트이고 발행은 승인 대기다).
6777
- * 토큰은 헤더에만 싣고 화면·로그에 찍지 않는다.
6778
- */
6779
- const CLI_VERSION = version;
6780
- const CLI_USER_AGENT = `sayren-cli/${CLI_VERSION}`;
6781
- /**
6782
- * 계정 토큰(#71)을 Bearer로, 고른 상점(`auth.storeId`)을 `X-Store-Id`로 싣는다. 401이면 `refresh`(자격 증명 파일의 refresh 회전)를
6783
- * 한 번 부른 뒤 다시 보낸다. 토큰·상점은 함수로 읽어 갱신·선택된 값을 따라간다.
6784
- */
6785
- function clientOf(auth, fetchImpl = fetch, refresh) {
6786
- return createStoreClient({
6787
- baseUrl: `${auth.apiOrigin}/v1`,
6788
- accessToken: () => auth.token,
6789
- storeId: () => auth.storeId ?? null,
6790
- ...refresh ? { refresh } : {},
6791
- fetch: (input, init) => {
6792
- const headers = new Headers(init?.headers);
6793
- headers.set("user-agent", CLI_USER_AGENT);
6794
- return fetchImpl(input, {
6795
- ...init,
6796
- headers
6797
- });
6798
- }
6799
- });
6800
- }
6801
- /** 오류 코드 — `ApiError`가 아니면 null */
6802
- function codeOf(error) {
6803
- return error instanceof ApiError ? error.code : null;
6804
- }
6805
- function detailsOf(error) {
6806
- return error instanceof ApiError ? error.details ?? {} : {};
8108
+ lang = argv[i + 1];
8109
+ i++;
8110
+ } else if (arg.startsWith("--lang=")) lang = arg.slice(7);
8111
+ else rest.push(arg);
8112
+ }
8113
+ return {
8114
+ lang,
8115
+ rest
8116
+ };
6807
8117
  }
6808
8118
 
6809
8119
  //#endregion
@@ -7775,6 +9085,807 @@ async function selectStore(auth, client, io, candidates, folderStore = null) {
7775
9085
  return auth.storeId;
7776
9086
  }
7777
9087
 
9088
+ //#endregion
9089
+ //#region package.json
9090
+ var version = "0.5.0";
9091
+
9092
+ //#endregion
9093
+ //#region src/client.ts
9094
+ /**
9095
+ * 관리 API 클라이언트 — `@sayren/store-sdk`(계약의 원천)를 쓴다. User-Agent `sayren-cli/{버전}`은 api가 버전의 만든 경로
9096
+ * (`createdVia: CLI`)를 적는 표시다(권한과 무관하다. 에이전트용 액세스 토큰이면 행위자는 여전히 에이전트이고 발행은 승인 대기다).
9097
+ * 토큰은 헤더에만 싣고 화면·로그에 찍지 않는다.
9098
+ */
9099
+ const CLI_VERSION = version;
9100
+ const CLI_USER_AGENT = `sayren-cli/${CLI_VERSION}`;
9101
+ /**
9102
+ * 계정 토큰(#71)을 Bearer로, 고른 상점(`auth.storeId`)을 `X-Store-Id`로 싣는다. 401이면 `refresh`(자격 증명 파일의 refresh 회전)를
9103
+ * 한 번 부른 뒤 다시 보낸다. 토큰·상점은 함수로 읽어 갱신·선택된 값을 따라간다.
9104
+ */
9105
+ function clientOf(auth, fetchImpl = fetch, refresh) {
9106
+ return createStoreClient({
9107
+ baseUrl: `${auth.apiOrigin}/v1`,
9108
+ accessToken: () => auth.token,
9109
+ storeId: () => auth.storeId ?? null,
9110
+ ...refresh ? { refresh } : {},
9111
+ fetch: (input, init$1) => {
9112
+ const headers = new Headers(init$1?.headers);
9113
+ headers.set("user-agent", CLI_USER_AGENT);
9114
+ return fetchImpl(input, {
9115
+ ...init$1,
9116
+ headers
9117
+ });
9118
+ }
9119
+ });
9120
+ }
9121
+ /** 오류 코드 — `ApiError`가 아니면 null */
9122
+ function codeOf(error) {
9123
+ return error instanceof ApiError ? error.code : null;
9124
+ }
9125
+ function detailsOf(error) {
9126
+ return error instanceof ApiError ? error.details ?? {} : {};
9127
+ }
9128
+
9129
+ //#endregion
9130
+ //#region src/app-commands.ts
9131
+ /**
9132
+ * `sayren app …`(이슈 #22, 매뉴얼 「앱 만들기」) — 앱 폴더(`sayren.app.json`)에서 돈다. 서버는 코드를 빌드하지 않는다(A1):
9133
+ * CLI가 esbuild로 서버 번들 한 파일을 만들어 올리고 api가 `DEPENDENCIES`·`VERIFY`·`BUNDLE`·`UPLOAD`를 돈다. 앱 화면(`ui/`)은
9134
+ * 정적 파일 그대로 올린다.
9135
+ *
9136
+ * 인증은 둘이다. 앱 배포 키(`--key`·`SAYREN_APP_KEY`, developer.sayren.app에서 발행, `sak_…`)는 그 앱의 경로에만 쓰이고(CI 용도),
9137
+ * 그 밖에는 `sayren login`의 계정 토큰이다. 앱 등록(`init`)·개발 상점은 계정 토큰만 된다.
9138
+ */
9139
+ const APP_MANIFEST_FILE = "sayren.app.json";
9140
+ const APP_STATE_FILE = `${STATE_DIR}/app.json`;
9141
+ const APP_DEV_PORT = 4020;
9142
+ const SERVER_ENTRY_CANDIDATES = [
9143
+ "src/server.ts",
9144
+ "src/server.js",
9145
+ "src/server.mjs"
9146
+ ];
9147
+ const UI_DIR = "ui";
9148
+ const SETTING_ENV_PREFIX = "SAYREN_APP_SETTING_";
9149
+ const SECRET_ENV_PREFIX = "SAYREN_APP_SECRET_";
9150
+ /** `dev`의 개발 설치 토큰을 만료 몇 초 전에 다시 받는가 */
9151
+ const DEV_TOKEN_REFRESH_MARGIN_MS = 6e4;
9152
+ function readAppState(dir) {
9153
+ const path = join(dir, APP_STATE_FILE);
9154
+ if (!existsSync(path)) return null;
9155
+ try {
9156
+ const parsed = JSON.parse(readFileSync(path, "utf8"));
9157
+ if (typeof parsed.appId === "string" && typeof parsed.handle === "string" && typeof parsed.apiOrigin === "string") return {
9158
+ appId: parsed.appId,
9159
+ handle: parsed.handle,
9160
+ apiOrigin: parsed.apiOrigin
9161
+ };
9162
+ } catch {}
9163
+ throw new CliError(cli_app_state_invalid({ file: APP_STATE_FILE }));
9164
+ }
9165
+ function writeAppState(dir, state) {
9166
+ mkdirSync(join(dir, STATE_DIR), { recursive: true });
9167
+ writeFileSync(join(dir, APP_STATE_FILE), `${JSON.stringify(state, null, 2)}\n`, { mode: 384 });
9168
+ }
9169
+ /** 매니페스트 원문(JSON)과 검증 결과 — 문제가 있으면 CliError */
9170
+ function loadManifest(dir) {
9171
+ const path = join(dir, APP_MANIFEST_FILE);
9172
+ if (!existsSync(path)) throw new CliError(cli_app_manifest_missing({ file: APP_MANIFEST_FILE }));
9173
+ let raw;
9174
+ try {
9175
+ raw = JSON.parse(readFileSync(path, "utf8"));
9176
+ } catch (error) {
9177
+ throw new CliError(cli_app_manifest_invalid({ problems: `- ${error instanceof Error ? error.message : String(error)}` }));
9178
+ }
9179
+ const parsed = appManifestSchema.safeParse(raw);
9180
+ if (!parsed.success) throw new CliError(cli_app_manifest_invalid({ problems: parsed.error.issues.map((issue) => `- ${issue.path.join(".") || "(root)"}: ${issue.message}`).join("\n") }));
9181
+ const problems = appManifestProblems(parsed.data);
9182
+ if (problems.length) throw new CliError(cli_app_manifest_invalid({ problems: problems.map((p) => `- ${p.path}: ${p.message} (${p.code})`).join("\n") }));
9183
+ return {
9184
+ raw,
9185
+ manifest: parsed.data
9186
+ };
9187
+ }
9188
+ function appDir(flags, io) {
9189
+ return resolve(io.cwd, flags.dir ?? ".");
9190
+ }
9191
+ function requireState(dir) {
9192
+ const state = readAppState(dir);
9193
+ if (!state) throw new CliError(cli_app_not_registered({ file: APP_MANIFEST_FILE }));
9194
+ return state;
9195
+ }
9196
+ /** 배포 키(`--key` → `SAYREN_APP_KEY`)가 있으면 그것, 없으면 계정 토큰(`resolveAuth`) */
9197
+ async function developerAuth(flags, dir, io, options = {}) {
9198
+ const state = readAppState(dir);
9199
+ const key = flags.key?.trim() || io.env.SAYREN_APP_KEY?.trim();
9200
+ if (key && !options.accountOnly) {
9201
+ if (!APP_DEPLOY_KEY_PATTERN.test(key)) throw new CliError(cli_app_key_invalid());
9202
+ const { apiOrigin } = resolveApiOrigin({ apiOrigin: flags.apiOrigin ?? state?.apiOrigin }, dir, null, io.env);
9203
+ return {
9204
+ apiOrigin,
9205
+ bearer: key,
9206
+ kind: "key"
9207
+ };
9208
+ }
9209
+ const auth = resolveAuth({
9210
+ ...flags,
9211
+ apiOrigin: flags.apiOrigin ?? state?.apiOrigin
9212
+ }, dir, null, io.env, credentialTokenReader(io.env));
9213
+ const refresh = await readyAuth(auth, io);
9214
+ return {
9215
+ apiOrigin: auth.apiOrigin,
9216
+ get bearer() {
9217
+ return auth.token;
9218
+ },
9219
+ kind: "account",
9220
+ ...refresh ? { refresh } : {}
9221
+ };
9222
+ }
9223
+ async function devApi(auth, io, method, path, body, retried = false) {
9224
+ const res = await io.fetch(`${auth.apiOrigin}/platform/v1/developer${path}`, {
9225
+ method,
9226
+ headers: {
9227
+ authorization: `Bearer ${auth.bearer}`,
9228
+ "user-agent": CLI_USER_AGENT,
9229
+ ...body === void 0 ? {} : { "content-type": "application/json" }
9230
+ },
9231
+ ...body === void 0 ? {} : { body: JSON.stringify(body) }
9232
+ });
9233
+ if (res.status === 204) return void 0;
9234
+ const text = await res.text();
9235
+ let json = {};
9236
+ try {
9237
+ json = text ? JSON.parse(text) : {};
9238
+ } catch {
9239
+ throw new ApiError(res.status, "INVALID_RESPONSE", text.slice(0, 200));
9240
+ }
9241
+ if (res.ok && json.meta?.isSuccess !== false) return json.data;
9242
+ if (res.status === 401 && auth.refresh && !retried && await auth.refresh()) return devApi(auth, io, method, path, body, true);
9243
+ throw new ApiError(res.status, json.error?.code ?? json.meta?.code ?? "ERROR", json.error?.message ?? json.meta?.message ?? `HTTP ${res.status}`, void 0, json, json.error?.details);
9244
+ }
9245
+ function serverEntryOf(dir) {
9246
+ const found = SERVER_ENTRY_CANDIDATES.find((candidate) => existsSync(join(dir, candidate)));
9247
+ if (!found) throw new CliError(cli_app_entry_missing({ entry: SERVER_ENTRY_CANDIDATES[0] }));
9248
+ return join(dir, found);
9249
+ }
9250
+ /** esbuild로 서버 번들을 만든다. 앱 의존성은 앱 폴더의 `node_modules`에서 푼다(설치돼 있어야 한다) */
9251
+ async function bundleServer(dir) {
9252
+ const entry = serverEntryOf(dir);
9253
+ const esbuild = await import("esbuild");
9254
+ try {
9255
+ const file = (await esbuild.build({
9256
+ entryPoints: [entry],
9257
+ bundle: true,
9258
+ write: false,
9259
+ format: "esm",
9260
+ platform: "browser",
9261
+ target: "es2022",
9262
+ conditions: [
9263
+ "workerd",
9264
+ "worker",
9265
+ "browser"
9266
+ ],
9267
+ mainFields: [
9268
+ "browser",
9269
+ "module",
9270
+ "main"
9271
+ ],
9272
+ absWorkingDir: dir,
9273
+ logLevel: "silent",
9274
+ legalComments: "none",
9275
+ define: { "process.env.NODE_ENV": "\"production\"" }
9276
+ })).outputFiles?.[0];
9277
+ if (!file) throw new CliError(cli_app_bundle_failed({ tail: "(빈 산출물)" }));
9278
+ return file.text;
9279
+ } catch (error) {
9280
+ if (error instanceof CliError) throw error;
9281
+ const tail = error && typeof error === "object" && "errors" in error ? (error.errors ?? []).map((e) => e.location ? `${e.location.file}:${e.location.line}: ${e.text}` : e.text).join("\n") : error instanceof Error ? error.message : String(error);
9282
+ throw new CliError(cli_app_bundle_failed({ tail }));
9283
+ }
9284
+ }
9285
+ /** 번들을 불러 `defineApp` 메타데이터를 읽는다 — `HANDLER_MISSING`·기본 내보내기 검사. `dev`도 이 모듈을 실행한다 */
9286
+ async function loadBundle(dir, server) {
9287
+ const out = join(dir, STATE_DIR, "build");
9288
+ mkdirSync(out, { recursive: true });
9289
+ const file = join(out, `server.${Date.now().toString(36)}.mjs`);
9290
+ writeFileSync(file, server);
9291
+ let mod;
9292
+ try {
9293
+ mod = await import(pathToFileURL(file).href);
9294
+ } catch (error) {
9295
+ throw new CliError(cli_app_bundle_failed({ tail: error instanceof Error ? error.message : String(error) }));
9296
+ }
9297
+ const app = mod.default;
9298
+ const meta = app?.__sayrenApp;
9299
+ if (!app || typeof app.fetch !== "function" || !meta) throw new CliError(cli_app_default_export_missing());
9300
+ return {
9301
+ app,
9302
+ meta: {
9303
+ events: [...meta.events],
9304
+ http: [...meta.http]
9305
+ }
9306
+ };
9307
+ }
9308
+ /** 로컬 검사 — 매니페스트, 번들, 이벤트 함수 존재, 비밀 값 형식, 크기. 서버 `VERIFY`·`BUNDLE`과 같은 규칙 */
9309
+ async function verifyApp(dir) {
9310
+ const { raw, manifest } = loadManifest(dir);
9311
+ const server = await bundleServer(dir);
9312
+ if (APP_SECRET_PATTERNS.find((pattern) => pattern.test(server))) throw new CliError(cli_app_secret_in_source());
9313
+ const gzipBytes = gzipSync(server).byteLength;
9314
+ if (gzipBytes > APP_SERVER_BUNDLE_MAX_GZIP_BYTES) throw new CliError(cli_app_bundle_too_large({ size: formatMb(gzipBytes) }));
9315
+ const { app, meta } = await loadBundle(dir, server);
9316
+ const missing = manifest.events.filter((event) => !meta.events.includes(event));
9317
+ if (missing.length) throw new CliError(cli_app_handler_missing({ events: missing.join(", ") }));
9318
+ const warnings = [];
9319
+ const listed = manifest.events;
9320
+ const extra = meta.events.filter((event) => !listed.includes(event));
9321
+ if (extra.length) warnings.push(cli_app_handler_unlisted({ events: extra.join(", ") }));
9322
+ const ui = manifest.ui?.adminPage ? collectUi(dir) : [];
9323
+ if (manifest.ui?.adminPage && !ui.some((file) => file.path === "index.html")) throw new CliError(cli_app_ui_index_missing({ dir: UI_DIR }));
9324
+ return {
9325
+ manifest,
9326
+ raw,
9327
+ bundle: {
9328
+ server,
9329
+ gzipBytes,
9330
+ meta
9331
+ },
9332
+ app,
9333
+ ui,
9334
+ warnings
9335
+ };
9336
+ }
9337
+ function collectUi(dir) {
9338
+ const root = join(dir, UI_DIR);
9339
+ if (!existsSync(root)) throw new CliError(cli_app_ui_index_missing({ dir: UI_DIR }));
9340
+ const files = [];
9341
+ const walk = (current) => {
9342
+ for (const name of readdirSync(current)) {
9343
+ if (name.startsWith(".") || name === "node_modules" || name === "_sayren") continue;
9344
+ const full = join(current, name);
9345
+ if (statSync(full).isDirectory()) walk(full);
9346
+ else files.push({
9347
+ path: relative(root, full).split(sep).join("/"),
9348
+ bytes: readFileSync(full)
9349
+ });
9350
+ }
9351
+ };
9352
+ walk(root);
9353
+ const bridge = join(dir, "node_modules/@sayren/app/dist/ui.mjs");
9354
+ if (!existsSync(bridge)) throw new CliError(cli_app_bridge_missing());
9355
+ files.push({
9356
+ path: "_sayren/ui.js",
9357
+ bytes: readFileSync(bridge)
9358
+ });
9359
+ if (files.length > APP_UI_MAX_FILES) throw new CliError(cli_app_ui_too_large({ limit: `${APP_UI_MAX_FILES} files` }));
9360
+ if (files.reduce((sum, file) => sum + file.bytes.byteLength, 0) > APP_UI_MAX_BYTES) throw new CliError(cli_app_ui_too_large({ limit: formatMb(APP_UI_MAX_BYTES) }));
9361
+ return files;
9362
+ }
9363
+ function formatMb(bytes) {
9364
+ return `${(bytes / 1024 / 1024).toFixed(1)}MB`;
9365
+ }
9366
+ const HANDLE_RE = /^[a-z0-9][a-z0-9-]{1,38}[a-z0-9]$/;
9367
+ function initFiles(handle, name) {
9368
+ const manifest = {
9369
+ handle,
9370
+ name,
9371
+ description: "",
9372
+ scopes: ["order:r"],
9373
+ network: { hosts: [] },
9374
+ events: ["ORDER.PAID"],
9375
+ settings: {}
9376
+ };
9377
+ return {
9378
+ [APP_MANIFEST_FILE]: `${JSON.stringify(manifest, null, 2)}\n`,
9379
+ "package.json": `${JSON.stringify({
9380
+ name: handle,
9381
+ private: true,
9382
+ type: "module",
9383
+ scripts: {
9384
+ dev: "sayren app dev",
9385
+ verify: "sayren app verify",
9386
+ deploy: "sayren app deploy"
9387
+ },
9388
+ dependencies: { "@sayren/app": `^${CLI_VERSION}` },
9389
+ devDependencies: {
9390
+ sayren: `^${CLI_VERSION}`,
9391
+ typescript: "^5.9.0"
9392
+ }
9393
+ }, null, 2)}\n`,
9394
+ "tsconfig.json": `${JSON.stringify({
9395
+ compilerOptions: {
9396
+ target: "ES2022",
9397
+ module: "ESNext",
9398
+ moduleResolution: "bundler",
9399
+ strict: true,
9400
+ noEmit: true,
9401
+ lib: ["ES2022", "DOM"],
9402
+ skipLibCheck: true
9403
+ },
9404
+ include: ["src"]
9405
+ }, null, 2)}\n`,
9406
+ "src/server.ts": `import { defineApp } from "@sayren/app";
9407
+
9408
+ export default defineApp({
9409
+ events: {
9410
+ "ORDER.PAID": async (event, ctx) => {
9411
+ const { orderId } = event.data as { orderId: string };
9412
+ const order = await ctx.api.orders.get(orderId);
9413
+ ctx.log.info("결제된 주문", order.orderNo, order.totalAmount);
9414
+ },
9415
+ },
9416
+ });
9417
+ `,
9418
+ ".gitignore": "node_modules/\ndist/\n.env\n.sayren/\n",
9419
+ ".env.example": `# 로컬 실행(sayren app dev)의 설정·비밀 값\n# ${SETTING_ENV_PREFIX}<설정 키>=값\n# ${SECRET_ENV_PREFIX}<비밀 값 이름>=값\n`
9420
+ };
9421
+ }
9422
+ async function appInit(handle, flags, io) {
9423
+ if (!handle || !HANDLE_RE.test(handle)) throw new CliError(cli_app_handle_invalid());
9424
+ const dir = resolve(io.cwd, flags.dir ?? handle);
9425
+ if (existsSync(join(dir, APP_MANIFEST_FILE))) throw new CliError(cli_app_dir_exists({ dir: relative(io.cwd, dir) || "." }));
9426
+ const name = flags.name?.trim() || handle;
9427
+ const auth = await developerAuth(flags, dir, io, { accountOnly: true });
9428
+ const app = await devApi(auth, io, "POST", "/apps", {
9429
+ handle,
9430
+ name
9431
+ });
9432
+ mkdirSync(join(dir, "src"), { recursive: true });
9433
+ for (const [path, content] of Object.entries(initFiles(handle, name))) {
9434
+ const full = join(dir, path);
9435
+ mkdirSync(join(full, ".."), { recursive: true });
9436
+ if (!existsSync(full)) writeFileSync(full, content);
9437
+ }
9438
+ writeAppState(dir, {
9439
+ appId: app.appId,
9440
+ handle: app.handle,
9441
+ apiOrigin: auth.apiOrigin
9442
+ });
9443
+ io.out(cli_app_init_done({
9444
+ dir: relative(io.cwd, dir) || ".",
9445
+ appId: app.appId,
9446
+ handle
9447
+ }));
9448
+ return 0;
9449
+ }
9450
+ async function appVerify(flags, io) {
9451
+ const outcome = await verifyApp(appDir(flags, io));
9452
+ for (const warning of outcome.warnings) io.err(cli_app_warning({ message: warning }));
9453
+ io.out(cli_app_verify_ok({
9454
+ events: outcome.bundle.meta.events.join(", ") || "-",
9455
+ http: outcome.bundle.meta.http.join(", ") || "-",
9456
+ size: formatMb(outcome.bundle.gzipBytes),
9457
+ ui: String(outcome.ui.length)
9458
+ }));
9459
+ return 0;
9460
+ }
9461
+ function printBuild(version$1, io) {
9462
+ for (const stage of version$1.build?.stages ?? []) io.out(` ${stage.ok ? "✓" : "✗"} ${stage.stage} ${stage.durationMs}ms`);
9463
+ }
9464
+ async function appDeploy(flags, io) {
9465
+ const dir = appDir(flags, io);
9466
+ const state = requireState(dir);
9467
+ const outcome = await verifyApp(dir);
9468
+ if (outcome.manifest.handle !== state.handle) throw new CliError(cli_app_handle_mismatch({
9469
+ manifest: outcome.manifest.handle,
9470
+ registered: state.handle
9471
+ }));
9472
+ for (const warning of outcome.warnings) io.err(cli_app_warning({ message: warning }));
9473
+ const auth = await developerAuth(flags, dir, io);
9474
+ const packageJson = existsSync(join(dir, "package.json")) ? readFileSync(join(dir, "package.json"), "utf8") : "{}";
9475
+ const lockfile = existsSync(join(dir, "pnpm-lock.yaml")) ? readFileSync(join(dir, "pnpm-lock.yaml"), "utf8") : null;
9476
+ io.out(cli_app_uploading({
9477
+ size: formatMb(outcome.bundle.gzipBytes),
9478
+ ui: String(outcome.ui.length)
9479
+ }));
9480
+ const version$1 = await devApi(auth, io, "PUT", `/apps/${state.appId}/versions`, {
9481
+ manifest: outcome.raw,
9482
+ packageJson,
9483
+ lockfile,
9484
+ server: Buffer.from(outcome.bundle.server, "utf8").toString("base64"),
9485
+ ui: outcome.ui.map((file) => ({
9486
+ path: file.path,
9487
+ content: file.bytes.toString("base64")
9488
+ })),
9489
+ ...flags.message ? { message: flags.message } : {}
9490
+ });
9491
+ printBuild(version$1, io);
9492
+ if (version$1.status !== "READY") {
9493
+ io.err(cli_app_build_failed({
9494
+ stage: version$1.build?.failureStage ?? "-",
9495
+ code: version$1.build?.errorCode ?? "-",
9496
+ tail: version$1.build?.logTail ?? ""
9497
+ }));
9498
+ return 1;
9499
+ }
9500
+ io.out(cli_app_deploy_done({ number: String(version$1.number) }));
9501
+ return 0;
9502
+ }
9503
+ async function appRelease(numberRaw, flags, io) {
9504
+ const number = Number(numberRaw);
9505
+ if (!Number.isInteger(number) || number < 1) throw new CliError(cli_app_version_number_required());
9506
+ const dir = appDir(flags, io);
9507
+ const state = requireState(dir);
9508
+ const result = await devApi(await developerAuth(flags, dir, io), io, "POST", `/apps/${state.appId}/versions/${number}/release`);
9509
+ io.out(cli_app_release_done({
9510
+ number: String(result.version.number),
9511
+ applied: String(result.applied),
9512
+ pending: String(result.pendingReconsent)
9513
+ }));
9514
+ return 0;
9515
+ }
9516
+ async function appStatus(flags, io) {
9517
+ const dir = appDir(flags, io);
9518
+ const state = requireState(dir);
9519
+ const auth = await developerAuth(flags, dir, io);
9520
+ const [app, versions] = await Promise.all([devApi(auth, io, "GET", `/apps/${state.appId}`), devApi(auth, io, "GET", `/apps/${state.appId}/versions`)]);
9521
+ io.out(cli_app_status({
9522
+ handle: app.handle,
9523
+ name: app.name,
9524
+ appId: app.appId,
9525
+ status: app.status,
9526
+ current: app.currentVersionNumber === null ? "-" : String(app.currentVersionNumber),
9527
+ active: String(app.installations.active),
9528
+ pending: String(app.installations.pendingReconsent)
9529
+ }));
9530
+ for (const version$1 of versions.slice(0, 5)) io.out(` v${version$1.number} ${version$1.status}${version$1.current ? " *" : ""} ${version$1.createdAt}${version$1.message ? ` — ${version$1.message}` : ""}${version$1.build?.errorCode ? ` (${version$1.build.errorCode})` : ""}`);
9531
+ return 0;
9532
+ }
9533
+ const SINCE_RE = /^(\d+)([smhd])$/;
9534
+ function sinceMs(value) {
9535
+ if (!value) return null;
9536
+ const match = SINCE_RE.exec(value.trim());
9537
+ if (!match) throw new CliError(cli_app_since_invalid({ value }));
9538
+ const unit = {
9539
+ s: 1e3,
9540
+ m: 6e4,
9541
+ h: 36e5,
9542
+ d: 864e5
9543
+ }[match[2]];
9544
+ return Number(match[1]) * unit;
9545
+ }
9546
+ function invocationLine(row) {
9547
+ const head = `${row.createdAt} ${row.outcome.padEnd(14)} ${row.kind}${row.eventType ? ` ${row.eventType}` : ""} ${row.storeName ?? row.storeId} v${row.versionNumber ?? "-"} ${row.durationMs}ms`;
9548
+ const lines = row.logs.map((line) => ` [${line.level}] ${line.message}`);
9549
+ if (row.errorMessage) lines.push(` ! ${row.errorMessage.split("\n")[0]}`);
9550
+ return [head, ...lines].join("\n");
9551
+ }
9552
+ async function appLogs(flags, io) {
9553
+ const dir = appDir(flags, io);
9554
+ const state = requireState(dir);
9555
+ const auth = await developerAuth(flags, dir, io);
9556
+ const since = sinceMs(flags.since);
9557
+ const seen = /* @__PURE__ */ new Set();
9558
+ const query = new URLSearchParams({ limit: "50" });
9559
+ if (flags.store) query.set("storeId", flags.store);
9560
+ const fetchOnce = async () => {
9561
+ const rows = await devApi(auth, io, "GET", `/apps/${state.appId}/invocations?${query}`);
9562
+ const now = io.now?.() ?? Date.now();
9563
+ const fresh = rows.filter((row) => !seen.has(row.invocationId)).filter((row) => since === null || now - Date.parse(row.createdAt) <= since).reverse();
9564
+ for (const row of fresh) {
9565
+ seen.add(row.invocationId);
9566
+ io.out(invocationLine(row));
9567
+ }
9568
+ return fresh.length;
9569
+ };
9570
+ const count = await fetchOnce();
9571
+ if (!flags.tail) {
9572
+ if (count === 0) io.out(cli_app_logs_empty());
9573
+ return 0;
9574
+ }
9575
+ while (!io.signal?.aborted) {
9576
+ await io.sleep(io.pollMs);
9577
+ await fetchOnce();
9578
+ }
9579
+ return 0;
9580
+ }
9581
+ async function appSecret(action, name, flags, io) {
9582
+ const dir = appDir(flags, io);
9583
+ const state = requireState(dir);
9584
+ const auth = await developerAuth(flags, dir, io);
9585
+ const base = `/apps/${state.appId}/secrets`;
9586
+ if (action === "list") {
9587
+ const list = await devApi(auth, io, "GET", base);
9588
+ if (list.length === 0) io.out(cli_app_secret_empty());
9589
+ for (const item of list) io.out(` ${item.name} ${item.updatedAt}`);
9590
+ return 0;
9591
+ }
9592
+ if (!name) throw new CliError(cli_app_secret_name_required());
9593
+ if (action === "put") {
9594
+ const value = (await (io.readStdin ?? readStdin)()).replace(/\r?\n$/, "");
9595
+ if (!value) throw new CliError(cli_app_secret_value_required({ name }));
9596
+ await devApi(auth, io, "PUT", `${base}/${encodeURIComponent(name)}`, { value });
9597
+ io.out(cli_app_secret_saved({ name }));
9598
+ return 0;
9599
+ }
9600
+ if (action === "delete") {
9601
+ await devApi(auth, io, "DELETE", `${base}/${encodeURIComponent(name)}`);
9602
+ io.out(cli_app_secret_deleted({ name }));
9603
+ return 0;
9604
+ }
9605
+ throw new CliError(cli_app_subcommand_unknown({ command: `secret ${action ?? ""}`.trim() }));
9606
+ }
9607
+ function readStdin() {
9608
+ return new Promise((resolve$1, reject) => {
9609
+ let data = "";
9610
+ process.stdin.setEncoding("utf8");
9611
+ process.stdin.on("data", (chunk) => {
9612
+ data += chunk;
9613
+ });
9614
+ process.stdin.once("end", () => resolve$1(data));
9615
+ process.stdin.once("error", reject);
9616
+ });
9617
+ }
9618
+ async function appDevStore(action, name, flags, io) {
9619
+ const auth = await developerAuth(flags, appDir(flags, io), io, { accountOnly: true });
9620
+ if (action === "list") {
9621
+ const list = await devApi(auth, io, "GET", "/dev-stores");
9622
+ if (list.length === 0) io.out(cli_app_dev_store_empty());
9623
+ for (const store of list) io.out(` ${store.storeId} ${store.storeCode} ${store.name} ${store.status}`);
9624
+ return 0;
9625
+ }
9626
+ if (action === "create") {
9627
+ if (!name?.trim()) throw new CliError(cli_app_dev_store_name_required());
9628
+ const store = await devApi(auth, io, "POST", "/dev-stores", { name: name.trim() });
9629
+ io.out(cli_app_dev_store_created({
9630
+ storeId: store.storeId,
9631
+ name: store.name
9632
+ }));
9633
+ return 0;
9634
+ }
9635
+ throw new CliError(cli_app_subcommand_unknown({ command: `dev-store ${action ?? ""}`.trim() }));
9636
+ }
9637
+ /** `.env`의 `SAYREN_APP_SETTING_*`·`SAYREN_APP_SECRET_*` — 설정은 매니페스트 타입으로 바꾼다 */
9638
+ function localSettingsOf(manifest, env) {
9639
+ const settings = {};
9640
+ const secrets = {};
9641
+ for (const [key, field] of Object.entries(manifest.settings ?? {})) {
9642
+ const raw = env.get(`${SETTING_ENV_PREFIX}${key}`);
9643
+ if (raw === void 0) {
9644
+ if (field.default !== void 0) settings[key] = field.default;
9645
+ continue;
9646
+ }
9647
+ settings[key] = field.type === "number" ? Number(raw) : field.type === "boolean" ? raw === "true" || raw === "1" : raw;
9648
+ }
9649
+ for (const [key, value] of env) if (key.startsWith(SECRET_ENV_PREFIX)) secrets[key.slice(18)] = value;
9650
+ return {
9651
+ settings,
9652
+ secrets
9653
+ };
9654
+ }
9655
+ let devSeq = 0;
9656
+ function devEnvelope(input) {
9657
+ devSeq += 1;
9658
+ return {
9659
+ v: 1,
9660
+ invocationId: `inv_dev_${Date.now().toString(36)}_${devSeq}`,
9661
+ kind: input.kind,
9662
+ installation: {
9663
+ installationId: input.token?.installationId ?? "inst_dev",
9664
+ appId: input.appId,
9665
+ versionNumber: 0,
9666
+ storeId: input.token?.storeId ?? "store_dev",
9667
+ storeName: "(dev)",
9668
+ apiBaseUrl: input.apiBaseUrl
9669
+ },
9670
+ token: input.token?.token ?? null,
9671
+ settings: input.settings,
9672
+ secrets: input.secrets,
9673
+ ...input.kind === "http" ? { user: {
9674
+ userId: "user_dev",
9675
+ role: "OWNER"
9676
+ } } : {},
9677
+ ...input.event ? { event: {
9678
+ id: `evt_dev_${devSeq}`,
9679
+ type: input.event.type,
9680
+ createdAt: (/* @__PURE__ */ new Date()).toISOString(),
9681
+ storeId: input.token?.storeId ?? "store_dev",
9682
+ sequence: devSeq,
9683
+ data: input.event.data
9684
+ } } : {},
9685
+ ...input.request ? { request: input.request } : {}
9686
+ };
9687
+ }
9688
+ async function invokeLocal(app, envelope) {
9689
+ const res = await app.fetch(new Request("https://app.local/_invoke", {
9690
+ method: "POST",
9691
+ headers: { "content-type": "application/json" },
9692
+ body: JSON.stringify(envelope)
9693
+ }));
9694
+ if (!res.ok) throw new CliError(cli_app_bundle_failed({ tail: await res.text() }));
9695
+ return await res.json();
9696
+ }
9697
+ function printResult(label, result, io) {
9698
+ io.out(`${label} ${result.outcome} ${result.durationMs}ms`);
9699
+ for (const line of result.logs) io.out(` [${line.level}] ${line.message}`);
9700
+ if (result.errorMessage) io.err(` ! ${result.errorMessage}`);
9701
+ }
9702
+ const MIME = {
9703
+ ".html": "text/html; charset=utf-8",
9704
+ ".js": "text/javascript; charset=utf-8",
9705
+ ".mjs": "text/javascript; charset=utf-8",
9706
+ ".css": "text/css; charset=utf-8",
9707
+ ".json": "application/json",
9708
+ ".svg": "image/svg+xml",
9709
+ ".png": "image/png",
9710
+ ".jpg": "image/jpeg",
9711
+ ".ico": "image/x-icon"
9712
+ };
9713
+ function readBody(req) {
9714
+ return new Promise((resolve$1, reject) => {
9715
+ const chunks = [];
9716
+ req.on("data", (chunk) => chunks.push(chunk));
9717
+ req.once("end", () => resolve$1(Buffer.concat(chunks).toString("utf8")));
9718
+ req.once("error", reject);
9719
+ });
9720
+ }
9721
+ /**
9722
+ * 로컬 실행(매뉴얼 「2. 로컬에서 실행하기」) — 번들을 이 프로세스에서 불러 `/_trigger`(이벤트)·`/_http/*`(HTTP 핸들러)·`/`(앱 화면)를 받는다.
9723
+ * 설치 토큰은 `POST …/dev-token`(1시간)으로 받고 만료 전에 다시 받는다. `--store`가 없으면 토큰 없이 돈다(`ctx.api`는 401).
9724
+ */
9725
+ async function appDev(flags, io) {
9726
+ const dir = appDir(flags, io);
9727
+ const state = requireState(dir);
9728
+ const { manifest } = loadManifest(dir);
9729
+ const { app } = await loadBundle(dir, await bundleServer(dir));
9730
+ const port = Number(flags.port ?? io.env.SAYREN_APP_PORT ?? APP_DEV_PORT);
9731
+ if (!Number.isInteger(port) || port < 1 || port > 65535) throw new CliError(cli_app_port_invalid({ value: String(flags.port) }));
9732
+ const storeId = flags.store?.trim() || io.env.SAYREN_STORE_ID?.trim() || null;
9733
+ const auth = storeId ? await developerAuth(flags, dir, io) : null;
9734
+ let token = null;
9735
+ const ensureToken = async () => {
9736
+ if (!auth || !storeId) return null;
9737
+ const now = io.now?.() ?? Date.now();
9738
+ if (token && Date.parse(token.expiresAt) - now > DEV_TOKEN_REFRESH_MARGIN_MS) return token;
9739
+ token = await devApi(auth, io, "POST", `/apps/${state.appId}/dev-token`, { storeId });
9740
+ return token;
9741
+ };
9742
+ await ensureToken();
9743
+ const local = () => localSettingsOf(manifest, readEnvFile(dir));
9744
+ const apiBaseUrl = `${state.apiOrigin}/v1`;
9745
+ const uiRoot = join(dir, UI_DIR);
9746
+ const handle = async (req, res) => {
9747
+ const url = new URL(req.url ?? "/", `http://localhost:${port}`);
9748
+ try {
9749
+ if (req.method === "POST" && url.pathname === "/_trigger") {
9750
+ const body = JSON.parse(await readBody(req) || "{}");
9751
+ if (!body.type) {
9752
+ res.writeHead(400, { "content-type": "application/json" });
9753
+ res.end(JSON.stringify({ error: "TYPE_REQUIRED" }));
9754
+ return;
9755
+ }
9756
+ const { settings, secrets } = local();
9757
+ const result = await invokeLocal(app, devEnvelope({
9758
+ kind: "event",
9759
+ token: await ensureToken(),
9760
+ apiBaseUrl,
9761
+ appId: state.appId,
9762
+ settings,
9763
+ secrets,
9764
+ event: {
9765
+ type: body.type,
9766
+ data: body.data ?? {}
9767
+ }
9768
+ }));
9769
+ printResult(`[event] ${body.type}`, result, io);
9770
+ res.writeHead(200, { "content-type": "application/json" });
9771
+ res.end(JSON.stringify(result));
9772
+ return;
9773
+ }
9774
+ if (url.pathname.startsWith("/_http/")) {
9775
+ const headers = {};
9776
+ for (const [key, value] of Object.entries(req.headers)) if (typeof value === "string" && key !== "host") headers[key] = value;
9777
+ const method = (req.method ?? "GET").toUpperCase();
9778
+ const { settings, secrets } = local();
9779
+ const result = await invokeLocal(app, devEnvelope({
9780
+ kind: "http",
9781
+ token: await ensureToken(),
9782
+ apiBaseUrl,
9783
+ appId: state.appId,
9784
+ settings,
9785
+ secrets,
9786
+ request: {
9787
+ method,
9788
+ path: `${url.pathname.slice(6)}${url.search}`,
9789
+ headers,
9790
+ body: method === "GET" ? null : await readBody(req)
9791
+ }
9792
+ }));
9793
+ printResult(`[http] ${method} ${url.pathname}`, result, io);
9794
+ if (!result.response) {
9795
+ res.writeHead(500, { "content-type": "application/json" });
9796
+ res.end(JSON.stringify({
9797
+ error: result.outcome,
9798
+ message: result.errorMessage
9799
+ }));
9800
+ return;
9801
+ }
9802
+ res.writeHead(result.response.status, result.response.headers);
9803
+ res.end(result.response.body ?? "");
9804
+ return;
9805
+ }
9806
+ const file = resolve(uiRoot, url.pathname === "/" ? "index.html" : url.pathname.slice(1));
9807
+ if (file.startsWith(uiRoot) && existsSync(file) && statSync(file).isFile()) {
9808
+ res.writeHead(200, { "content-type": MIME[extname(file)] ?? "application/octet-stream" });
9809
+ res.end(readFileSync(file));
9810
+ return;
9811
+ }
9812
+ res.writeHead(404, { "content-type": "text/plain; charset=utf-8" });
9813
+ res.end("not found");
9814
+ } catch (error) {
9815
+ io.err(cli_app_dev_error({ message: error instanceof Error ? error.message : String(error) }));
9816
+ if (!res.headersSent) res.writeHead(500, { "content-type": "application/json" });
9817
+ res.end(JSON.stringify({ error: "DEV_ERROR" }));
9818
+ }
9819
+ };
9820
+ const serverHandle = createServer((req, res) => {
9821
+ handle(req, res);
9822
+ });
9823
+ await new Promise((resolveListen, reject) => {
9824
+ serverHandle.once("error", reject);
9825
+ serverHandle.listen(port, "127.0.0.1", () => resolveListen());
9826
+ });
9827
+ io.out(cli_app_dev_listening({
9828
+ port: String(port),
9829
+ store: storeId ?? "-",
9830
+ events: manifest.events.join(", ") || "-"
9831
+ }));
9832
+ await new Promise((resolveClose) => {
9833
+ const stop = () => {
9834
+ serverHandle.close();
9835
+ resolveClose();
9836
+ };
9837
+ if (io.signal) if (io.signal.aborted) stop();
9838
+ else io.signal.addEventListener("abort", stop, { once: true });
9839
+ else {
9840
+ process.once("SIGINT", stop);
9841
+ process.once("SIGTERM", stop);
9842
+ }
9843
+ });
9844
+ return 0;
9845
+ }
9846
+ async function appTrigger(type, flags, io) {
9847
+ if (!type) throw new CliError(cli_app_trigger_type_required());
9848
+ let data = {};
9849
+ if (flags.data) try {
9850
+ data = JSON.parse(flags.data);
9851
+ } catch {
9852
+ throw new CliError(cli_app_trigger_data_invalid());
9853
+ }
9854
+ if (flags.order) data = {
9855
+ ...data,
9856
+ orderId: flags.order
9857
+ };
9858
+ const port = Number(flags.port ?? io.env.SAYREN_APP_PORT ?? APP_DEV_PORT);
9859
+ const res = await io.fetch(`http://127.0.0.1:${port}/_trigger`, {
9860
+ method: "POST",
9861
+ headers: { "content-type": "application/json" },
9862
+ body: JSON.stringify({
9863
+ type,
9864
+ data
9865
+ })
9866
+ });
9867
+ if (!res.ok) throw new CliError(cli_app_trigger_failed({ status: String(res.status) }));
9868
+ const result = await res.json();
9869
+ printResult(`[event] ${type}`, result, io);
9870
+ return result.outcome === "OK" ? 0 : 1;
9871
+ }
9872
+ async function appMain(positional, flags, io) {
9873
+ const [sub, ...rest] = positional;
9874
+ switch (sub) {
9875
+ case "init": return appInit(rest[0], flags, io);
9876
+ case "verify": return appVerify(flags, io);
9877
+ case "deploy": return appDeploy(flags, io);
9878
+ case "release": return appRelease(rest[0], flags, io);
9879
+ case "status": return appStatus(flags, io);
9880
+ case "logs": return appLogs(flags, io);
9881
+ case "secret": return appSecret(rest[0], rest[1], flags, io);
9882
+ case "dev-store": return appDevStore(rest[0], rest.slice(1).join(" ") || void 0, flags, io);
9883
+ case "dev": return appDev(flags, io);
9884
+ case "trigger": return appTrigger(rest[0], flags, io);
9885
+ default: throw new CliError(cli_app_subcommand_unknown({ command: sub ?? "" }));
9886
+ }
9887
+ }
9888
+
7778
9889
  //#endregion
7779
9890
  //#region ../mcp/src/rules.ts
7780
9891
  /** 규칙의 심각도 — 없으면 `error` */
@@ -7990,6 +10101,16 @@ const RULES = [
7990
10101
  templateFile: "src/lib/ordering.ts",
7991
10102
  severity: "warning"
7992
10103
  }),
10104
+ defineRule({
10105
+ id: "product-link",
10106
+ title: mcp_rule_product_link_title,
10107
+ why: mcp_rule_product_link_why,
10108
+ fix: mcp_rule_product_link_fix,
10109
+ example: mcp_rule_product_link_example,
10110
+ doc: "/guides/order-numbers",
10111
+ templateFile: "src/lib/product-path.ts",
10112
+ severity: "warning"
10113
+ }),
7993
10114
  defineRule({
7994
10115
  id: "server-only-import",
7995
10116
  title: mcp_rule_server_only_import_title,
@@ -8085,6 +10206,8 @@ function verifySources(files, options = {}) {
8085
10206
  inFile("custom-input-private", file, mcp_verify_custom_input_private({ where: where() }), pattern);
8086
10207
  break;
8087
10208
  }
10209
+ const productIdLink = /params=\{\{\s*productId:\s*[\w.?]+\.productId\s*\}\}/;
10210
+ if (/\/products\/\$productId/.test(file.content) && productIdLink.test(file.content)) inFile("product-link", file, mcp_verify_product_link(), productIdLink);
8088
10211
  const analyticsFactory = /createAnalytics\(/;
8089
10212
  if (isServer$1 && analyticsFactory.test(file.content)) inFile("analytics-start", file, mcp_verify_analytics_start_server_file(), analyticsFactory);
8090
10213
  if (isServer$1 && /createStorefrontClient\(/.test(file.content) && !/analyticsIdsFromCookie|visitorId/.test(file.content)) inFile("analytics-ids", file, mcp_verify_analytics_ids(), /createStorefrontClient\(/);
@@ -8833,6 +10956,55 @@ function lockImporterSpecifiers(lock) {
8833
10956
  return out;
8834
10957
  }
8835
10958
 
10959
+ //#endregion
10960
+ //#region src/local-build.ts
10961
+ /** 실패할 때 보여 주는 빌드 출력 줄 수 */
10962
+ const OUTPUT_TAIL_LINES = 40;
10963
+ /** 모아 두는 출력 상한(문자) — 긴 빌드 로그를 다 쥐고 있지 않는다 */
10964
+ const OUTPUT_KEEP_CHARS = 64 * 1024;
10965
+ /** 빌드를 돌릴 수 있는 폴더인가 — `build` 스크립트와 설치된 의존성(`node_modules`)이 있어야 한다 */
10966
+ function planLocalBuild(dir) {
10967
+ let scripts;
10968
+ try {
10969
+ scripts = JSON.parse(readFileSync(join(dir, "package.json"), "utf8")).scripts;
10970
+ } catch {
10971
+ return { kind: "no-script" };
10972
+ }
10973
+ const build = scripts && typeof scripts === "object" ? scripts.build : void 0;
10974
+ if (typeof build !== "string" || !build.trim()) return { kind: "no-script" };
10975
+ if (!existsSync(join(dir, "node_modules"))) return { kind: "no-deps" };
10976
+ return { kind: "run" };
10977
+ }
10978
+ /** `npm run build`를 돌린다. 출력은 모아 두고(실패할 때 꼬리를 보여 준다) 화면에 흘리지 않는다 */
10979
+ function runNpmBuild(dir, env) {
10980
+ return new Promise((resolve$1, reject) => {
10981
+ let output = "";
10982
+ const keep = (chunk) => {
10983
+ output = (output + chunk.toString("utf8")).slice(-OUTPUT_KEEP_CHARS);
10984
+ };
10985
+ const child = spawn("npm", ["run", "build"], {
10986
+ cwd: dir,
10987
+ env,
10988
+ stdio: [
10989
+ "ignore",
10990
+ "pipe",
10991
+ "pipe"
10992
+ ],
10993
+ shell: process.platform === "win32"
10994
+ });
10995
+ child.stdout?.on("data", keep);
10996
+ child.stderr?.on("data", keep);
10997
+ child.once("error", reject);
10998
+ child.once("close", (code) => resolve$1({
10999
+ code,
11000
+ output: tailOf(output)
11001
+ }));
11002
+ });
11003
+ }
11004
+ function tailOf(output, lines = OUTPUT_TAIL_LINES) {
11005
+ return output.trimEnd().split(/\r?\n/).slice(-lines).join("\n");
11006
+ }
11007
+
8836
11008
  //#endregion
8837
11009
  //#region src/commands.ts
8838
11010
  /** 종료 코드 — 0 성공 · 1 실패 · 3 발행이 승인 대기(에이전트 토큰) */
@@ -8889,13 +11061,20 @@ async function pull(flags, io) {
8889
11061
  storeId: source.storeId,
8890
11062
  project: flags.project
8891
11063
  }));
11064
+ return receiveSource(client, auth, source, flags, io, authDir);
11065
+ }
11066
+ /**
11067
+ * 받은 작업 트리를 폴더에 쓰고 받은 폴더 파일(`.sayren/state.json`·`.env`·`.mcp.json`·`.gitignore`)을 맞춘다. `pull`과 `init`(#101)이 같이 쓴다.
11068
+ * 대상은 `--dir` → 받은 폴더 안이면 그 폴더 → 상점 코드다. 비어 있지 않은 폴더는 `--force`일 때 같은 사이트를 받은 폴더만 다시 받는다.
11069
+ */
11070
+ async function receiveSource(client, auth, source, flags, io, migratedDir) {
8892
11071
  const store = {
8893
11072
  storeId: source.storeId,
8894
11073
  storeCode: source.storeCode
8895
11074
  };
8896
11075
  const defaultDir = store.storeCode || source.siteId;
8897
11076
  const target = !flags.dir && isPulledDir(io.cwd) ? io.cwd : resolve(io.cwd, flags.dir ?? defaultDir);
8898
- if (target !== authDir) migrateLegacy(target, io.out);
11077
+ if (target !== migratedDir) migrateLegacy(target, io.out);
8899
11078
  const existing = existsSync(target) ? readdirSync(target) : [];
8900
11079
  if (existing.length > 0) {
8901
11080
  if (!flags.force) throw new CliError(cli_pull_dir_not_empty({ dir: relativeOf(io, target) }));
@@ -9017,6 +11196,80 @@ async function pull(flags, io) {
9017
11196
  io.out(cli_pull_next_steps({ dir: pulledDir }));
9018
11197
  return 0;
9019
11198
  }
11199
+ /**
11200
+ * `sayren init [폴더]`(#101) — 템플릿을 골라 호스팅 사이트를 만들고(`POST /v1/storefront/site`) `pull`과 같은 폴더를 만든다.
11201
+ * 사이트가 이미 있으면 만들지 않고 `pull`을 안내한다(상점당 열린 사이트는 하나다). 만들기는 상점 한도(30일 3회)를 쓰므로 확인을 묻는다.
11202
+ * 토큰은 `storefront:rw`가 있어야 한다(로그인 토큰 `CLI_LOGIN_SCOPE`에 있다). 에이전트 토큰이어도 만들기는 승인 대상이 아니다
11203
+ * (쓰기 정책 표에 없다 — 오픈 준비 중으로 시작해 구매자 화면을 바꾸지 않는다).
11204
+ */
11205
+ async function init(flags, io) {
11206
+ const target = flags.dir ? resolve(io.cwd, flags.dir) : null;
11207
+ if (target && existsSync(target) && readdirSync(target).length > 0) throw new CliError(cli_init_dir_not_empty({ dir: relativeOf(io, target) }));
11208
+ if (!target && isPulledDir(io.cwd)) throw new CliError(cli_init_inside_pulled());
11209
+ const authDir = target && existsSync(target) ? target : io.cwd;
11210
+ const { auth, client } = await apiFor(flags, authDir, null, io);
11211
+ const storeId = auth.storeId ?? "<storeId>";
11212
+ const hosting = await client.storefront.get();
11213
+ if (hosting.site) {
11214
+ io.out(cli_init_site_url({ url: hosting.site.url }));
11215
+ throw new CliError(cli_init_site_exists({ storeId }));
11216
+ }
11217
+ if (!hosting.enabled) throw new CliError(cli_init_hosting_disabled());
11218
+ if (!hosting.editingEnabled) throw new CliError(cli_pull_editing_disabled());
11219
+ const template = await pickTemplate(await client.storefront.listTemplates(), flags.template, io);
11220
+ io.out(cli_init_summary({
11221
+ name: template.name,
11222
+ templateId: template.templateId,
11223
+ version: template.version,
11224
+ storeId
11225
+ }));
11226
+ if (!flags.yes) {
11227
+ if (!io.confirm) throw new CliError(cli_init_yes_required());
11228
+ if (!await io.confirm(cli_init_confirm())) {
11229
+ io.out(cli_cancelled());
11230
+ return 1;
11231
+ }
11232
+ }
11233
+ let site;
11234
+ try {
11235
+ site = await client.storefront.create({ templateId: template.templateId });
11236
+ } catch (error) {
11237
+ const code = codeOf(error);
11238
+ if (code === "STOREFRONT_SITE_EXISTS") throw new CliError(cli_init_site_exists({ storeId }));
11239
+ if (code === "STOREFRONT_SLUG_TAKEN") throw new CliError(cli_init_slug_taken());
11240
+ throw error;
11241
+ }
11242
+ io.out(cli_init_created({ url: site.url }));
11243
+ try {
11244
+ return await receiveSource(client, auth, await client.storefront.getSource(), { dir: flags.dir }, io, authDir);
11245
+ } catch (error) {
11246
+ io.err(cli_init_pull_failed({ storeId }));
11247
+ throw error;
11248
+ }
11249
+ }
11250
+ /** `--template`이 있으면 그 템플릿, 없으면 대화형 선택. 비대화형이면 `--template`이 있어야 한다 */
11251
+ async function pickTemplate(templates, wanted, io) {
11252
+ if (templates.length === 0) throw new CliError(cli_init_no_templates());
11253
+ const ids = templates.map((t) => t.templateId).join(", ");
11254
+ if (wanted) {
11255
+ const found = templates.find((t) => t.templateId === wanted);
11256
+ if (!found) throw new CliError(cli_init_template_unknown({
11257
+ templateId: wanted,
11258
+ ids
11259
+ }));
11260
+ return found;
11261
+ }
11262
+ const labels = templates.map((t) => cli_init_template_option({
11263
+ templateId: t.templateId,
11264
+ name: t.name,
11265
+ version: t.version,
11266
+ description: t.description
11267
+ }));
11268
+ const picked = io.select ? await io.select(cli_init_template_prompt(), labels) : null;
11269
+ const index = picked ? labels.indexOf(picked) : -1;
11270
+ if (index < 0) throw new CliError(cli_init_template_required({ list: labels.map((label) => ` ${label}`).join("\n") }));
11271
+ return templates[index];
11272
+ }
9020
11273
  async function verify(flags, io) {
9021
11274
  const dir = resolve(io.cwd, flags.dir ?? ".");
9022
11275
  const tree = collectTree(dir);
@@ -9073,6 +11326,7 @@ async function deploy(flags, io) {
9073
11326
  const checks = runLocalChecks(tree);
9074
11327
  printChecks(tree, checks, io);
9075
11328
  if (checks.blockingRules.length > 0 || checks.problems.length > 0) throw new CliError(cli_deploy_checks_failed());
11329
+ await localBuild(dir, flags.skipBuild === true, io);
9076
11330
  const site = (await client.storefront.get()).site;
9077
11331
  if (!site || site.siteId !== rc.siteId) throw new CliError(cli_deploy_site_mismatch({ siteId: rc.siteId }));
9078
11332
  if (flags.force && !flags.yes) {
@@ -9144,6 +11398,42 @@ async function deploy(flags, io) {
9144
11398
  throw error;
9145
11399
  }
9146
11400
  }
11401
+ /**
11402
+ * 배포 전 로컬 빌드(#103). 의존성이 설치돼 있고 `build` 스크립트가 있으면 돌리고, 실패하면(시작하지 못한 것 포함) 올리지 않는다.
11403
+ * 의존성이 없으면 알리고 건너뛴다 — 셀러가 install하지 않은 폴더에서도 배포는 된다(서버가 다시 빌드한다).
11404
+ */
11405
+ async function localBuild(dir, skip, io) {
11406
+ if (skip) {
11407
+ io.out(cli_deploy_build_local_skipped_flag());
11408
+ return;
11409
+ }
11410
+ const plan = planLocalBuild(dir);
11411
+ if (plan.kind === "no-script") {
11412
+ io.out(cli_deploy_build_local_no_script());
11413
+ return;
11414
+ }
11415
+ if (plan.kind === "no-deps") {
11416
+ io.out(cli_deploy_build_local_no_deps());
11417
+ return;
11418
+ }
11419
+ io.out(cli_deploy_build_local_running());
11420
+ const started = io.now?.() ?? Date.now();
11421
+ let result;
11422
+ try {
11423
+ result = await (io.runBuild ?? ((at) => runNpmBuild(at, io.env)))(dir);
11424
+ } catch (error) {
11425
+ throw new CliError(cli_deploy_build_local_spawn_failed({ message: error instanceof Error ? error.message : String(error) }));
11426
+ }
11427
+ if (result.code !== 0) {
11428
+ if (result.output) {
11429
+ io.err(cli_deploy_build_local_output({ count: OUTPUT_TAIL_LINES }));
11430
+ for (const line of result.output.split("\n")) io.err(` ${line}`);
11431
+ }
11432
+ throw new CliError(cli_deploy_build_local_failed({ code: String(result.code ?? "-") }));
11433
+ }
11434
+ const seconds = Math.round(((io.now?.() ?? Date.now()) - started) / 1e3);
11435
+ io.out(cli_deploy_build_local_passed({ seconds }));
11436
+ }
9147
11437
  async function replaceSource(client, tree, rc, force, io) {
9148
11438
  const files = tree.files.map((file) => ({
9149
11439
  path: file.path,
@@ -9470,16 +11760,25 @@ const VALUE_FLAGS = new Set([
9470
11760
  "message",
9471
11761
  "api-origin",
9472
11762
  "store",
9473
- "accounts-origin"
11763
+ "accounts-origin",
11764
+ "template",
11765
+ "key",
11766
+ "name",
11767
+ "port",
11768
+ "since",
11769
+ "data",
11770
+ "order"
9474
11771
  ]);
9475
11772
  const BOOL_FLAGS = new Set([
9476
11773
  "force",
9477
11774
  "yes",
9478
11775
  "no-publish",
11776
+ "skip-build",
9479
11777
  "help",
9480
11778
  "version",
9481
11779
  "device",
9482
- "paste"
11780
+ "paste",
11781
+ "tail"
9483
11782
  ]);
9484
11783
  function parseArgs(argv) {
9485
11784
  const out = {
@@ -9491,7 +11790,11 @@ function parseArgs(argv) {
9491
11790
  const arg = argv[i];
9492
11791
  if (arg === "-h") out.flags.help = true;
9493
11792
  else if (arg === "-v") out.flags.version = true;
9494
- else if (arg.startsWith("--")) {
11793
+ else if (arg === "-m") {
11794
+ const value = argv[++i];
11795
+ if (value === void 0 || value.startsWith("--")) throw new CliError(cli_flag_value_required({ name: "message" }));
11796
+ out.flags.message = value;
11797
+ } else if (arg.startsWith("--")) {
9495
11798
  const body = arg.slice(2);
9496
11799
  const eq = body.indexOf("=");
9497
11800
  const name = eq < 0 ? body : body.slice(0, eq);
@@ -9536,6 +11839,26 @@ async function main(argv, io) {
9536
11839
  accountsOrigin: str(parsed.flags["accounts-origin"])
9537
11840
  };
9538
11841
  switch (parsed.command) {
11842
+ case "app": return appMain(parsed.positional, {
11843
+ token: str(parsed.flags.token),
11844
+ key: str(parsed.flags.key),
11845
+ apiOrigin: str(parsed.flags["api-origin"]),
11846
+ dir: str(parsed.flags.dir),
11847
+ store: str(parsed.flags.store),
11848
+ message: str(parsed.flags.message),
11849
+ name: str(parsed.flags.name),
11850
+ port: str(parsed.flags.port),
11851
+ since: str(parsed.flags.since),
11852
+ tail: parsed.flags.tail === true,
11853
+ data: str(parsed.flags.data),
11854
+ order: str(parsed.flags.order),
11855
+ yes: parsed.flags.yes === true
11856
+ }, io);
11857
+ case "init": return init({
11858
+ ...common,
11859
+ template: str(parsed.flags.template),
11860
+ yes: parsed.flags.yes === true
11861
+ }, io);
9539
11862
  case "pull": return pull({
9540
11863
  ...common,
9541
11864
  project: str(parsed.flags.project),
@@ -9547,6 +11870,7 @@ async function main(argv, io) {
9547
11870
  force: parsed.flags.force === true,
9548
11871
  yes: parsed.flags.yes === true,
9549
11872
  publish: parsed.flags["no-publish"] !== true,
11873
+ skipBuild: parsed.flags["skip-build"] === true,
9550
11874
  message: str(parsed.flags.message)
9551
11875
  }, io);
9552
11876
  case "status": return status(common, io);
@@ -9576,7 +11900,7 @@ function defaultIo() {
9576
11900
  return {
9577
11901
  cwd: process.cwd(),
9578
11902
  env: process.env,
9579
- fetch: (input, init) => fetch(input, init),
11903
+ fetch: (input, init$1) => fetch(input, init$1),
9580
11904
  out: (line) => console.log(line),
9581
11905
  err: (line) => console.error(line),
9582
11906
  confirm: stdin.isTTY ? async (question) => /^(y|yes|예|네)$/i.test((await ask(`${question} (y/N) `) ?? "").trim()) : null,