sayren 0.3.3 → 0.4.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.
- package/dist/index.mjs +858 -14
- package/package.json +2 -2
package/dist/index.mjs
CHANGED
|
@@ -1278,6 +1278,150 @@ const cli_deploy_build_in_progress = ((inputs = {}, options = {}) => {
|
|
|
1278
1278
|
return ko_cli_deploy_build_in_progress(inputs);
|
|
1279
1279
|
});
|
|
1280
1280
|
|
|
1281
|
+
//#endregion
|
|
1282
|
+
//#region ../i18n/src/paraglide/messages/cli_deploy_build_local_failed.js
|
|
1283
|
+
/** @typedef {import('../runtime.js').LocalizedString} LocalizedString */
|
|
1284
|
+
/** @typedef {{ code: NonNullable<unknown> }} Cli_Deploy_Build_Local_FailedInputs */
|
|
1285
|
+
const ko_cli_deploy_build_local_failed = (i) => {
|
|
1286
|
+
return `로컬 빌드가 실패해 올리지 않았습니다(종료 코드 ${i?.code}). 위 출력을 확인해 고친 뒤 다시 배포하십시오. 빌드를 확인하지 않고 올리려면 --skip-build를 붙이십시오`;
|
|
1287
|
+
};
|
|
1288
|
+
/**
|
|
1289
|
+
|
|
1290
|
+
* @param {Cli_Deploy_Build_Local_FailedInputs} inputs
|
|
1291
|
+
* @param {{ locale?: "ko" }} options
|
|
1292
|
+
* @returns {LocalizedString}
|
|
1293
|
+
*/
|
|
1294
|
+
const cli_deploy_build_local_failed = ((inputs, options = {}) => {
|
|
1295
|
+
experimentalStaticLocale ?? options.locale ?? getLocale();
|
|
1296
|
+
return ko_cli_deploy_build_local_failed(inputs);
|
|
1297
|
+
});
|
|
1298
|
+
|
|
1299
|
+
//#endregion
|
|
1300
|
+
//#region ../i18n/src/paraglide/messages/cli_deploy_build_local_no_deps.js
|
|
1301
|
+
/** @typedef {import('../runtime.js').LocalizedString} LocalizedString */
|
|
1302
|
+
/** @typedef {{}} Cli_Deploy_Build_Local_No_DepsInputs */
|
|
1303
|
+
const ko_cli_deploy_build_local_no_deps = () => {
|
|
1304
|
+
return `의존성이 설치되지 않아(node_modules 없음) 로컬 빌드를 건너뜁니다. npm install --ignore-scripts 뒤 배포하면 올리기 전에 빌드를 확인합니다`;
|
|
1305
|
+
};
|
|
1306
|
+
/**
|
|
1307
|
+
|
|
1308
|
+
* @param {Cli_Deploy_Build_Local_No_DepsInputs} inputs
|
|
1309
|
+
* @param {{ locale?: "ko" }} options
|
|
1310
|
+
* @returns {LocalizedString}
|
|
1311
|
+
*/
|
|
1312
|
+
const cli_deploy_build_local_no_deps = ((inputs = {}, options = {}) => {
|
|
1313
|
+
experimentalStaticLocale ?? options.locale ?? getLocale();
|
|
1314
|
+
return ko_cli_deploy_build_local_no_deps(inputs);
|
|
1315
|
+
});
|
|
1316
|
+
|
|
1317
|
+
//#endregion
|
|
1318
|
+
//#region ../i18n/src/paraglide/messages/cli_deploy_build_local_no_script.js
|
|
1319
|
+
/** @typedef {import('../runtime.js').LocalizedString} LocalizedString */
|
|
1320
|
+
/** @typedef {{}} Cli_Deploy_Build_Local_No_ScriptInputs */
|
|
1321
|
+
const ko_cli_deploy_build_local_no_script = () => {
|
|
1322
|
+
return `package.json에 build 스크립트가 없어 로컬 빌드를 건너뜁니다`;
|
|
1323
|
+
};
|
|
1324
|
+
/**
|
|
1325
|
+
|
|
1326
|
+
* @param {Cli_Deploy_Build_Local_No_ScriptInputs} inputs
|
|
1327
|
+
* @param {{ locale?: "ko" }} options
|
|
1328
|
+
* @returns {LocalizedString}
|
|
1329
|
+
*/
|
|
1330
|
+
const cli_deploy_build_local_no_script = ((inputs = {}, options = {}) => {
|
|
1331
|
+
experimentalStaticLocale ?? options.locale ?? getLocale();
|
|
1332
|
+
return ko_cli_deploy_build_local_no_script(inputs);
|
|
1333
|
+
});
|
|
1334
|
+
|
|
1335
|
+
//#endregion
|
|
1336
|
+
//#region ../i18n/src/paraglide/messages/cli_deploy_build_local_output.js
|
|
1337
|
+
/** @typedef {import('../runtime.js').LocalizedString} LocalizedString */
|
|
1338
|
+
/** @typedef {{ count: NonNullable<unknown> }} Cli_Deploy_Build_Local_OutputInputs */
|
|
1339
|
+
const ko_cli_deploy_build_local_output = (i) => {
|
|
1340
|
+
return `빌드 출력(마지막 ${i?.count}줄):`;
|
|
1341
|
+
};
|
|
1342
|
+
/**
|
|
1343
|
+
|
|
1344
|
+
* @param {Cli_Deploy_Build_Local_OutputInputs} inputs
|
|
1345
|
+
* @param {{ locale?: "ko" }} options
|
|
1346
|
+
* @returns {LocalizedString}
|
|
1347
|
+
*/
|
|
1348
|
+
const cli_deploy_build_local_output = ((inputs, options = {}) => {
|
|
1349
|
+
experimentalStaticLocale ?? options.locale ?? getLocale();
|
|
1350
|
+
return ko_cli_deploy_build_local_output(inputs);
|
|
1351
|
+
});
|
|
1352
|
+
|
|
1353
|
+
//#endregion
|
|
1354
|
+
//#region ../i18n/src/paraglide/messages/cli_deploy_build_local_passed.js
|
|
1355
|
+
/** @typedef {import('../runtime.js').LocalizedString} LocalizedString */
|
|
1356
|
+
/** @typedef {{ seconds: NonNullable<unknown> }} Cli_Deploy_Build_Local_PassedInputs */
|
|
1357
|
+
const ko_cli_deploy_build_local_passed = (i) => {
|
|
1358
|
+
return `로컬 빌드 통과(${i?.seconds}초)`;
|
|
1359
|
+
};
|
|
1360
|
+
/**
|
|
1361
|
+
|
|
1362
|
+
* @param {Cli_Deploy_Build_Local_PassedInputs} inputs
|
|
1363
|
+
* @param {{ locale?: "ko" }} options
|
|
1364
|
+
* @returns {LocalizedString}
|
|
1365
|
+
*/
|
|
1366
|
+
const cli_deploy_build_local_passed = ((inputs, options = {}) => {
|
|
1367
|
+
experimentalStaticLocale ?? options.locale ?? getLocale();
|
|
1368
|
+
return ko_cli_deploy_build_local_passed(inputs);
|
|
1369
|
+
});
|
|
1370
|
+
|
|
1371
|
+
//#endregion
|
|
1372
|
+
//#region ../i18n/src/paraglide/messages/cli_deploy_build_local_running.js
|
|
1373
|
+
/** @typedef {import('../runtime.js').LocalizedString} LocalizedString */
|
|
1374
|
+
/** @typedef {{}} Cli_Deploy_Build_Local_RunningInputs */
|
|
1375
|
+
const ko_cli_deploy_build_local_running = () => {
|
|
1376
|
+
return `로컬 빌드(npm run build)를 실행합니다. 서버 빌드가 실패할 것을 올리기 전에 확인합니다`;
|
|
1377
|
+
};
|
|
1378
|
+
/**
|
|
1379
|
+
|
|
1380
|
+
* @param {Cli_Deploy_Build_Local_RunningInputs} inputs
|
|
1381
|
+
* @param {{ locale?: "ko" }} options
|
|
1382
|
+
* @returns {LocalizedString}
|
|
1383
|
+
*/
|
|
1384
|
+
const cli_deploy_build_local_running = ((inputs = {}, options = {}) => {
|
|
1385
|
+
experimentalStaticLocale ?? options.locale ?? getLocale();
|
|
1386
|
+
return ko_cli_deploy_build_local_running(inputs);
|
|
1387
|
+
});
|
|
1388
|
+
|
|
1389
|
+
//#endregion
|
|
1390
|
+
//#region ../i18n/src/paraglide/messages/cli_deploy_build_local_skipped_flag.js
|
|
1391
|
+
/** @typedef {import('../runtime.js').LocalizedString} LocalizedString */
|
|
1392
|
+
/** @typedef {{}} Cli_Deploy_Build_Local_Skipped_FlagInputs */
|
|
1393
|
+
const ko_cli_deploy_build_local_skipped_flag = () => {
|
|
1394
|
+
return `로컬 빌드를 건너뜁니다(--skip-build). 서버 빌드가 같은 빌드를 다시 합니다`;
|
|
1395
|
+
};
|
|
1396
|
+
/**
|
|
1397
|
+
|
|
1398
|
+
* @param {Cli_Deploy_Build_Local_Skipped_FlagInputs} inputs
|
|
1399
|
+
* @param {{ locale?: "ko" }} options
|
|
1400
|
+
* @returns {LocalizedString}
|
|
1401
|
+
*/
|
|
1402
|
+
const cli_deploy_build_local_skipped_flag = ((inputs = {}, options = {}) => {
|
|
1403
|
+
experimentalStaticLocale ?? options.locale ?? getLocale();
|
|
1404
|
+
return ko_cli_deploy_build_local_skipped_flag(inputs);
|
|
1405
|
+
});
|
|
1406
|
+
|
|
1407
|
+
//#endregion
|
|
1408
|
+
//#region ../i18n/src/paraglide/messages/cli_deploy_build_local_spawn_failed.js
|
|
1409
|
+
/** @typedef {import('../runtime.js').LocalizedString} LocalizedString */
|
|
1410
|
+
/** @typedef {{ message: NonNullable<unknown> }} Cli_Deploy_Build_Local_Spawn_FailedInputs */
|
|
1411
|
+
const ko_cli_deploy_build_local_spawn_failed = (i) => {
|
|
1412
|
+
return `로컬 빌드를 시작하지 못해 올리지 않았습니다(${i?.message}). npm이 PATH에 있는지 확인하거나 --skip-build를 붙이십시오`;
|
|
1413
|
+
};
|
|
1414
|
+
/**
|
|
1415
|
+
|
|
1416
|
+
* @param {Cli_Deploy_Build_Local_Spawn_FailedInputs} inputs
|
|
1417
|
+
* @param {{ locale?: "ko" }} options
|
|
1418
|
+
* @returns {LocalizedString}
|
|
1419
|
+
*/
|
|
1420
|
+
const cli_deploy_build_local_spawn_failed = ((inputs, options = {}) => {
|
|
1421
|
+
experimentalStaticLocale ?? options.locale ?? getLocale();
|
|
1422
|
+
return ko_cli_deploy_build_local_spawn_failed(inputs);
|
|
1423
|
+
});
|
|
1424
|
+
|
|
1281
1425
|
//#endregion
|
|
1282
1426
|
//#region ../i18n/src/paraglide/messages/cli_deploy_build_started.js
|
|
1283
1427
|
/** @typedef {import('../runtime.js').LocalizedString} LocalizedString */
|
|
@@ -1890,6 +2034,295 @@ const cli_flag_value_required = ((inputs, options = {}) => {
|
|
|
1890
2034
|
return ko_cli_flag_value_required(inputs);
|
|
1891
2035
|
});
|
|
1892
2036
|
|
|
2037
|
+
//#endregion
|
|
2038
|
+
//#region ../i18n/src/paraglide/messages/cli_init_confirm.js
|
|
2039
|
+
/** @typedef {import('../runtime.js').LocalizedString} LocalizedString */
|
|
2040
|
+
/** @typedef {{}} Cli_Init_ConfirmInputs */
|
|
2041
|
+
const ko_cli_init_confirm = () => {
|
|
2042
|
+
return `사이트를 만드시겠습니까?`;
|
|
2043
|
+
};
|
|
2044
|
+
/**
|
|
2045
|
+
|
|
2046
|
+
* @param {Cli_Init_ConfirmInputs} inputs
|
|
2047
|
+
* @param {{ locale?: "ko" }} options
|
|
2048
|
+
* @returns {LocalizedString}
|
|
2049
|
+
*/
|
|
2050
|
+
const cli_init_confirm = ((inputs = {}, options = {}) => {
|
|
2051
|
+
experimentalStaticLocale ?? options.locale ?? getLocale();
|
|
2052
|
+
return ko_cli_init_confirm(inputs);
|
|
2053
|
+
});
|
|
2054
|
+
|
|
2055
|
+
//#endregion
|
|
2056
|
+
//#region ../i18n/src/paraglide/messages/cli_init_created.js
|
|
2057
|
+
/** @typedef {import('../runtime.js').LocalizedString} LocalizedString */
|
|
2058
|
+
/** @typedef {{ url: NonNullable<unknown> }} Cli_Init_CreatedInputs */
|
|
2059
|
+
const ko_cli_init_created = (i) => {
|
|
2060
|
+
return `사이트를 만들었습니다 — ${i?.url} (오픈 준비 중, 반영까지 1분 안팎)`;
|
|
2061
|
+
};
|
|
2062
|
+
/**
|
|
2063
|
+
|
|
2064
|
+
* @param {Cli_Init_CreatedInputs} inputs
|
|
2065
|
+
* @param {{ locale?: "ko" }} options
|
|
2066
|
+
* @returns {LocalizedString}
|
|
2067
|
+
*/
|
|
2068
|
+
const cli_init_created = ((inputs, options = {}) => {
|
|
2069
|
+
experimentalStaticLocale ?? options.locale ?? getLocale();
|
|
2070
|
+
return ko_cli_init_created(inputs);
|
|
2071
|
+
});
|
|
2072
|
+
|
|
2073
|
+
//#endregion
|
|
2074
|
+
//#region ../i18n/src/paraglide/messages/cli_init_dir_not_empty.js
|
|
2075
|
+
/** @typedef {import('../runtime.js').LocalizedString} LocalizedString */
|
|
2076
|
+
/** @typedef {{ dir: NonNullable<unknown> }} Cli_Init_Dir_Not_EmptyInputs */
|
|
2077
|
+
const ko_cli_init_dir_not_empty = (i) => {
|
|
2078
|
+
return `폴더가 비어 있지 않습니다: ${i?.dir}. 빈 폴더나 새 폴더 이름을 주십시오`;
|
|
2079
|
+
};
|
|
2080
|
+
/**
|
|
2081
|
+
|
|
2082
|
+
* @param {Cli_Init_Dir_Not_EmptyInputs} inputs
|
|
2083
|
+
* @param {{ locale?: "ko" }} options
|
|
2084
|
+
* @returns {LocalizedString}
|
|
2085
|
+
*/
|
|
2086
|
+
const cli_init_dir_not_empty = ((inputs, options = {}) => {
|
|
2087
|
+
experimentalStaticLocale ?? options.locale ?? getLocale();
|
|
2088
|
+
return ko_cli_init_dir_not_empty(inputs);
|
|
2089
|
+
});
|
|
2090
|
+
|
|
2091
|
+
//#endregion
|
|
2092
|
+
//#region ../i18n/src/paraglide/messages/cli_init_hosting_disabled.js
|
|
2093
|
+
/** @typedef {import('../runtime.js').LocalizedString} LocalizedString */
|
|
2094
|
+
/** @typedef {{}} Cli_Init_Hosting_DisabledInputs */
|
|
2095
|
+
const ko_cli_init_hosting_disabled = () => {
|
|
2096
|
+
return `지금은 새 호스팅 사이트를 만들 수 없습니다(호스팅 기능이 꺼져 있습니다)`;
|
|
2097
|
+
};
|
|
2098
|
+
/**
|
|
2099
|
+
|
|
2100
|
+
* @param {Cli_Init_Hosting_DisabledInputs} inputs
|
|
2101
|
+
* @param {{ locale?: "ko" }} options
|
|
2102
|
+
* @returns {LocalizedString}
|
|
2103
|
+
*/
|
|
2104
|
+
const cli_init_hosting_disabled = ((inputs = {}, options = {}) => {
|
|
2105
|
+
experimentalStaticLocale ?? options.locale ?? getLocale();
|
|
2106
|
+
return ko_cli_init_hosting_disabled(inputs);
|
|
2107
|
+
});
|
|
2108
|
+
|
|
2109
|
+
//#endregion
|
|
2110
|
+
//#region ../i18n/src/paraglide/messages/cli_init_inside_pulled.js
|
|
2111
|
+
/** @typedef {import('../runtime.js').LocalizedString} LocalizedString */
|
|
2112
|
+
/** @typedef {{}} Cli_Init_Inside_PulledInputs */
|
|
2113
|
+
const ko_cli_init_inside_pulled = () => {
|
|
2114
|
+
return `지금 폴더는 이미 받은 사이트 폴더입니다. 새 사이트는 다른 폴더에서 npx sayren init <폴더>로 만들고, 이 사이트를 다시 받으려면 npx sayren pull --force를 쓰십시오`;
|
|
2115
|
+
};
|
|
2116
|
+
/**
|
|
2117
|
+
|
|
2118
|
+
* @param {Cli_Init_Inside_PulledInputs} inputs
|
|
2119
|
+
* @param {{ locale?: "ko" }} options
|
|
2120
|
+
* @returns {LocalizedString}
|
|
2121
|
+
*/
|
|
2122
|
+
const cli_init_inside_pulled = ((inputs = {}, options = {}) => {
|
|
2123
|
+
experimentalStaticLocale ?? options.locale ?? getLocale();
|
|
2124
|
+
return ko_cli_init_inside_pulled(inputs);
|
|
2125
|
+
});
|
|
2126
|
+
|
|
2127
|
+
//#endregion
|
|
2128
|
+
//#region ../i18n/src/paraglide/messages/cli_init_no_templates.js
|
|
2129
|
+
/** @typedef {import('../runtime.js').LocalizedString} LocalizedString */
|
|
2130
|
+
/** @typedef {{}} Cli_Init_No_TemplatesInputs */
|
|
2131
|
+
const ko_cli_init_no_templates = () => {
|
|
2132
|
+
return `쓸 수 있는 템플릿이 없습니다`;
|
|
2133
|
+
};
|
|
2134
|
+
/**
|
|
2135
|
+
|
|
2136
|
+
* @param {Cli_Init_No_TemplatesInputs} inputs
|
|
2137
|
+
* @param {{ locale?: "ko" }} options
|
|
2138
|
+
* @returns {LocalizedString}
|
|
2139
|
+
*/
|
|
2140
|
+
const cli_init_no_templates = ((inputs = {}, options = {}) => {
|
|
2141
|
+
experimentalStaticLocale ?? options.locale ?? getLocale();
|
|
2142
|
+
return ko_cli_init_no_templates(inputs);
|
|
2143
|
+
});
|
|
2144
|
+
|
|
2145
|
+
//#endregion
|
|
2146
|
+
//#region ../i18n/src/paraglide/messages/cli_init_pull_failed.js
|
|
2147
|
+
/** @typedef {import('../runtime.js').LocalizedString} LocalizedString */
|
|
2148
|
+
/** @typedef {{ storeId: NonNullable<unknown> }} Cli_Init_Pull_FailedInputs */
|
|
2149
|
+
const ko_cli_init_pull_failed = (i) => {
|
|
2150
|
+
return `사이트는 만들었지만 소스를 받지 못했습니다. 다시 만들지 말고 npx sayren pull --project ${i?.storeId}로 받으십시오`;
|
|
2151
|
+
};
|
|
2152
|
+
/**
|
|
2153
|
+
|
|
2154
|
+
* @param {Cli_Init_Pull_FailedInputs} inputs
|
|
2155
|
+
* @param {{ locale?: "ko" }} options
|
|
2156
|
+
* @returns {LocalizedString}
|
|
2157
|
+
*/
|
|
2158
|
+
const cli_init_pull_failed = ((inputs, options = {}) => {
|
|
2159
|
+
experimentalStaticLocale ?? options.locale ?? getLocale();
|
|
2160
|
+
return ko_cli_init_pull_failed(inputs);
|
|
2161
|
+
});
|
|
2162
|
+
|
|
2163
|
+
//#endregion
|
|
2164
|
+
//#region ../i18n/src/paraglide/messages/cli_init_site_exists.js
|
|
2165
|
+
/** @typedef {import('../runtime.js').LocalizedString} LocalizedString */
|
|
2166
|
+
/** @typedef {{ storeId: NonNullable<unknown> }} Cli_Init_Site_ExistsInputs */
|
|
2167
|
+
const ko_cli_init_site_exists = (i) => {
|
|
2168
|
+
return `이 상점에는 이미 호스팅 사이트가 있어 새로 만들지 않았습니다. npx sayren pull --project ${i?.storeId}로 소스를 받으십시오`;
|
|
2169
|
+
};
|
|
2170
|
+
/**
|
|
2171
|
+
|
|
2172
|
+
* @param {Cli_Init_Site_ExistsInputs} inputs
|
|
2173
|
+
* @param {{ locale?: "ko" }} options
|
|
2174
|
+
* @returns {LocalizedString}
|
|
2175
|
+
*/
|
|
2176
|
+
const cli_init_site_exists = ((inputs, options = {}) => {
|
|
2177
|
+
experimentalStaticLocale ?? options.locale ?? getLocale();
|
|
2178
|
+
return ko_cli_init_site_exists(inputs);
|
|
2179
|
+
});
|
|
2180
|
+
|
|
2181
|
+
//#endregion
|
|
2182
|
+
//#region ../i18n/src/paraglide/messages/cli_init_site_url.js
|
|
2183
|
+
/** @typedef {import('../runtime.js').LocalizedString} LocalizedString */
|
|
2184
|
+
/** @typedef {{ url: NonNullable<unknown> }} Cli_Init_Site_UrlInputs */
|
|
2185
|
+
const ko_cli_init_site_url = (i) => {
|
|
2186
|
+
return `지금 사이트: ${i?.url}`;
|
|
2187
|
+
};
|
|
2188
|
+
/**
|
|
2189
|
+
|
|
2190
|
+
* @param {Cli_Init_Site_UrlInputs} inputs
|
|
2191
|
+
* @param {{ locale?: "ko" }} options
|
|
2192
|
+
* @returns {LocalizedString}
|
|
2193
|
+
*/
|
|
2194
|
+
const cli_init_site_url = ((inputs, options = {}) => {
|
|
2195
|
+
experimentalStaticLocale ?? options.locale ?? getLocale();
|
|
2196
|
+
return ko_cli_init_site_url(inputs);
|
|
2197
|
+
});
|
|
2198
|
+
|
|
2199
|
+
//#endregion
|
|
2200
|
+
//#region ../i18n/src/paraglide/messages/cli_init_slug_taken.js
|
|
2201
|
+
/** @typedef {import('../runtime.js').LocalizedString} LocalizedString */
|
|
2202
|
+
/** @typedef {{}} Cli_Init_Slug_TakenInputs */
|
|
2203
|
+
const ko_cli_init_slug_taken = () => {
|
|
2204
|
+
return `상점 코드와 같은 주소를 다른 사이트가 쓰고 있어 만들지 못했습니다. 상점 플랫폼 › 스토어프론트에서 다른 주소로 만든 뒤 npx sayren pull로 받으십시오`;
|
|
2205
|
+
};
|
|
2206
|
+
/**
|
|
2207
|
+
|
|
2208
|
+
* @param {Cli_Init_Slug_TakenInputs} inputs
|
|
2209
|
+
* @param {{ locale?: "ko" }} options
|
|
2210
|
+
* @returns {LocalizedString}
|
|
2211
|
+
*/
|
|
2212
|
+
const cli_init_slug_taken = ((inputs = {}, options = {}) => {
|
|
2213
|
+
experimentalStaticLocale ?? options.locale ?? getLocale();
|
|
2214
|
+
return ko_cli_init_slug_taken(inputs);
|
|
2215
|
+
});
|
|
2216
|
+
|
|
2217
|
+
//#endregion
|
|
2218
|
+
//#region ../i18n/src/paraglide/messages/cli_init_summary.js
|
|
2219
|
+
/** @typedef {import('../runtime.js').LocalizedString} LocalizedString */
|
|
2220
|
+
/** @typedef {{ storeId: NonNullable<unknown>, name: NonNullable<unknown>, templateId: NonNullable<unknown>, version: NonNullable<unknown> }} Cli_Init_SummaryInputs */
|
|
2221
|
+
const ko_cli_init_summary = (i) => {
|
|
2222
|
+
return `상점 ${i?.storeId}에 템플릿 ${i?.name}(${i?.templateId} v${i?.version})로 호스팅 사이트를 만듭니다. 주소는 상점 코드이고 오픈 준비 중으로 시작합니다. 만들기는 상점당 30일에 3번까지입니다`;
|
|
2223
|
+
};
|
|
2224
|
+
/**
|
|
2225
|
+
|
|
2226
|
+
* @param {Cli_Init_SummaryInputs} inputs
|
|
2227
|
+
* @param {{ locale?: "ko" }} options
|
|
2228
|
+
* @returns {LocalizedString}
|
|
2229
|
+
*/
|
|
2230
|
+
const cli_init_summary = ((inputs, options = {}) => {
|
|
2231
|
+
experimentalStaticLocale ?? options.locale ?? getLocale();
|
|
2232
|
+
return ko_cli_init_summary(inputs);
|
|
2233
|
+
});
|
|
2234
|
+
|
|
2235
|
+
//#endregion
|
|
2236
|
+
//#region ../i18n/src/paraglide/messages/cli_init_template_option.js
|
|
2237
|
+
/** @typedef {import('../runtime.js').LocalizedString} LocalizedString */
|
|
2238
|
+
/** @typedef {{ templateId: NonNullable<unknown>, name: NonNullable<unknown>, version: NonNullable<unknown>, description: NonNullable<unknown> }} Cli_Init_Template_OptionInputs */
|
|
2239
|
+
const ko_cli_init_template_option = (i) => {
|
|
2240
|
+
return `${i?.templateId} — ${i?.name} v${i?.version}: ${i?.description}`;
|
|
2241
|
+
};
|
|
2242
|
+
/**
|
|
2243
|
+
|
|
2244
|
+
* @param {Cli_Init_Template_OptionInputs} inputs
|
|
2245
|
+
* @param {{ locale?: "ko" }} options
|
|
2246
|
+
* @returns {LocalizedString}
|
|
2247
|
+
*/
|
|
2248
|
+
const cli_init_template_option = ((inputs, options = {}) => {
|
|
2249
|
+
experimentalStaticLocale ?? options.locale ?? getLocale();
|
|
2250
|
+
return ko_cli_init_template_option(inputs);
|
|
2251
|
+
});
|
|
2252
|
+
|
|
2253
|
+
//#endregion
|
|
2254
|
+
//#region ../i18n/src/paraglide/messages/cli_init_template_prompt.js
|
|
2255
|
+
/** @typedef {import('../runtime.js').LocalizedString} LocalizedString */
|
|
2256
|
+
/** @typedef {{}} Cli_Init_Template_PromptInputs */
|
|
2257
|
+
const ko_cli_init_template_prompt = () => {
|
|
2258
|
+
return `템플릿을 고르십시오:`;
|
|
2259
|
+
};
|
|
2260
|
+
/**
|
|
2261
|
+
|
|
2262
|
+
* @param {Cli_Init_Template_PromptInputs} inputs
|
|
2263
|
+
* @param {{ locale?: "ko" }} options
|
|
2264
|
+
* @returns {LocalizedString}
|
|
2265
|
+
*/
|
|
2266
|
+
const cli_init_template_prompt = ((inputs = {}, options = {}) => {
|
|
2267
|
+
experimentalStaticLocale ?? options.locale ?? getLocale();
|
|
2268
|
+
return ko_cli_init_template_prompt(inputs);
|
|
2269
|
+
});
|
|
2270
|
+
|
|
2271
|
+
//#endregion
|
|
2272
|
+
//#region ../i18n/src/paraglide/messages/cli_init_template_required.js
|
|
2273
|
+
/** @typedef {import('../runtime.js').LocalizedString} LocalizedString */
|
|
2274
|
+
/** @typedef {{ list: NonNullable<unknown> }} Cli_Init_Template_RequiredInputs */
|
|
2275
|
+
const ko_cli_init_template_required = (i) => {
|
|
2276
|
+
return `템플릿을 고르지 않았습니다. --template <id>로 주십시오(비대화형은 필수입니다):
|
|
2277
|
+
${i?.list}`;
|
|
2278
|
+
};
|
|
2279
|
+
/**
|
|
2280
|
+
|
|
2281
|
+
* @param {Cli_Init_Template_RequiredInputs} inputs
|
|
2282
|
+
* @param {{ locale?: "ko" }} options
|
|
2283
|
+
* @returns {LocalizedString}
|
|
2284
|
+
*/
|
|
2285
|
+
const cli_init_template_required = ((inputs, options = {}) => {
|
|
2286
|
+
experimentalStaticLocale ?? options.locale ?? getLocale();
|
|
2287
|
+
return ko_cli_init_template_required(inputs);
|
|
2288
|
+
});
|
|
2289
|
+
|
|
2290
|
+
//#endregion
|
|
2291
|
+
//#region ../i18n/src/paraglide/messages/cli_init_template_unknown.js
|
|
2292
|
+
/** @typedef {import('../runtime.js').LocalizedString} LocalizedString */
|
|
2293
|
+
/** @typedef {{ templateId: NonNullable<unknown>, ids: NonNullable<unknown> }} Cli_Init_Template_UnknownInputs */
|
|
2294
|
+
const ko_cli_init_template_unknown = (i) => {
|
|
2295
|
+
return `템플릿을 찾지 못했습니다: ${i?.templateId}. 쓸 수 있는 템플릿: ${i?.ids}`;
|
|
2296
|
+
};
|
|
2297
|
+
/**
|
|
2298
|
+
|
|
2299
|
+
* @param {Cli_Init_Template_UnknownInputs} inputs
|
|
2300
|
+
* @param {{ locale?: "ko" }} options
|
|
2301
|
+
* @returns {LocalizedString}
|
|
2302
|
+
*/
|
|
2303
|
+
const cli_init_template_unknown = ((inputs, options = {}) => {
|
|
2304
|
+
experimentalStaticLocale ?? options.locale ?? getLocale();
|
|
2305
|
+
return ko_cli_init_template_unknown(inputs);
|
|
2306
|
+
});
|
|
2307
|
+
|
|
2308
|
+
//#endregion
|
|
2309
|
+
//#region ../i18n/src/paraglide/messages/cli_init_yes_required.js
|
|
2310
|
+
/** @typedef {import('../runtime.js').LocalizedString} LocalizedString */
|
|
2311
|
+
/** @typedef {{}} Cli_Init_Yes_RequiredInputs */
|
|
2312
|
+
const ko_cli_init_yes_required = () => {
|
|
2313
|
+
return `사이트 만들기를 확인할 수 없는 환경입니다. --yes를 함께 주십시오`;
|
|
2314
|
+
};
|
|
2315
|
+
/**
|
|
2316
|
+
|
|
2317
|
+
* @param {Cli_Init_Yes_RequiredInputs} inputs
|
|
2318
|
+
* @param {{ locale?: "ko" }} options
|
|
2319
|
+
* @returns {LocalizedString}
|
|
2320
|
+
*/
|
|
2321
|
+
const cli_init_yes_required = ((inputs = {}, options = {}) => {
|
|
2322
|
+
experimentalStaticLocale ?? options.locale ?? getLocale();
|
|
2323
|
+
return ko_cli_init_yes_required(inputs);
|
|
2324
|
+
});
|
|
2325
|
+
|
|
1893
2326
|
//#endregion
|
|
1894
2327
|
//#region ../i18n/src/paraglide/messages/cli_invalid_file_path.js
|
|
1895
2328
|
/** @typedef {import('../runtime.js').LocalizedString} LocalizedString */
|
|
@@ -2908,7 +3341,7 @@ const cli_pull_next_steps = ((inputs, options = {}) => {
|
|
|
2908
3341
|
/** @typedef {import('../runtime.js').LocalizedString} LocalizedString */
|
|
2909
3342
|
/** @typedef {{}} Cli_Pull_No_SiteInputs */
|
|
2910
3343
|
const ko_cli_pull_no_site = () => {
|
|
2911
|
-
return `이 상점에는 호스팅 사이트가 없습니다. 상점 플랫폼 › 스토어프론트에서
|
|
3344
|
+
return `이 상점에는 호스팅 사이트가 없습니다. npx sayren init으로 만들거나 상점 플랫폼 › 스토어프론트에서 만든 뒤 다시 받으십시오`;
|
|
2912
3345
|
};
|
|
2913
3346
|
/**
|
|
2914
3347
|
|
|
@@ -3894,8 +4327,9 @@ const ko_cli_usage = (i) => {
|
|
|
3894
4327
|
npx sayren login --paste # 액세스 토큰을 입력받아 저장(셸 기록에 남지 않습니다)
|
|
3895
4328
|
npx sayren logout
|
|
3896
4329
|
npx sayren whoami
|
|
4330
|
+
npx sayren init [폴더] [--template <id>] [--store <storeId>] [--yes]
|
|
3897
4331
|
npx sayren pull --project <storeId> [폴더] [--force [--yes]]
|
|
3898
|
-
npx sayren deploy [--no-publish] [--message <메모>] [--force [--yes]]
|
|
4332
|
+
npx sayren deploy [--no-publish] [--skip-build] [--message <메모>] [--force [--yes]]
|
|
3899
4333
|
npx sayren status
|
|
3900
4334
|
npx sayren verify
|
|
3901
4335
|
|
|
@@ -3903,8 +4337,9 @@ const ko_cli_usage = (i) => {
|
|
|
3903
4337
|
login Sayren 계정으로 로그인합니다. 로그인 토큰은 사용자 설정 폴더(~/.config/sayren/credentials.json)에 둡니다
|
|
3904
4338
|
logout 로그인을 폐기하고 이 컴퓨터의 토큰을 지웁니다
|
|
3905
4339
|
whoami 쓰는 계정·토큰 종류·상점 범위
|
|
4340
|
+
init 템플릿을 골라 호스팅 사이트를 만들고 pull과 같은 폴더(기본: 상점 코드)로 받습니다. 사이트가 이미 있으면 만들지 않습니다
|
|
3906
4341
|
pull 호스팅 중인 사이트의 작업 트리를 폴더(기본: 상점 코드)로 받고 .mcp.json·.env·.sayren/state.json을 씁니다
|
|
3907
|
-
deploy 로컬 검사 → 작업 트리 올리기 → 빌드 → 발행. 원격이 pull 이후 바뀌었으면 덮어쓰지 않습니다
|
|
4342
|
+
deploy 로컬 검사 → 로컬 빌드 → 작업 트리 올리기 → 빌드 → 발행. 원격이 pull 이후 바뀌었으면 덮어쓰지 않습니다
|
|
3908
4343
|
status 사이트·발행 버전·최근 빌드·편집 환경
|
|
3909
4344
|
verify 로컬 규칙·경로·크기 검사(서버 빌드와 같은 규칙)
|
|
3910
4345
|
|
|
@@ -3915,11 +4350,13 @@ const ko_cli_usage = (i) => {
|
|
|
3915
4350
|
|
|
3916
4351
|
옵션:
|
|
3917
4352
|
--project <storeId> pull: 받을 상점(--store와 같습니다)
|
|
3918
|
-
--
|
|
4353
|
+
--template <id> init: 템플릿 id(비대화형은 필수)
|
|
4354
|
+
--dir <폴더> 작업 폴더(기본: 지금 폴더, pull·init은 상점 코드)
|
|
3919
4355
|
--force pull: 같은 사이트를 받은 폴더에 원격을 다시 받습니다(지울·덮을 파일을 보여 주고 묻습니다)
|
|
3920
4356
|
deploy: 원격 변경·열린 편집 환경을 무시하고 덮어씁니다(확인을 묻습니다)
|
|
3921
|
-
--yes --force의 확인을 묻지 않습니다(비대화형)
|
|
4357
|
+
--yes --force·init의 확인을 묻지 않습니다(비대화형)
|
|
3922
4358
|
--no-publish deploy: 버전까지만 만들고 발행하지 않습니다
|
|
4359
|
+
--skip-build deploy: 올리기 전 로컬 빌드(npm run build)를 건너뜁니다
|
|
3923
4360
|
--message <메모> deploy: 버전 메모
|
|
3924
4361
|
--store <storeId> 다룰 상점(SAYREN_STORE_ID)
|
|
3925
4362
|
--device login: 브라우저 대신 기기 코드로 로그인합니다(SSH 등)
|
|
@@ -4433,7 +4870,7 @@ const mcp_report_template_hint_local = ((inputs, options = {}) => {
|
|
|
4433
4870
|
/** @typedef {import('../runtime.js').LocalizedString} LocalizedString */
|
|
4434
4871
|
/** @typedef {{ files: NonNullable<unknown> }} Mcp_Report_Template_Hint_RemoteInputs */
|
|
4435
4872
|
const ko_mcp_report_template_hint_remote = (i) => {
|
|
4436
|
-
return `손대지 않아야 하는 파일을 고친 결과일 수 있다 — ${i?.files}을(를) \`read_file\`로 읽어 규칙의 \`example\`과 대조하고 되돌린다.`;
|
|
4873
|
+
return `손대지 않아야 하는 파일을 고친 결과일 수 있다 — ${i?.files}을(를) \`read_file\`로 읽어 \`get_template_file\`의 템플릿 원본(지금 카탈로그 버전)이나 규칙의 \`example\`과 대조하고 되돌린다.`;
|
|
4437
4874
|
};
|
|
4438
4875
|
/**
|
|
4439
4876
|
|
|
@@ -5318,7 +5755,7 @@ const mcp_rule_local_import_exists_example = ((inputs = {}, options = {}) => {
|
|
|
5318
5755
|
/** @typedef {import('../runtime.js').LocalizedString} LocalizedString */
|
|
5319
5756
|
/** @typedef {{}} Mcp_Rule_Local_Import_Exists_FixInputs */
|
|
5320
5757
|
const ko_mcp_rule_local_import_exists_fix = () => {
|
|
5321
|
-
return `빠진 파일을 템플릿 원본(
|
|
5758
|
+
return `빠진 파일을 템플릿 원본(\`get_template_file\`, 또는 \`npx @sayren/mcp create\`로 받은 사본)에서 가져와 같은 경로에 둔다. 호스팅 사이트는 \`write_files\`(\`expectedHash: null\`)나 \`sayren deploy\`로 올린다. 쓰지 않는 import면 지운다. 템플릿의 화면 문구는 \`messages/ko.json\`이다`;
|
|
5322
5759
|
};
|
|
5323
5760
|
/**
|
|
5324
5761
|
|
|
@@ -5953,6 +6390,85 @@ const mcp_rule_server_only_env_why = ((inputs = {}, options = {}) => {
|
|
|
5953
6390
|
return ko_mcp_rule_server_only_env_why(inputs);
|
|
5954
6391
|
});
|
|
5955
6392
|
|
|
6393
|
+
//#endregion
|
|
6394
|
+
//#region ../i18n/src/paraglide/messages/mcp_rule_server_only_import_example.js
|
|
6395
|
+
/** @typedef {import('../runtime.js').LocalizedString} LocalizedString */
|
|
6396
|
+
/** @typedef {{}} Mcp_Rule_Server_Only_Import_ExampleInputs */
|
|
6397
|
+
const ko_mcp_rule_server_only_import_example = () => {
|
|
6398
|
+
return `// src/lib/my-orders.ts — 브라우저도 가져가는 파일
|
|
6399
|
+
import { apiFor } from "./api.server";
|
|
6400
|
+
import { readToken } from "./session.server";
|
|
6401
|
+
|
|
6402
|
+
// handler 안에서만 부른다. 일반 함수(export function)로 두면 브라우저 번들에 남는다
|
|
6403
|
+
export const listMyOrders = createServerFn({ method: "GET" }).handler(() =>
|
|
6404
|
+
apiFor({ accessToken: readToken() }).orders.list(),
|
|
6405
|
+
);`;
|
|
6406
|
+
};
|
|
6407
|
+
/**
|
|
6408
|
+
|
|
6409
|
+
* @param {Mcp_Rule_Server_Only_Import_ExampleInputs} inputs
|
|
6410
|
+
* @param {{ locale?: "ko" }} options
|
|
6411
|
+
* @returns {LocalizedString}
|
|
6412
|
+
*/
|
|
6413
|
+
const mcp_rule_server_only_import_example = ((inputs = {}, options = {}) => {
|
|
6414
|
+
experimentalStaticLocale ?? options.locale ?? getLocale();
|
|
6415
|
+
return ko_mcp_rule_server_only_import_example(inputs);
|
|
6416
|
+
});
|
|
6417
|
+
|
|
6418
|
+
//#endregion
|
|
6419
|
+
//#region ../i18n/src/paraglide/messages/mcp_rule_server_only_import_fix.js
|
|
6420
|
+
/** @typedef {import('../runtime.js').LocalizedString} LocalizedString */
|
|
6421
|
+
/** @typedef {{}} Mcp_Rule_Server_Only_Import_FixInputs */
|
|
6422
|
+
const ko_mcp_rule_server_only_import_fix = () => {
|
|
6423
|
+
return `서버 API를 부르는 함수는 \`*.server.ts\` 파일로 옮기거나 \`createServerFn().handler(…)\`로 감싼다. 브라우저가 함께 가져가는 파일(컴포넌트·\`src/lib/*.ts\`)은 서버 함수만 내보내고, \`*.server.ts\`의 값은 handler 안에서만 부른다. 서버 전용 모듈을 다시 내보내지 않는다`;
|
|
6424
|
+
};
|
|
6425
|
+
/**
|
|
6426
|
+
|
|
6427
|
+
* @param {Mcp_Rule_Server_Only_Import_FixInputs} inputs
|
|
6428
|
+
* @param {{ locale?: "ko" }} options
|
|
6429
|
+
* @returns {LocalizedString}
|
|
6430
|
+
*/
|
|
6431
|
+
const mcp_rule_server_only_import_fix = ((inputs = {}, options = {}) => {
|
|
6432
|
+
experimentalStaticLocale ?? options.locale ?? getLocale();
|
|
6433
|
+
return ko_mcp_rule_server_only_import_fix(inputs);
|
|
6434
|
+
});
|
|
6435
|
+
|
|
6436
|
+
//#endregion
|
|
6437
|
+
//#region ../i18n/src/paraglide/messages/mcp_rule_server_only_import_title.js
|
|
6438
|
+
/** @typedef {import('../runtime.js').LocalizedString} LocalizedString */
|
|
6439
|
+
/** @typedef {{}} Mcp_Rule_Server_Only_Import_TitleInputs */
|
|
6440
|
+
const ko_mcp_rule_server_only_import_title = () => {
|
|
6441
|
+
return `서버 전용 모듈(\`*.server.ts\`)에서 가져온 것은 서버 함수 안에서만 쓴다`;
|
|
6442
|
+
};
|
|
6443
|
+
/**
|
|
6444
|
+
|
|
6445
|
+
* @param {Mcp_Rule_Server_Only_Import_TitleInputs} inputs
|
|
6446
|
+
* @param {{ locale?: "ko" }} options
|
|
6447
|
+
* @returns {LocalizedString}
|
|
6448
|
+
*/
|
|
6449
|
+
const mcp_rule_server_only_import_title = ((inputs = {}, options = {}) => {
|
|
6450
|
+
experimentalStaticLocale ?? options.locale ?? getLocale();
|
|
6451
|
+
return ko_mcp_rule_server_only_import_title(inputs);
|
|
6452
|
+
});
|
|
6453
|
+
|
|
6454
|
+
//#endregion
|
|
6455
|
+
//#region ../i18n/src/paraglide/messages/mcp_rule_server_only_import_why.js
|
|
6456
|
+
/** @typedef {import('../runtime.js').LocalizedString} LocalizedString */
|
|
6457
|
+
/** @typedef {{}} Mcp_Rule_Server_Only_Import_WhyInputs */
|
|
6458
|
+
const ko_mcp_rule_server_only_import_why = () => {
|
|
6459
|
+
return `TanStack Start는 서버 함수 handler만 브라우저 번들에서 걷어낸다. 그 밖에서 \`*.server.ts\`(\`api.server\` 등)의 값을 쓰면 import가 브라우저 번들에 남고, import 보호가 버전 빌드(\`vite build\`)를 실패시킨다. 개발 서버와 타입 검사는 이것을 잡지 않는다`;
|
|
6460
|
+
};
|
|
6461
|
+
/**
|
|
6462
|
+
|
|
6463
|
+
* @param {Mcp_Rule_Server_Only_Import_WhyInputs} inputs
|
|
6464
|
+
* @param {{ locale?: "ko" }} options
|
|
6465
|
+
* @returns {LocalizedString}
|
|
6466
|
+
*/
|
|
6467
|
+
const mcp_rule_server_only_import_why = ((inputs = {}, options = {}) => {
|
|
6468
|
+
experimentalStaticLocale ?? options.locale ?? getLocale();
|
|
6469
|
+
return ko_mcp_rule_server_only_import_why(inputs);
|
|
6470
|
+
});
|
|
6471
|
+
|
|
5956
6472
|
//#endregion
|
|
5957
6473
|
//#region ../i18n/src/paraglide/messages/mcp_rule_tenant_header_fix.js
|
|
5958
6474
|
/** @typedef {import('../runtime.js').LocalizedString} LocalizedString */
|
|
@@ -6565,6 +7081,42 @@ const mcp_verify_server_only_env = ((inputs = {}, options = {}) => {
|
|
|
6565
7081
|
return ko_mcp_verify_server_only_env(inputs);
|
|
6566
7082
|
});
|
|
6567
7083
|
|
|
7084
|
+
//#endregion
|
|
7085
|
+
//#region ../i18n/src/paraglide/messages/mcp_verify_server_only_import.js
|
|
7086
|
+
/** @typedef {import('../runtime.js').LocalizedString} LocalizedString */
|
|
7087
|
+
/** @typedef {{ specifier: NonNullable<unknown>, name: NonNullable<unknown> }} Mcp_Verify_Server_Only_ImportInputs */
|
|
7088
|
+
const ko_mcp_verify_server_only_import = (i) => {
|
|
7089
|
+
return `서버 전용 모듈 \`${i?.specifier}\`의 \`${i?.name}\`을 서버 함수(handler) 밖에서 쓴다. 브라우저 번들에 남아 버전 빌드가 import 보호로 실패한다`;
|
|
7090
|
+
};
|
|
7091
|
+
/**
|
|
7092
|
+
|
|
7093
|
+
* @param {Mcp_Verify_Server_Only_ImportInputs} inputs
|
|
7094
|
+
* @param {{ locale?: "ko" }} options
|
|
7095
|
+
* @returns {LocalizedString}
|
|
7096
|
+
*/
|
|
7097
|
+
const mcp_verify_server_only_import = ((inputs, options = {}) => {
|
|
7098
|
+
experimentalStaticLocale ?? options.locale ?? getLocale();
|
|
7099
|
+
return ko_mcp_verify_server_only_import(inputs);
|
|
7100
|
+
});
|
|
7101
|
+
|
|
7102
|
+
//#endregion
|
|
7103
|
+
//#region ../i18n/src/paraglide/messages/mcp_verify_server_only_import_reexport.js
|
|
7104
|
+
/** @typedef {import('../runtime.js').LocalizedString} LocalizedString */
|
|
7105
|
+
/** @typedef {{ specifier: NonNullable<unknown> }} Mcp_Verify_Server_Only_Import_ReexportInputs */
|
|
7106
|
+
const ko_mcp_verify_server_only_import_reexport = (i) => {
|
|
7107
|
+
return `서버 전용 모듈 \`${i?.specifier}\`를 부수 효과 import나 다시 내보내기로 가져온다. 브라우저 번들에 남아 버전 빌드가 import 보호로 실패한다`;
|
|
7108
|
+
};
|
|
7109
|
+
/**
|
|
7110
|
+
|
|
7111
|
+
* @param {Mcp_Verify_Server_Only_Import_ReexportInputs} inputs
|
|
7112
|
+
* @param {{ locale?: "ko" }} options
|
|
7113
|
+
* @returns {LocalizedString}
|
|
7114
|
+
*/
|
|
7115
|
+
const mcp_verify_server_only_import_reexport = ((inputs, options = {}) => {
|
|
7116
|
+
experimentalStaticLocale ?? options.locale ?? getLocale();
|
|
7117
|
+
return ko_mcp_verify_server_only_import_reexport(inputs);
|
|
7118
|
+
});
|
|
7119
|
+
|
|
6568
7120
|
//#endregion
|
|
6569
7121
|
//#region ../i18n/src/paraglide/messages/mcp_verify_tenant_header.js
|
|
6570
7122
|
/** @typedef {import('../runtime.js').LocalizedString} LocalizedString */
|
|
@@ -6652,7 +7204,7 @@ function takeLangFlag(argv) {
|
|
|
6652
7204
|
|
|
6653
7205
|
//#endregion
|
|
6654
7206
|
//#region package.json
|
|
6655
|
-
var version = "0.
|
|
7207
|
+
var version = "0.4.0";
|
|
6656
7208
|
|
|
6657
7209
|
//#endregion
|
|
6658
7210
|
//#region src/client.ts
|
|
@@ -6673,11 +7225,11 @@ function clientOf(auth, fetchImpl = fetch, refresh) {
|
|
|
6673
7225
|
accessToken: () => auth.token,
|
|
6674
7226
|
storeId: () => auth.storeId ?? null,
|
|
6675
7227
|
...refresh ? { refresh } : {},
|
|
6676
|
-
fetch: (input, init) => {
|
|
6677
|
-
const headers = new Headers(init?.headers);
|
|
7228
|
+
fetch: (input, init$1) => {
|
|
7229
|
+
const headers = new Headers(init$1?.headers);
|
|
6678
7230
|
headers.set("user-agent", CLI_USER_AGENT);
|
|
6679
7231
|
return fetchImpl(input, {
|
|
6680
|
-
...init,
|
|
7232
|
+
...init$1,
|
|
6681
7233
|
headers
|
|
6682
7234
|
});
|
|
6683
7235
|
}
|
|
@@ -7875,6 +8427,15 @@ const RULES = [
|
|
|
7875
8427
|
templateFile: "src/lib/ordering.ts",
|
|
7876
8428
|
severity: "warning"
|
|
7877
8429
|
}),
|
|
8430
|
+
defineRule({
|
|
8431
|
+
id: "server-only-import",
|
|
8432
|
+
title: mcp_rule_server_only_import_title,
|
|
8433
|
+
why: mcp_rule_server_only_import_why,
|
|
8434
|
+
fix: mcp_rule_server_only_import_fix,
|
|
8435
|
+
example: mcp_rule_server_only_import_example,
|
|
8436
|
+
doc: "/guides/mcp-customize",
|
|
8437
|
+
templateFile: "src/lib/api.server.ts"
|
|
8438
|
+
}),
|
|
7878
8439
|
defineRule({
|
|
7879
8440
|
id: "local-import-exists",
|
|
7880
8441
|
title: mcp_rule_local_import_exists_title,
|
|
@@ -7988,6 +8549,7 @@ function verifySources(files, options = {}) {
|
|
|
7988
8549
|
const clientQuery = matches(/\buse(Suspense)?Query\(/);
|
|
7989
8550
|
if (clientQuery && !has("ensureQueryData(") && !has("prefetchQuery(")) inFile("loader-first", clientQuery, mcp_verify_loader_first_query(), /\buse(Suspense)?Query\(/);
|
|
7990
8551
|
if (has("createStorefrontClient(") && !has("loader")) inProject("loader-first", mcp_verify_loader_first_missing());
|
|
8552
|
+
findings.push(...serverOnlyImports(cleaned));
|
|
7991
8553
|
if (options.paths) findings.push(...missingLocalImports(cleaned, options.paths));
|
|
7992
8554
|
return findings;
|
|
7993
8555
|
}
|
|
@@ -8049,6 +8611,113 @@ function missingLocalImports(files, paths) {
|
|
|
8049
8611
|
}
|
|
8050
8612
|
return out;
|
|
8051
8613
|
}
|
|
8614
|
+
/**
|
|
8615
|
+
* 서버 전용 모듈 — TanStack Start import 보호의 기본 판정과 같다(클라이언트 환경에서 `*.server.*` 파일과
|
|
8616
|
+
* `@tanstack/{react,solid,vue}-start/server`를 막는다). 표시 모듈 `…/server-only`는 막는 대상이 아니다.
|
|
8617
|
+
*/
|
|
8618
|
+
const SERVER_ONLY_SPECIFIER = /^(?:@tanstack\/(?:react|solid|vue)-start\/server|\.{1,2}\/(?:[^"'\n]*\/)?[^/"'\n]+\.server(?:\.[cm]?[jt]sx?)?)$/;
|
|
8619
|
+
/** 그 자체가 브라우저로 가지 않아 import 보호가 보지 않는 파일 — `*.server.*`와 테스트 */
|
|
8620
|
+
const SERVER_ONLY_IMPORTER = /\.server\.[cm]?[jt]sx?$|\.(test|spec)\.[cm]?[jt]sx?$/;
|
|
8621
|
+
/** 스스로 서버 전용임을 밝힌 모듈 — 브라우저가 가져가면 import 보호가 그 모듈을 막으므로 여기서는 보지 않는다 */
|
|
8622
|
+
const SERVER_ONLY_MARKER = /\bimport\s*["']@tanstack\/(?:react|solid|vue)-start\/server-only["']/;
|
|
8623
|
+
/** 정적 import 문(여러 줄 포함). 1: `type` 2: 가져오는 이름들 3: 모듈 */
|
|
8624
|
+
const STATIC_IMPORT = /\bimport\s+(type\s+)?([^;"'`]*?)\s*\bfrom\s*["']([^"'\n]+)["']\s*;?/g;
|
|
8625
|
+
/** 부수 효과 import·다시 내보내기 — 서버 전용 모듈이면 그대로 브라우저 번들에 남는다 */
|
|
8626
|
+
const SIDE_EFFECT_OR_REEXPORT = /\bimport\s*["']([^"'\n]+)["']|\bexport\s+(?:type\s+)?(?:\*(?:\s+as\s+[\w$]+)?|\{[^}]*\})\s*from\s*["']([^"'\n]+)["']/g;
|
|
8627
|
+
/**
|
|
8628
|
+
* 서버에서만 도는 자리 — Start 컴파일러가 클라이언트 번들에서 걷어내는 인자다. `createServerFn().handler(…)`,
|
|
8629
|
+
* `createMiddleware().server(…)`·`createIsomorphicFn().server(…)`, `createServerOnlyFn(…)`, 서버 라우트
|
|
8630
|
+
* `createFileRoute(…)({ server: { handlers } })`의 `server` 객체. 일치의 마지막 글자가 여는 괄호다
|
|
8631
|
+
*/
|
|
8632
|
+
const SERVER_CONTEXT = /\.(?:handler|server)\s*\(|\bcreateServerOnlyFn\s*\(|\bserver\s*:\s*\{/g;
|
|
8633
|
+
/** import 문이 가져오는 값 이름 — `type` 표시가 붙은 이름은 빼고, `a as b`는 `b`다 */
|
|
8634
|
+
function importedBindings(clause) {
|
|
8635
|
+
const names = [];
|
|
8636
|
+
const named = /\{([^}]*)\}/.exec(clause);
|
|
8637
|
+
for (const part of named?.[1]?.split(",") ?? []) {
|
|
8638
|
+
const item = part.trim();
|
|
8639
|
+
if (!item || /^type\s/.test(item)) continue;
|
|
8640
|
+
const alias = /\bas\s+([\w$]+)$/.exec(item);
|
|
8641
|
+
names.push(alias ? alias[1] : item.split(/\s+/)[0]);
|
|
8642
|
+
}
|
|
8643
|
+
const rest = clause.replace(/\{[^}]*\}/, "");
|
|
8644
|
+
const namespace = /\*\s*as\s+([\w$]+)/.exec(rest);
|
|
8645
|
+
if (namespace) names.push(namespace[1]);
|
|
8646
|
+
const defaultName = /^\s*([\w$]+)\s*(?:,|$)/.exec(rest.replace(/\*\s*as\s+[\w$]+/, ""));
|
|
8647
|
+
if (defaultName) names.push(defaultName[1]);
|
|
8648
|
+
return names.filter((name) => /^[A-Za-z_$][\w$]*$/.test(name));
|
|
8649
|
+
}
|
|
8650
|
+
/** `open` 위치의 여는 괄호와 짝이 맞는 닫는 괄호 다음 위치. 문자열·템플릿 리터럴 안의 괄호는 세지 않는다 */
|
|
8651
|
+
function closingBracket(source, open) {
|
|
8652
|
+
let depth = 0;
|
|
8653
|
+
let quote = null;
|
|
8654
|
+
for (let i = open; i < source.length; i++) {
|
|
8655
|
+
const ch = source[i];
|
|
8656
|
+
if (quote) {
|
|
8657
|
+
if (ch === "\\") i++;
|
|
8658
|
+
else if (ch === quote) quote = null;
|
|
8659
|
+
continue;
|
|
8660
|
+
}
|
|
8661
|
+
if (ch === "\"" || ch === "'" || ch === "`") quote = ch;
|
|
8662
|
+
else if (ch === "(" || ch === "{" || ch === "[") depth++;
|
|
8663
|
+
else if ((ch === ")" || ch === "}" || ch === "]") && --depth === 0) return i + 1;
|
|
8664
|
+
}
|
|
8665
|
+
return source.length;
|
|
8666
|
+
}
|
|
8667
|
+
/** 줄 수를 지키며 구간을 공백으로 지운다 — 남은 코드의 위치가 원본 줄 번호와 맞아야 한다 */
|
|
8668
|
+
const blank = (text) => text.replace(/[^\n]/g, " ");
|
|
8669
|
+
/**
|
|
8670
|
+
* 브라우저로 갈 수 있는 모듈이 서버 전용 모듈을 쓰는가(이슈 #88). TanStack Start는 서버 함수 handler처럼 서버에서만
|
|
8671
|
+
* 도는 인자를 클라이언트 번들에서 걷어내고, 그 뒤에도 `*.server.*` import가 남으면 import 보호로 빌드를 실패시킨다.
|
|
8672
|
+
* 그래서 import 자체가 아니라 **서버 자리 밖에서 가져온 이름을 쓰는 것**을 위반으로 본다. 템플릿은 라우트·`lib`에서
|
|
8673
|
+
* `apiFor`를 import하고 `createServerFn().handler(…)`·서버 라우트 `server` 안에서만 부른다. 서버 자리 밖의 일반 함수(예: 서버 API를 부르는
|
|
8674
|
+
* `export function wishedOf()`)는 브라우저 번들에 남으므로 위반이다 — 그 함수를 `*.server.ts`로 옮기거나 서버 함수로 감싼다.
|
|
8675
|
+
* 정적 검사라 서버 자리에서만 부르는 지역 함수까지 따라가지는 않는다(보수적으로 위반으로 본다).
|
|
8676
|
+
*/
|
|
8677
|
+
function serverOnlyImports(files) {
|
|
8678
|
+
const out = [];
|
|
8679
|
+
for (const file of files) {
|
|
8680
|
+
if (!CLIENT_FILE.test(file.path) || SERVER_ONLY_IMPORTER.test(file.path)) continue;
|
|
8681
|
+
if (SERVER_ONLY_MARKER.test(file.content)) continue;
|
|
8682
|
+
const lineAt = (index) => file.content.slice(0, index).split("\n").length;
|
|
8683
|
+
for (const match of file.content.matchAll(SIDE_EFFECT_OR_REEXPORT)) {
|
|
8684
|
+
const specifier = match[1] ?? match[2];
|
|
8685
|
+
if (!SERVER_ONLY_SPECIFIER.test(specifier)) continue;
|
|
8686
|
+
out.push({
|
|
8687
|
+
ruleId: "server-only-import",
|
|
8688
|
+
file: file.path,
|
|
8689
|
+
line: lineAt(match.index),
|
|
8690
|
+
detail: mcp_verify_server_only_import_reexport({ specifier })
|
|
8691
|
+
});
|
|
8692
|
+
}
|
|
8693
|
+
const bindings = /* @__PURE__ */ new Map();
|
|
8694
|
+
let body = file.content.replace(STATIC_IMPORT, (statement, typeOnly, clause, specifier) => {
|
|
8695
|
+
if (!typeOnly && SERVER_ONLY_SPECIFIER.test(specifier)) for (const name of importedBindings(clause)) bindings.set(name, specifier);
|
|
8696
|
+
return blank(statement);
|
|
8697
|
+
});
|
|
8698
|
+
if (bindings.size === 0) continue;
|
|
8699
|
+
for (const context of [...body.matchAll(SERVER_CONTEXT)]) {
|
|
8700
|
+
const open = context.index + context[0].length - 1;
|
|
8701
|
+
if (body[open] !== "(" && body[open] !== "{") continue;
|
|
8702
|
+
const end = closingBracket(body, open);
|
|
8703
|
+
body = body.slice(0, open) + blank(body.slice(open, end)) + body.slice(end);
|
|
8704
|
+
}
|
|
8705
|
+
for (const [name, specifier] of bindings) {
|
|
8706
|
+
const use = (/* @__PURE__ */ new RegExp(`(?<![\\w$.])${name.replace(/\$/g, "\\$")}(?![\\w$])`)).exec(body);
|
|
8707
|
+
if (!use) continue;
|
|
8708
|
+
out.push({
|
|
8709
|
+
ruleId: "server-only-import",
|
|
8710
|
+
file: file.path,
|
|
8711
|
+
line: lineAt(use.index),
|
|
8712
|
+
detail: mcp_verify_server_only_import({
|
|
8713
|
+
name,
|
|
8714
|
+
specifier
|
|
8715
|
+
})
|
|
8716
|
+
});
|
|
8717
|
+
}
|
|
8718
|
+
}
|
|
8719
|
+
return out;
|
|
8720
|
+
}
|
|
8052
8721
|
|
|
8053
8722
|
//#endregion
|
|
8054
8723
|
//#region ../mcp/src/verify-report.ts
|
|
@@ -8601,6 +9270,55 @@ function lockImporterSpecifiers(lock) {
|
|
|
8601
9270
|
return out;
|
|
8602
9271
|
}
|
|
8603
9272
|
|
|
9273
|
+
//#endregion
|
|
9274
|
+
//#region src/local-build.ts
|
|
9275
|
+
/** 실패할 때 보여 주는 빌드 출력 줄 수 */
|
|
9276
|
+
const OUTPUT_TAIL_LINES = 40;
|
|
9277
|
+
/** 모아 두는 출력 상한(문자) — 긴 빌드 로그를 다 쥐고 있지 않는다 */
|
|
9278
|
+
const OUTPUT_KEEP_CHARS = 64 * 1024;
|
|
9279
|
+
/** 빌드를 돌릴 수 있는 폴더인가 — `build` 스크립트와 설치된 의존성(`node_modules`)이 있어야 한다 */
|
|
9280
|
+
function planLocalBuild(dir) {
|
|
9281
|
+
let scripts;
|
|
9282
|
+
try {
|
|
9283
|
+
scripts = JSON.parse(readFileSync(join(dir, "package.json"), "utf8")).scripts;
|
|
9284
|
+
} catch {
|
|
9285
|
+
return { kind: "no-script" };
|
|
9286
|
+
}
|
|
9287
|
+
const build = scripts && typeof scripts === "object" ? scripts.build : void 0;
|
|
9288
|
+
if (typeof build !== "string" || !build.trim()) return { kind: "no-script" };
|
|
9289
|
+
if (!existsSync(join(dir, "node_modules"))) return { kind: "no-deps" };
|
|
9290
|
+
return { kind: "run" };
|
|
9291
|
+
}
|
|
9292
|
+
/** `npm run build`를 돌린다. 출력은 모아 두고(실패할 때 꼬리를 보여 준다) 화면에 흘리지 않는다 */
|
|
9293
|
+
function runNpmBuild(dir, env) {
|
|
9294
|
+
return new Promise((resolve$1, reject) => {
|
|
9295
|
+
let output = "";
|
|
9296
|
+
const keep = (chunk) => {
|
|
9297
|
+
output = (output + chunk.toString("utf8")).slice(-OUTPUT_KEEP_CHARS);
|
|
9298
|
+
};
|
|
9299
|
+
const child = spawn("npm", ["run", "build"], {
|
|
9300
|
+
cwd: dir,
|
|
9301
|
+
env,
|
|
9302
|
+
stdio: [
|
|
9303
|
+
"ignore",
|
|
9304
|
+
"pipe",
|
|
9305
|
+
"pipe"
|
|
9306
|
+
],
|
|
9307
|
+
shell: process.platform === "win32"
|
|
9308
|
+
});
|
|
9309
|
+
child.stdout?.on("data", keep);
|
|
9310
|
+
child.stderr?.on("data", keep);
|
|
9311
|
+
child.once("error", reject);
|
|
9312
|
+
child.once("close", (code) => resolve$1({
|
|
9313
|
+
code,
|
|
9314
|
+
output: tailOf(output)
|
|
9315
|
+
}));
|
|
9316
|
+
});
|
|
9317
|
+
}
|
|
9318
|
+
function tailOf(output, lines = OUTPUT_TAIL_LINES) {
|
|
9319
|
+
return output.trimEnd().split(/\r?\n/).slice(-lines).join("\n");
|
|
9320
|
+
}
|
|
9321
|
+
|
|
8604
9322
|
//#endregion
|
|
8605
9323
|
//#region src/commands.ts
|
|
8606
9324
|
/** 종료 코드 — 0 성공 · 1 실패 · 3 발행이 승인 대기(에이전트 토큰) */
|
|
@@ -8657,13 +9375,20 @@ async function pull(flags, io) {
|
|
|
8657
9375
|
storeId: source.storeId,
|
|
8658
9376
|
project: flags.project
|
|
8659
9377
|
}));
|
|
9378
|
+
return receiveSource(client, auth, source, flags, io, authDir);
|
|
9379
|
+
}
|
|
9380
|
+
/**
|
|
9381
|
+
* 받은 작업 트리를 폴더에 쓰고 받은 폴더 파일(`.sayren/state.json`·`.env`·`.mcp.json`·`.gitignore`)을 맞춘다. `pull`과 `init`(#101)이 같이 쓴다.
|
|
9382
|
+
* 대상은 `--dir` → 받은 폴더 안이면 그 폴더 → 상점 코드다. 비어 있지 않은 폴더는 `--force`일 때 같은 사이트를 받은 폴더만 다시 받는다.
|
|
9383
|
+
*/
|
|
9384
|
+
async function receiveSource(client, auth, source, flags, io, migratedDir) {
|
|
8660
9385
|
const store = {
|
|
8661
9386
|
storeId: source.storeId,
|
|
8662
9387
|
storeCode: source.storeCode
|
|
8663
9388
|
};
|
|
8664
9389
|
const defaultDir = store.storeCode || source.siteId;
|
|
8665
9390
|
const target = !flags.dir && isPulledDir(io.cwd) ? io.cwd : resolve(io.cwd, flags.dir ?? defaultDir);
|
|
8666
|
-
if (target !==
|
|
9391
|
+
if (target !== migratedDir) migrateLegacy(target, io.out);
|
|
8667
9392
|
const existing = existsSync(target) ? readdirSync(target) : [];
|
|
8668
9393
|
if (existing.length > 0) {
|
|
8669
9394
|
if (!flags.force) throw new CliError(cli_pull_dir_not_empty({ dir: relativeOf(io, target) }));
|
|
@@ -8785,6 +9510,80 @@ async function pull(flags, io) {
|
|
|
8785
9510
|
io.out(cli_pull_next_steps({ dir: pulledDir }));
|
|
8786
9511
|
return 0;
|
|
8787
9512
|
}
|
|
9513
|
+
/**
|
|
9514
|
+
* `sayren init [폴더]`(#101) — 템플릿을 골라 호스팅 사이트를 만들고(`POST /v1/storefront/site`) `pull`과 같은 폴더를 만든다.
|
|
9515
|
+
* 사이트가 이미 있으면 만들지 않고 `pull`을 안내한다(상점당 열린 사이트는 하나다). 만들기는 상점 한도(30일 3회)를 쓰므로 확인을 묻는다.
|
|
9516
|
+
* 토큰은 `storefront:rw`가 있어야 한다(로그인 토큰 `CLI_LOGIN_SCOPE`에 있다). 에이전트 토큰이어도 만들기는 승인 대상이 아니다
|
|
9517
|
+
* (쓰기 정책 표에 없다 — 오픈 준비 중으로 시작해 구매자 화면을 바꾸지 않는다).
|
|
9518
|
+
*/
|
|
9519
|
+
async function init(flags, io) {
|
|
9520
|
+
const target = flags.dir ? resolve(io.cwd, flags.dir) : null;
|
|
9521
|
+
if (target && existsSync(target) && readdirSync(target).length > 0) throw new CliError(cli_init_dir_not_empty({ dir: relativeOf(io, target) }));
|
|
9522
|
+
if (!target && isPulledDir(io.cwd)) throw new CliError(cli_init_inside_pulled());
|
|
9523
|
+
const authDir = target && existsSync(target) ? target : io.cwd;
|
|
9524
|
+
const { auth, client } = await apiFor(flags, authDir, null, io);
|
|
9525
|
+
const storeId = auth.storeId ?? "<storeId>";
|
|
9526
|
+
const hosting = await client.storefront.get();
|
|
9527
|
+
if (hosting.site) {
|
|
9528
|
+
io.out(cli_init_site_url({ url: hosting.site.url }));
|
|
9529
|
+
throw new CliError(cli_init_site_exists({ storeId }));
|
|
9530
|
+
}
|
|
9531
|
+
if (!hosting.enabled) throw new CliError(cli_init_hosting_disabled());
|
|
9532
|
+
if (!hosting.editingEnabled) throw new CliError(cli_pull_editing_disabled());
|
|
9533
|
+
const template = await pickTemplate(await client.storefront.listTemplates(), flags.template, io);
|
|
9534
|
+
io.out(cli_init_summary({
|
|
9535
|
+
name: template.name,
|
|
9536
|
+
templateId: template.templateId,
|
|
9537
|
+
version: template.version,
|
|
9538
|
+
storeId
|
|
9539
|
+
}));
|
|
9540
|
+
if (!flags.yes) {
|
|
9541
|
+
if (!io.confirm) throw new CliError(cli_init_yes_required());
|
|
9542
|
+
if (!await io.confirm(cli_init_confirm())) {
|
|
9543
|
+
io.out(cli_cancelled());
|
|
9544
|
+
return 1;
|
|
9545
|
+
}
|
|
9546
|
+
}
|
|
9547
|
+
let site;
|
|
9548
|
+
try {
|
|
9549
|
+
site = await client.storefront.create({ templateId: template.templateId });
|
|
9550
|
+
} catch (error) {
|
|
9551
|
+
const code = codeOf(error);
|
|
9552
|
+
if (code === "STOREFRONT_SITE_EXISTS") throw new CliError(cli_init_site_exists({ storeId }));
|
|
9553
|
+
if (code === "STOREFRONT_SLUG_TAKEN") throw new CliError(cli_init_slug_taken());
|
|
9554
|
+
throw error;
|
|
9555
|
+
}
|
|
9556
|
+
io.out(cli_init_created({ url: site.url }));
|
|
9557
|
+
try {
|
|
9558
|
+
return await receiveSource(client, auth, await client.storefront.getSource(), { dir: flags.dir }, io, authDir);
|
|
9559
|
+
} catch (error) {
|
|
9560
|
+
io.err(cli_init_pull_failed({ storeId }));
|
|
9561
|
+
throw error;
|
|
9562
|
+
}
|
|
9563
|
+
}
|
|
9564
|
+
/** `--template`이 있으면 그 템플릿, 없으면 대화형 선택. 비대화형이면 `--template`이 있어야 한다 */
|
|
9565
|
+
async function pickTemplate(templates, wanted, io) {
|
|
9566
|
+
if (templates.length === 0) throw new CliError(cli_init_no_templates());
|
|
9567
|
+
const ids = templates.map((t) => t.templateId).join(", ");
|
|
9568
|
+
if (wanted) {
|
|
9569
|
+
const found = templates.find((t) => t.templateId === wanted);
|
|
9570
|
+
if (!found) throw new CliError(cli_init_template_unknown({
|
|
9571
|
+
templateId: wanted,
|
|
9572
|
+
ids
|
|
9573
|
+
}));
|
|
9574
|
+
return found;
|
|
9575
|
+
}
|
|
9576
|
+
const labels = templates.map((t) => cli_init_template_option({
|
|
9577
|
+
templateId: t.templateId,
|
|
9578
|
+
name: t.name,
|
|
9579
|
+
version: t.version,
|
|
9580
|
+
description: t.description
|
|
9581
|
+
}));
|
|
9582
|
+
const picked = io.select ? await io.select(cli_init_template_prompt(), labels) : null;
|
|
9583
|
+
const index = picked ? labels.indexOf(picked) : -1;
|
|
9584
|
+
if (index < 0) throw new CliError(cli_init_template_required({ list: labels.map((label) => ` ${label}`).join("\n") }));
|
|
9585
|
+
return templates[index];
|
|
9586
|
+
}
|
|
8788
9587
|
async function verify(flags, io) {
|
|
8789
9588
|
const dir = resolve(io.cwd, flags.dir ?? ".");
|
|
8790
9589
|
const tree = collectTree(dir);
|
|
@@ -8841,6 +9640,7 @@ async function deploy(flags, io) {
|
|
|
8841
9640
|
const checks = runLocalChecks(tree);
|
|
8842
9641
|
printChecks(tree, checks, io);
|
|
8843
9642
|
if (checks.blockingRules.length > 0 || checks.problems.length > 0) throw new CliError(cli_deploy_checks_failed());
|
|
9643
|
+
await localBuild(dir, flags.skipBuild === true, io);
|
|
8844
9644
|
const site = (await client.storefront.get()).site;
|
|
8845
9645
|
if (!site || site.siteId !== rc.siteId) throw new CliError(cli_deploy_site_mismatch({ siteId: rc.siteId }));
|
|
8846
9646
|
if (flags.force && !flags.yes) {
|
|
@@ -8912,6 +9712,42 @@ async function deploy(flags, io) {
|
|
|
8912
9712
|
throw error;
|
|
8913
9713
|
}
|
|
8914
9714
|
}
|
|
9715
|
+
/**
|
|
9716
|
+
* 배포 전 로컬 빌드(#103). 의존성이 설치돼 있고 `build` 스크립트가 있으면 돌리고, 실패하면(시작하지 못한 것 포함) 올리지 않는다.
|
|
9717
|
+
* 의존성이 없으면 알리고 건너뛴다 — 셀러가 install하지 않은 폴더에서도 배포는 된다(서버가 다시 빌드한다).
|
|
9718
|
+
*/
|
|
9719
|
+
async function localBuild(dir, skip, io) {
|
|
9720
|
+
if (skip) {
|
|
9721
|
+
io.out(cli_deploy_build_local_skipped_flag());
|
|
9722
|
+
return;
|
|
9723
|
+
}
|
|
9724
|
+
const plan = planLocalBuild(dir);
|
|
9725
|
+
if (plan.kind === "no-script") {
|
|
9726
|
+
io.out(cli_deploy_build_local_no_script());
|
|
9727
|
+
return;
|
|
9728
|
+
}
|
|
9729
|
+
if (plan.kind === "no-deps") {
|
|
9730
|
+
io.out(cli_deploy_build_local_no_deps());
|
|
9731
|
+
return;
|
|
9732
|
+
}
|
|
9733
|
+
io.out(cli_deploy_build_local_running());
|
|
9734
|
+
const started = io.now?.() ?? Date.now();
|
|
9735
|
+
let result;
|
|
9736
|
+
try {
|
|
9737
|
+
result = await (io.runBuild ?? ((at) => runNpmBuild(at, io.env)))(dir);
|
|
9738
|
+
} catch (error) {
|
|
9739
|
+
throw new CliError(cli_deploy_build_local_spawn_failed({ message: error instanceof Error ? error.message : String(error) }));
|
|
9740
|
+
}
|
|
9741
|
+
if (result.code !== 0) {
|
|
9742
|
+
if (result.output) {
|
|
9743
|
+
io.err(cli_deploy_build_local_output({ count: OUTPUT_TAIL_LINES }));
|
|
9744
|
+
for (const line of result.output.split("\n")) io.err(` ${line}`);
|
|
9745
|
+
}
|
|
9746
|
+
throw new CliError(cli_deploy_build_local_failed({ code: String(result.code ?? "-") }));
|
|
9747
|
+
}
|
|
9748
|
+
const seconds = Math.round(((io.now?.() ?? Date.now()) - started) / 1e3);
|
|
9749
|
+
io.out(cli_deploy_build_local_passed({ seconds }));
|
|
9750
|
+
}
|
|
8915
9751
|
async function replaceSource(client, tree, rc, force, io) {
|
|
8916
9752
|
const files = tree.files.map((file) => ({
|
|
8917
9753
|
path: file.path,
|
|
@@ -9238,12 +10074,14 @@ const VALUE_FLAGS = new Set([
|
|
|
9238
10074
|
"message",
|
|
9239
10075
|
"api-origin",
|
|
9240
10076
|
"store",
|
|
9241
|
-
"accounts-origin"
|
|
10077
|
+
"accounts-origin",
|
|
10078
|
+
"template"
|
|
9242
10079
|
]);
|
|
9243
10080
|
const BOOL_FLAGS = new Set([
|
|
9244
10081
|
"force",
|
|
9245
10082
|
"yes",
|
|
9246
10083
|
"no-publish",
|
|
10084
|
+
"skip-build",
|
|
9247
10085
|
"help",
|
|
9248
10086
|
"version",
|
|
9249
10087
|
"device",
|
|
@@ -9304,6 +10142,11 @@ async function main(argv, io) {
|
|
|
9304
10142
|
accountsOrigin: str(parsed.flags["accounts-origin"])
|
|
9305
10143
|
};
|
|
9306
10144
|
switch (parsed.command) {
|
|
10145
|
+
case "init": return init({
|
|
10146
|
+
...common,
|
|
10147
|
+
template: str(parsed.flags.template),
|
|
10148
|
+
yes: parsed.flags.yes === true
|
|
10149
|
+
}, io);
|
|
9307
10150
|
case "pull": return pull({
|
|
9308
10151
|
...common,
|
|
9309
10152
|
project: str(parsed.flags.project),
|
|
@@ -9315,6 +10158,7 @@ async function main(argv, io) {
|
|
|
9315
10158
|
force: parsed.flags.force === true,
|
|
9316
10159
|
yes: parsed.flags.yes === true,
|
|
9317
10160
|
publish: parsed.flags["no-publish"] !== true,
|
|
10161
|
+
skipBuild: parsed.flags["skip-build"] === true,
|
|
9318
10162
|
message: str(parsed.flags.message)
|
|
9319
10163
|
}, io);
|
|
9320
10164
|
case "status": return status(common, io);
|
|
@@ -9344,7 +10188,7 @@ function defaultIo() {
|
|
|
9344
10188
|
return {
|
|
9345
10189
|
cwd: process.cwd(),
|
|
9346
10190
|
env: process.env,
|
|
9347
|
-
fetch: (input, init) => fetch(input, init),
|
|
10191
|
+
fetch: (input, init$1) => fetch(input, init$1),
|
|
9348
10192
|
out: (line) => console.log(line),
|
|
9349
10193
|
err: (line) => console.error(line),
|
|
9350
10194
|
confirm: stdin.isTTY ? async (question) => /^(y|yes|예|네)$/i.test((await ask(`${question} (y/N) `) ?? "").trim()) : null,
|
package/package.json
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "sayren",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.4.0",
|
|
4
4
|
"type": "module",
|
|
5
|
-
"description": "sayren 스토어프론트 CLI — 호스팅
|
|
5
|
+
"description": "sayren 스토어프론트 CLI — 호스팅 사이트를 만들고(init) 소스를 내려받아(pull) 로컬에서 고친 뒤 배포(deploy)합니다",
|
|
6
6
|
"bin": {
|
|
7
7
|
"sayren": "./dist/index.mjs"
|
|
8
8
|
},
|