@aigne/doc-smith 0.8.11-beta → 0.8.11-beta.2
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/.aigne/doc-smith/config.yaml +2 -0
- package/.aigne/doc-smith/output/structure-plan.json +3 -3
- package/.aigne/doc-smith/upload-cache.yaml +252 -0
- package/.github/workflows/publish-docs.yml +67 -0
- package/.release-please-manifest.json +1 -1
- package/CHANGELOG.md +22 -0
- package/README.md +45 -115
- package/agents/clear/choose-contents.mjs +170 -0
- package/agents/clear/clear-auth-tokens.mjs +111 -0
- package/agents/clear/clear-document-config.mjs +39 -0
- package/agents/clear/clear-document-structure.mjs +106 -0
- package/agents/clear/clear-generated-docs.mjs +51 -0
- package/agents/clear/index.yaml +23 -0
- package/agents/evaluate/code-snippet.mjs +93 -0
- package/agents/evaluate/document-structure.yaml +70 -0
- package/agents/evaluate/document.yaml +79 -0
- package/agents/evaluate/generate-report.mjs +78 -0
- package/agents/evaluate/index.yaml +39 -0
- package/agents/generate/document-structure-tools/add-document.mjs +56 -0
- package/agents/generate/document-structure-tools/delete-document.mjs +49 -0
- package/agents/generate/document-structure-tools/move-document.mjs +82 -0
- package/agents/generate/document-structure-tools/update-document.mjs +50 -0
- package/agents/generate/generate-structure.yaml +1 -1
- package/agents/generate/update-document-structure.yaml +42 -0
- package/agents/generate/user-review-document-structure.mjs +6 -4
- package/agents/init/index.mjs +1 -1
- package/agents/publish/publish-docs.mjs +12 -3
- package/agents/translate/choose-language.mjs +1 -1
- package/agents/update/batch-update-document.yaml +7 -0
- package/agents/update/check-update-is-single.mjs +38 -0
- package/agents/update/document-tools/update-document-content.mjs +293 -0
- package/agents/update/index.yaml +4 -10
- package/agents/update/update-document-detail.yaml +52 -0
- package/agents/update/update-single-document.yaml +15 -0
- package/agents/update/user-review-document.mjs +248 -0
- package/agents/utils/choose-docs.mjs +4 -2
- package/agents/utils/format-document-structure.mjs +12 -2
- package/agents/utils/load-document-all-content.mjs +84 -0
- package/agents/utils/load-sources.mjs +4 -1
- package/aigne.yaml +59 -20
- package/assets/report-template/report.html +198 -0
- package/biome.json +14 -2
- package/docs/advanced-how-it-works.ja.md +101 -0
- package/docs/advanced-how-it-works.zh-TW.md +101 -0
- package/docs/advanced-how-it-works.zh.md +20 -20
- package/docs/advanced-quality-assurance.ja.md +96 -0
- package/docs/advanced-quality-assurance.zh-TW.md +96 -0
- package/docs/advanced-quality-assurance.zh.md +18 -18
- package/docs/advanced.ja.md +16 -0
- package/docs/advanced.zh-TW.md +16 -0
- package/docs/advanced.zh.md +4 -4
- package/docs/changelog.ja.md +309 -0
- package/docs/changelog.zh-TW.md +309 -0
- package/docs/changelog.zh.md +23 -23
- package/docs/cli-reference.ja.md +210 -0
- package/docs/cli-reference.zh-TW.md +210 -0
- package/docs/cli-reference.zh.md +21 -21
- package/docs/configuration-interactive-setup.ja.md +135 -0
- package/docs/configuration-interactive-setup.zh-TW.md +135 -0
- package/docs/configuration-interactive-setup.zh.md +29 -29
- package/docs/configuration-language-support.ja.md +94 -0
- package/docs/configuration-language-support.zh-TW.md +94 -0
- package/docs/configuration-language-support.zh.md +13 -13
- package/docs/configuration-llm-setup.ja.md +54 -0
- package/docs/configuration-llm-setup.zh-TW.md +54 -0
- package/docs/configuration-llm-setup.zh.md +12 -12
- package/docs/configuration-preferences.ja.md +129 -0
- package/docs/configuration-preferences.zh-TW.md +129 -0
- package/docs/configuration-preferences.zh.md +36 -36
- package/docs/configuration.ja.md +172 -0
- package/docs/configuration.zh-TW.md +172 -0
- package/docs/configuration.zh.md +49 -49
- package/docs/features-generate-documentation.ja.md +101 -0
- package/docs/features-generate-documentation.zh-TW.md +101 -0
- package/docs/features-generate-documentation.zh.md +17 -17
- package/docs/features-publish-your-docs.ja.md +107 -0
- package/docs/features-publish-your-docs.zh-TW.md +107 -0
- package/docs/features-publish-your-docs.zh.md +22 -22
- package/docs/features-translate-documentation.ja.md +79 -0
- package/docs/features-translate-documentation.zh-TW.md +79 -0
- package/docs/features-translate-documentation.zh.md +12 -12
- package/docs/features-update-and-refine.ja.md +138 -0
- package/docs/features-update-and-refine.zh-TW.md +138 -0
- package/docs/features-update-and-refine.zh.md +21 -21
- package/docs/features.ja.md +52 -0
- package/docs/features.zh-TW.md +52 -0
- package/docs/features.zh.md +8 -8
- package/docs/getting-started.ja.md +123 -0
- package/docs/getting-started.zh-TW.md +123 -0
- package/docs/getting-started.zh.md +24 -24
- package/docs/overview.ja.md +30 -0
- package/docs/overview.zh-TW.md +30 -0
- package/docs/overview.zh.md +8 -8
- package/package.json +19 -11
- package/prompts/common/document/content-rules-core.md +19 -0
- package/prompts/common/document/media-handling-rules.md +9 -0
- package/prompts/common/document/role-and-personality.md +15 -0
- package/prompts/common/document/user-preferences.md +9 -0
- package/prompts/common/document-structure/conflict-resolution-guidance.md +16 -0
- package/prompts/common/document-structure/document-structure-rules.md +45 -0
- package/prompts/common/document-structure/glossary.md +7 -0
- package/prompts/common/document-structure/intj-traits.md +5 -0
- package/prompts/common/document-structure/output-constraints.md +9 -0
- package/prompts/common/document-structure/user-locale-rules.md +10 -0
- package/prompts/common/document-structure/user-preferences.md +9 -0
- package/prompts/detail/custom/custom-components.md +9 -1
- package/prompts/detail/document-rules.md +6 -6
- package/prompts/detail/generate-document.md +5 -45
- package/prompts/detail/update-document.md +145 -0
- package/prompts/evaluate/document-structure.md +94 -0
- package/prompts/evaluate/document.md +149 -0
- package/prompts/structure/document-rules.md +1 -1
- package/prompts/structure/generate-structure-system.md +74 -0
- package/prompts/structure/generate-structure-user.md +41 -0
- package/prompts/structure/update-document-structure.md +118 -0
- package/prompts/translate/translate-document.md +1 -1
- package/prompts/utils/feedback-refiner.md +3 -3
- package/release-please-config.json +1 -7
- package/tests/agents/clear/choose-contents.test.mjs +280 -0
- package/tests/agents/clear/clear-auth-tokens.test.mjs +268 -0
- package/tests/agents/clear/clear-document-config.test.mjs +167 -0
- package/tests/agents/clear/clear-document-structure.test.mjs +374 -0
- package/tests/agents/clear/clear-generated-docs.test.mjs +222 -0
- package/tests/agents/evaluate/code-snippet.test.mjs +163 -0
- package/tests/agents/evaluate/fixtures/api-services.md +87 -0
- package/tests/agents/evaluate/fixtures/js-sdk.md +94 -0
- package/tests/agents/evaluate/generate-report.test.mjs +312 -0
- package/tests/agents/generate/check-document-structure.test.mjs +0 -6
- package/tests/agents/generate/document-structure-tools/add-document.test.mjs +449 -0
- package/tests/agents/generate/document-structure-tools/delete-document.test.mjs +410 -0
- package/tests/agents/generate/document-structure-tools/move-document.test.mjs +476 -0
- package/tests/agents/generate/document-structure-tools/update-document.test.mjs +548 -0
- package/tests/agents/generate/generate-structure.test.mjs +0 -6
- package/tests/agents/generate/user-review-document-structure.test.mjs +9 -9
- package/tests/agents/publish/publish-docs.test.mjs +2 -2
- package/tests/agents/update/check-update-is-single.test.mjs +300 -0
- package/tests/agents/update/document-tools/update-document-content.test.mjs +326 -0
- package/tests/agents/update/user-review-document.test.mjs +561 -0
- package/tests/agents/utils/format-document-structure.test.mjs +100 -0
- package/tests/utils/auth-utils.test.mjs +239 -1
- package/tests/utils/blocklet.test.mjs +9 -7
- package/tests/utils/constants.test.mjs +1 -1
- package/tests/utils/d2-utils.test.mjs +1 -1
- package/tests/utils/deploy.test.mjs +310 -366
- package/tests/utils/kroki-utils.test.mjs +2 -15
- package/tests/utils/linter/fixtures/css/keyword-error.css +1 -0
- package/tests/utils/linter/fixtures/css/missing-semicolon.css +1 -0
- package/tests/utils/linter/fixtures/css/syntax-error.css +1 -0
- package/tests/utils/linter/fixtures/css/undeclare-variable.css +1 -0
- package/tests/utils/linter/fixtures/css/unused-variable.css +2 -0
- package/tests/utils/linter/fixtures/css/valid-code.css +1 -0
- package/tests/utils/linter/fixtures/dockerfile/keyword-error.dockerfile +1 -0
- package/tests/utils/linter/fixtures/dockerfile/missing-semicolon.dockerfile +2 -0
- package/tests/utils/linter/fixtures/dockerfile/syntax-error.dockerfile +2 -0
- package/tests/utils/linter/fixtures/dockerfile/undeclare-variable.dockerfile +1 -0
- package/tests/utils/linter/fixtures/dockerfile/unused-variable.dockerfile +1 -0
- package/tests/utils/linter/fixtures/dockerfile/valid-code.dockerfile +2 -0
- package/tests/utils/linter/fixtures/go/keyword-error.go +5 -0
- package/tests/utils/linter/fixtures/go/missing-semicolon.go +5 -0
- package/tests/utils/linter/fixtures/go/syntax-error.go +6 -0
- package/tests/utils/linter/fixtures/go/undeclare-variable.go +5 -0
- package/tests/utils/linter/fixtures/go/unused-variable.go +5 -0
- package/tests/utils/linter/fixtures/go/valid-code.go +7 -0
- package/tests/utils/linter/fixtures/js/keyword-error.js +3 -0
- package/tests/utils/linter/fixtures/js/missing-semicolon.js +6 -0
- package/tests/utils/linter/fixtures/js/syntax-error.js +4 -0
- package/tests/utils/linter/fixtures/js/undeclare-variable.js +3 -0
- package/tests/utils/linter/fixtures/js/unused-variable.js +7 -0
- package/tests/utils/linter/fixtures/js/valid-code.js +15 -0
- package/tests/utils/linter/fixtures/json/keyword-error.json +1 -0
- package/tests/utils/linter/fixtures/json/missing-semicolon.json +1 -0
- package/tests/utils/linter/fixtures/json/syntax-error.json +1 -0
- package/tests/utils/linter/fixtures/json/undeclare-variable.json +1 -0
- package/tests/utils/linter/fixtures/json/unused-variable.json +1 -0
- package/tests/utils/linter/fixtures/json/valid-code.json +1 -0
- package/tests/utils/linter/fixtures/jsx/keyword-error.jsx +5 -0
- package/tests/utils/linter/fixtures/jsx/missing-semicolon.jsx +5 -0
- package/tests/utils/linter/fixtures/jsx/syntax-error.jsx +5 -0
- package/tests/utils/linter/fixtures/jsx/undeclare-variable.jsx +5 -0
- package/tests/utils/linter/fixtures/jsx/unused-variable.jsx +4 -0
- package/tests/utils/linter/fixtures/jsx/valid-code.jsx +5 -0
- package/tests/utils/linter/fixtures/python/keyword-error.py +3 -0
- package/tests/utils/linter/fixtures/python/missing-semicolon.py +2 -0
- package/tests/utils/linter/fixtures/python/syntax-error.py +3 -0
- package/tests/utils/linter/fixtures/python/undeclare-variable.py +3 -0
- package/tests/utils/linter/fixtures/python/unused-variable.py +6 -0
- package/tests/utils/linter/fixtures/python/valid-code.py +12 -0
- package/tests/utils/linter/fixtures/ruby/keyword-error.rb +2 -0
- package/tests/utils/linter/fixtures/ruby/missing-semicolon.rb +1 -0
- package/tests/utils/linter/fixtures/ruby/syntax-error.rb +2 -0
- package/tests/utils/linter/fixtures/ruby/undeclare-variable.rb +1 -0
- package/tests/utils/linter/fixtures/ruby/unused-variable.rb +2 -0
- package/tests/utils/linter/fixtures/ruby/valid-code.rb +1 -0
- package/tests/utils/linter/fixtures/sass/keyword-error.sass +2 -0
- package/tests/utils/linter/fixtures/sass/missing-semicolon.sass +3 -0
- package/tests/utils/linter/fixtures/sass/syntax-error.sass +3 -0
- package/tests/utils/linter/fixtures/sass/undeclare-variable.sass +2 -0
- package/tests/utils/linter/fixtures/sass/unused-variable.sass +4 -0
- package/tests/utils/linter/fixtures/sass/valid-code.sass +2 -0
- package/tests/utils/linter/fixtures/scss/keyword-error.scss +1 -0
- package/tests/utils/linter/fixtures/scss/missing-semicolon.scss +1 -0
- package/tests/utils/linter/fixtures/scss/syntax-error.scss +1 -0
- package/tests/utils/linter/fixtures/scss/undeclare-variable.scss +1 -0
- package/tests/utils/linter/fixtures/scss/unused-variable.scss +2 -0
- package/tests/utils/linter/fixtures/scss/valid-code.scss +1 -0
- package/tests/utils/linter/fixtures/shell/keyword-error.sh +5 -0
- package/tests/utils/linter/fixtures/shell/missing-semicolon.sh +3 -0
- package/tests/utils/linter/fixtures/shell/syntax-error.sh +4 -0
- package/tests/utils/linter/fixtures/shell/undeclare-variable.sh +3 -0
- package/tests/utils/linter/fixtures/shell/unused-variable.sh +4 -0
- package/tests/utils/linter/fixtures/shell/valid-code.sh +3 -0
- package/tests/utils/linter/fixtures/ts/keyword-error.ts +1 -0
- package/tests/utils/linter/fixtures/ts/missing-semicolon.ts +1 -0
- package/tests/utils/linter/fixtures/ts/syntax-error.ts +1 -0
- package/tests/utils/linter/fixtures/ts/undeclare-variable.ts +1 -0
- package/tests/utils/linter/fixtures/ts/unused-variable.ts +3 -0
- package/tests/utils/linter/fixtures/ts/valid-code.ts +3 -0
- package/tests/utils/linter/fixtures/tsx/keyword-error.tsx +5 -0
- package/tests/utils/linter/fixtures/tsx/missing-semicolon.tsx +5 -0
- package/tests/utils/linter/fixtures/tsx/syntax-error.tsx +5 -0
- package/tests/utils/linter/fixtures/tsx/undeclare-variable.tsx +6 -0
- package/tests/utils/linter/fixtures/tsx/unused-variable.tsx +6 -0
- package/tests/utils/linter/fixtures/tsx/valid-code.tsx +5 -0
- package/tests/utils/linter/fixtures/vue/keyword-error.vue +6 -0
- package/tests/utils/linter/fixtures/vue/missing-semicolon.vue +6 -0
- package/tests/utils/linter/fixtures/vue/syntax-error.vue +6 -0
- package/tests/utils/linter/fixtures/vue/undeclare-variable.vue +6 -0
- package/tests/utils/linter/fixtures/vue/unused-variable.vue +7 -0
- package/tests/utils/linter/fixtures/vue/valid-code.vue +6 -0
- package/tests/utils/linter/fixtures/yaml/keyword-error.yml +1 -0
- package/tests/utils/linter/fixtures/yaml/missing-semicolon.yml +2 -0
- package/tests/utils/linter/fixtures/yaml/syntax-error.yml +1 -0
- package/tests/utils/linter/fixtures/yaml/undeclare-variable.yml +1 -0
- package/tests/utils/linter/fixtures/yaml/unused-variable.yml +2 -0
- package/tests/utils/linter/fixtures/yaml/valid-code.yml +3 -0
- package/tests/utils/linter/index.test.mjs +440 -0
- package/tests/utils/linter/scan-results.mjs +42 -0
- package/tests/utils/markdown/index.test.mjs +478 -0
- package/tests/utils/mermaid-validator.test.mjs +2 -2
- package/tests/utils/utils.test.mjs +3 -1
- package/types/document-schema.mjs +54 -0
- package/types/document-structure-schema.mjs +244 -0
- package/utils/auth-utils.mjs +131 -6
- package/utils/conflict-detector.mjs +5 -1
- package/utils/{constants.mjs → constants/index.mjs} +109 -0
- package/utils/constants/linter.mjs +102 -0
- package/utils/d2-utils.mjs +2 -4
- package/utils/debug.mjs +3 -0
- package/utils/deploy.mjs +81 -385
- package/utils/evaluate/report-utils.mjs +131 -0
- package/utils/file-utils.mjs +36 -1
- package/utils/kroki-utils.mjs +1 -1
- package/utils/linter/index.mjs +50 -0
- package/utils/markdown/index.mjs +26 -0
- package/utils/markdown-checker.mjs +1 -1
- package/utils/utils.mjs +19 -7
- package/prompts/structure/generate-structure.md +0 -161
package/utils/deploy.mjs
CHANGED
|
@@ -1,410 +1,106 @@
|
|
|
1
|
+
import { BrokerClient, STEPS } from "@blocklet/payment-broker-client/node";
|
|
1
2
|
import chalk from "chalk";
|
|
2
|
-
import
|
|
3
|
-
import {
|
|
4
|
-
import { PAYMENT_KIT_DID } from "./constants.mjs";
|
|
3
|
+
import open from "open";
|
|
4
|
+
import { getOfficialAccessToken } from "./auth-utils.mjs";
|
|
5
5
|
import { saveValueToConfig } from "./utils.mjs";
|
|
6
6
|
|
|
7
|
-
// ====================
|
|
7
|
+
// ==================== Configuration ====================
|
|
8
8
|
const BASE_URL = process.env.DOC_SMITH_BASE_URL || "";
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
const TIMEOUTS = {
|
|
13
|
-
paymentWait: 300, // Step 2: Payment wait timeout (5 minutes)
|
|
14
|
-
installation: 300, // Step 3: Installation timeout (5 minutes)
|
|
15
|
-
serviceStart: 300, // Step 4: Website startup timeout (5 minutes)
|
|
9
|
+
const SUCCESS_MESSAGE = {
|
|
10
|
+
en: "Congratulations! Your website has been successfully installed. You can return to the command-line tool to continue the next steps.",
|
|
11
|
+
zh: "恭喜您,你的网站已安装成功!可以返回命令行工具继续后续操作!",
|
|
16
12
|
};
|
|
17
13
|
|
|
18
|
-
// ==================== Utility Functions ====================
|
|
19
|
-
|
|
20
|
-
/**
|
|
21
|
-
* Generic polling utility with timeout and retry logic
|
|
22
|
-
* @param {Object} options - Polling configuration
|
|
23
|
-
* @param {Function} options.checkCondition - Async function that returns result if condition met, null/false if not
|
|
24
|
-
* @param {number} options.maxAttempts - Maximum number of attempts
|
|
25
|
-
* @param {number} options.intervalMs - Interval between attempts in milliseconds
|
|
26
|
-
* @param {string} options.timeoutMessage - Error message for timeout
|
|
27
|
-
* @param {string} options.stepName - Name of the step for logging (optional)
|
|
28
|
-
* @returns {Promise<any>} Result from checkCondition when successful
|
|
29
|
-
*/
|
|
30
|
-
async function pollWithTimeout({
|
|
31
|
-
checkCondition,
|
|
32
|
-
maxAttempts,
|
|
33
|
-
intervalMs = INTERVAL_MS,
|
|
34
|
-
timeoutMessage,
|
|
35
|
-
stepName = "Operation",
|
|
36
|
-
}) {
|
|
37
|
-
let attempts = 0;
|
|
38
|
-
|
|
39
|
-
while (attempts < maxAttempts) {
|
|
40
|
-
attempts++;
|
|
41
|
-
|
|
42
|
-
try {
|
|
43
|
-
const result = await checkCondition();
|
|
44
|
-
if (result !== null && result !== false) {
|
|
45
|
-
return result;
|
|
46
|
-
}
|
|
47
|
-
} catch (_error) {
|
|
48
|
-
// Log error for debugging but continue retrying unless it's the last attempt
|
|
49
|
-
if (attempts === maxAttempts) {
|
|
50
|
-
throw new Error(`${timeoutMessage} (${stepName} failed after ${maxAttempts} attempts)`);
|
|
51
|
-
}
|
|
52
|
-
// Continue retrying for non-fatal errors
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
// If this is the last attempt, don't wait - just exit the loop
|
|
56
|
-
if (attempts === maxAttempts) {
|
|
57
|
-
break;
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
// Wait before retry
|
|
61
|
-
await new Promise((resolve) => setTimeout(resolve, intervalMs));
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
// If we reach here, all attempts were exhausted
|
|
65
|
-
throw new Error(`${timeoutMessage} (${stepName} timed out after ${maxAttempts} attempts)`);
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
// ==================== API Endpoints ====================
|
|
69
|
-
const API_ENDPOINTS = {
|
|
70
|
-
createCheckout: `/api/checkout-sessions/start`,
|
|
71
|
-
paymentPage: `/checkout/pay/{id}`,
|
|
72
|
-
orderStatus: `/api/vendors/order/{id}/status`,
|
|
73
|
-
orderDetail: `/api/vendors/order/{id}/detail`,
|
|
74
|
-
};
|
|
75
|
-
|
|
76
|
-
let prefix = "";
|
|
77
|
-
let paymentLinkId = "";
|
|
78
14
|
/**
|
|
79
15
|
* Deploy a new Discuss Kit Website and return the installation URL
|
|
80
|
-
* @
|
|
16
|
+
* @param {string} id - Cached checkout ID (optional)
|
|
17
|
+
* @param {string} cachedUrl - Cached payment URL (optional)
|
|
18
|
+
* @returns {Promise<Object>} - The deployment result with URLs
|
|
81
19
|
*/
|
|
82
20
|
export async function deploy(id, cachedUrl) {
|
|
83
|
-
const
|
|
84
|
-
BASE_URL,
|
|
85
|
-
PAYMENT_KIT_DID,
|
|
86
|
-
);
|
|
87
|
-
prefix = mountPoint;
|
|
88
|
-
paymentLinkId = PAYMENT_LINK_ID;
|
|
89
|
-
|
|
90
|
-
if (!PAYMENT_LINK_ID) {
|
|
91
|
-
const { PAYMENT_LINK_ID: id } = await getComponentInfoWithMountPoint(
|
|
92
|
-
joinURL(BASE_URL, mountPoint),
|
|
93
|
-
PAYMENT_KIT_DID,
|
|
94
|
-
);
|
|
95
|
-
paymentLinkId = id;
|
|
96
|
-
}
|
|
97
|
-
|
|
98
|
-
// Step 1: Create payment link and open
|
|
99
|
-
const cachedCheckoutId = await checkCacheCheckoutId(id);
|
|
100
|
-
let checkoutId = cachedCheckoutId;
|
|
101
|
-
let paymentUrl = cachedUrl;
|
|
102
|
-
if (!cachedCheckoutId) {
|
|
103
|
-
const { checkoutId: newCheckoutId, paymentUrl: newPaymentUrl } = await createPaymentSession();
|
|
104
|
-
checkoutId = newCheckoutId;
|
|
105
|
-
paymentUrl = newPaymentUrl;
|
|
106
|
-
}
|
|
107
|
-
|
|
108
|
-
if (!paymentUrl) {
|
|
109
|
-
paymentUrl = joinURL(BASE_URL, prefix, API_ENDPOINTS.paymentPage.replace("{id}", checkoutId));
|
|
110
|
-
}
|
|
111
|
-
if (cachedCheckoutId !== checkoutId) {
|
|
112
|
-
await openBrowser(paymentUrl);
|
|
113
|
-
}
|
|
114
|
-
|
|
115
|
-
// Step 2: Wait for payment completion
|
|
116
|
-
console.log(`⏳ Step 1/4: Waiting for payment...`);
|
|
117
|
-
console.log(`🔗 Payment link: ${chalk.cyan(paymentUrl)}\n`);
|
|
118
|
-
await pollPaymentStatus(checkoutId);
|
|
119
|
-
await saveValueToConfig("checkoutId", checkoutId, "Checkout ID for document deployment website");
|
|
120
|
-
await saveValueToConfig("paymentUrl", paymentUrl, "Payment URL for document deployment website");
|
|
121
|
-
|
|
122
|
-
// Step 3: Wait for website installation
|
|
123
|
-
console.log(`📦 Step 2/4: Installing Website...`);
|
|
124
|
-
const readyVendors = await waitInstallation(checkoutId);
|
|
125
|
-
|
|
126
|
-
// Step 4: Wait for website startup
|
|
127
|
-
console.log(`🚀 Step 3/4: Starting Website...`);
|
|
128
|
-
const runningVendors = await waitWebsiteRunning(readyVendors);
|
|
129
|
-
|
|
130
|
-
// Step 5: Get final URL
|
|
131
|
-
console.log(`🌐 Step 4/4: Getting Website URL...`);
|
|
132
|
-
const urlInfo = await getDashboardAndUrl(checkoutId, runningVendors);
|
|
133
|
-
const { appUrl, homeUrl, token, subscriptionUrl } = urlInfo || {};
|
|
134
|
-
|
|
135
|
-
console.log(`\n🔗 Your website is available at: ${chalk.cyan(homeUrl || appUrl)}`);
|
|
136
|
-
|
|
137
|
-
if (subscriptionUrl) {
|
|
138
|
-
console.log(`🔗 Your subscription management URL: ${chalk.cyan(subscriptionUrl)}\n`);
|
|
139
|
-
} else {
|
|
140
|
-
// just log one space line
|
|
141
|
-
console.log("");
|
|
142
|
-
}
|
|
143
|
-
|
|
144
|
-
return {
|
|
145
|
-
appUrl,
|
|
146
|
-
homeUrl,
|
|
147
|
-
token,
|
|
148
|
-
};
|
|
149
|
-
}
|
|
150
|
-
|
|
151
|
-
/**
|
|
152
|
-
* Check if there is a cached checkoutId
|
|
153
|
-
*/
|
|
154
|
-
async function checkCacheCheckoutId(checkoutId) {
|
|
155
|
-
try {
|
|
156
|
-
if (!checkoutId) {
|
|
157
|
-
return "";
|
|
158
|
-
}
|
|
159
|
-
|
|
160
|
-
const orderStatusUrl = joinURL(
|
|
161
|
-
BASE_URL,
|
|
162
|
-
prefix,
|
|
163
|
-
API_ENDPOINTS.orderStatus.replace("{id}", checkoutId),
|
|
164
|
-
);
|
|
165
|
-
const response = await fetch(orderStatusUrl);
|
|
166
|
-
|
|
167
|
-
if (!response.ok) {
|
|
168
|
-
throw new Error(`HTTP error! status: ${response.status}`);
|
|
169
|
-
}
|
|
170
|
-
|
|
171
|
-
const data = await response.json();
|
|
172
|
-
|
|
173
|
-
if (data.error) {
|
|
174
|
-
throw new Error(data.error);
|
|
175
|
-
}
|
|
176
|
-
|
|
177
|
-
// Check payment status and vendors status
|
|
178
|
-
const isPaid = data.payment_status === "paid";
|
|
179
|
-
|
|
180
|
-
return isPaid ? checkoutId : "";
|
|
181
|
-
} catch (_error) {
|
|
182
|
-
await saveValueToConfig("checkoutId", "", "Checkout ID for document deployment website");
|
|
183
|
-
return "";
|
|
184
|
-
}
|
|
185
|
-
}
|
|
186
|
-
|
|
187
|
-
/**
|
|
188
|
-
* Create payment session - Step 1
|
|
189
|
-
*/
|
|
190
|
-
async function createPaymentSession() {
|
|
191
|
-
// 1. Call payment API
|
|
192
|
-
if (!paymentLinkId) {
|
|
193
|
-
throw new Error("Payment link ID not found");
|
|
194
|
-
}
|
|
195
|
-
|
|
196
|
-
const createCheckoutId = joinURL(BASE_URL, prefix, API_ENDPOINTS.createCheckout, paymentLinkId);
|
|
197
|
-
try {
|
|
198
|
-
const response = await fetch(createCheckoutId, {
|
|
199
|
-
method: "POST",
|
|
200
|
-
headers: { "Content-Type": "application/json" },
|
|
201
|
-
body: JSON.stringify({
|
|
202
|
-
needShortUrl: true,
|
|
203
|
-
metadata: {
|
|
204
|
-
page_info: {
|
|
205
|
-
has_vendor: true,
|
|
206
|
-
success_message: {
|
|
207
|
-
en: "Congratulations! Your website has been successfully installed. You can return to the command-line tool to continue the next steps.",
|
|
208
|
-
zh: "恭喜您,你的网站已安装成功!可以返回命令行工具继续后续操作!",
|
|
209
|
-
},
|
|
210
|
-
},
|
|
211
|
-
},
|
|
212
|
-
}),
|
|
213
|
-
});
|
|
214
|
-
|
|
215
|
-
if (!response.ok) {
|
|
216
|
-
throw new Error(`HTTP error! status: ${response.status}`);
|
|
217
|
-
}
|
|
218
|
-
|
|
219
|
-
const data = await response.json();
|
|
220
|
-
const checkoutId = data.checkoutSession.id;
|
|
221
|
-
const paymentUrl = data.paymentUrl;
|
|
21
|
+
const authToken = await getOfficialAccessToken(BASE_URL);
|
|
222
22
|
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
console.error(
|
|
226
|
-
`${chalk.red("❌")} Failed to create payment session:`,
|
|
227
|
-
error.message,
|
|
228
|
-
createCheckoutId,
|
|
229
|
-
);
|
|
230
|
-
throw new Error(`Failed to create payment session: ${error.message}`);
|
|
23
|
+
if (!authToken) {
|
|
24
|
+
throw new Error("Failed to get official access token");
|
|
231
25
|
}
|
|
232
|
-
}
|
|
233
|
-
|
|
234
|
-
/**
|
|
235
|
-
* Open browser with payment URL
|
|
236
|
-
*/
|
|
237
|
-
async function openBrowser(paymentUrl) {
|
|
238
|
-
const { default: open } = await import("open");
|
|
239
|
-
try {
|
|
240
|
-
await open(paymentUrl);
|
|
241
|
-
} catch (_error) {
|
|
242
|
-
console.log(`${chalk.yellow("⚠️ Could not open browser automatically.")}`);
|
|
243
|
-
console.log(`${chalk.blue("Please manually open this URL:")} ${chalk.cyan(paymentUrl)}`);
|
|
244
|
-
}
|
|
245
|
-
}
|
|
246
|
-
|
|
247
|
-
/**
|
|
248
|
-
* Wait for payment completion - Step 2 (5 minute timeout)
|
|
249
|
-
*/
|
|
250
|
-
async function pollPaymentStatus(checkoutId) {
|
|
251
|
-
return pollWithTimeout({
|
|
252
|
-
checkCondition: async () => {
|
|
253
|
-
const orderStatusUrl = joinURL(
|
|
254
|
-
BASE_URL,
|
|
255
|
-
prefix,
|
|
256
|
-
API_ENDPOINTS.orderStatus.replace("{id}", checkoutId),
|
|
257
|
-
);
|
|
258
|
-
const response = await fetch(orderStatusUrl);
|
|
259
26
|
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
// Check payment status and vendors status
|
|
271
|
-
const isPaid = data.payment_status === "paid";
|
|
272
|
-
if (isPaid) {
|
|
273
|
-
return data.vendors;
|
|
274
|
-
}
|
|
275
|
-
|
|
276
|
-
return null; // Not ready yet, continue polling
|
|
27
|
+
const client = new BrokerClient({
|
|
28
|
+
baseUrl: BASE_URL,
|
|
29
|
+
authToken,
|
|
30
|
+
paymentLinkKey: "PAYMENT_LINK_ID",
|
|
31
|
+
timeout: 300000,
|
|
32
|
+
polling: {
|
|
33
|
+
interval: 3000,
|
|
34
|
+
maxAttempts: 100,
|
|
35
|
+
backoffStrategy: "linear",
|
|
277
36
|
},
|
|
278
|
-
maxAttempts: Math.ceil((TIMEOUTS.paymentWait * 1000) / INTERVAL_MS),
|
|
279
|
-
intervalMs: INTERVAL_MS,
|
|
280
|
-
timeoutMessage: "Payment timeout - please complete payment within 5 minutes",
|
|
281
|
-
stepName: "Payment",
|
|
282
37
|
});
|
|
283
|
-
}
|
|
284
|
-
|
|
285
|
-
/**
|
|
286
|
-
* Wait for installation completion - Step 3
|
|
287
|
-
*/
|
|
288
|
-
async function waitInstallation(checkoutId) {
|
|
289
|
-
return pollWithTimeout({
|
|
290
|
-
checkCondition: async () => {
|
|
291
|
-
const orderStatusUrl = joinURL(
|
|
292
|
-
BASE_URL,
|
|
293
|
-
prefix,
|
|
294
|
-
API_ENDPOINTS.orderStatus.replace("{id}", checkoutId),
|
|
295
|
-
);
|
|
296
|
-
const response = await fetch(orderStatusUrl);
|
|
297
|
-
|
|
298
|
-
if (!response.ok) {
|
|
299
|
-
throw new Error(`HTTP error! status: ${response.status}`);
|
|
300
|
-
}
|
|
301
38
|
|
|
302
|
-
|
|
39
|
+
console.log(`🚀 Starting deployment...`);
|
|
303
40
|
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
const isInstalled = data.vendors?.every((vendor) => vendor.progress >= 80 && vendor.appUrl);
|
|
310
|
-
if (isInstalled) {
|
|
311
|
-
return data.vendors;
|
|
312
|
-
}
|
|
313
|
-
|
|
314
|
-
return null; // Not ready yet, continue polling
|
|
41
|
+
const result = await client.deploy({
|
|
42
|
+
cachedCheckoutId: id,
|
|
43
|
+
cachedPaymentUrl: cachedUrl,
|
|
44
|
+
pageInfo: {
|
|
45
|
+
successMessage: SUCCESS_MESSAGE,
|
|
315
46
|
},
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
if (blockletInfo.status === "running") {
|
|
335
|
-
return vendor;
|
|
336
|
-
}
|
|
337
|
-
return null;
|
|
338
|
-
} catch (_error) {
|
|
339
|
-
return null;
|
|
47
|
+
hooks: {
|
|
48
|
+
[STEPS.PAYMENT_PENDING]: async ({ sessionId, paymentUrl, isResuming }) => {
|
|
49
|
+
console.log(`⏳ Step 1/4: Waiting for payment...`);
|
|
50
|
+
console.log(`🔗 Payment link: ${chalk.cyan(paymentUrl)}\n`);
|
|
51
|
+
|
|
52
|
+
await saveValueToConfig(
|
|
53
|
+
"checkoutId",
|
|
54
|
+
sessionId,
|
|
55
|
+
"Checkout ID for document deployment website",
|
|
56
|
+
);
|
|
57
|
+
await saveValueToConfig(
|
|
58
|
+
"paymentUrl",
|
|
59
|
+
paymentUrl,
|
|
60
|
+
"Payment URL for document deployment website",
|
|
61
|
+
);
|
|
62
|
+
|
|
63
|
+
if (!isResuming) {
|
|
64
|
+
await open(paymentUrl);
|
|
340
65
|
}
|
|
341
|
-
}
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
66
|
+
},
|
|
67
|
+
|
|
68
|
+
[STEPS.INSTALLATION_STARTING]: () => {
|
|
69
|
+
console.log(`📦 Step 2/4: Installing Website...`);
|
|
70
|
+
},
|
|
71
|
+
|
|
72
|
+
[STEPS.SERVICE_STARTING]: () => {
|
|
73
|
+
console.log(`🚀 Step 3/4: Starting Website...`);
|
|
74
|
+
},
|
|
75
|
+
|
|
76
|
+
[STEPS.ACCESS_PREPARING]: () => {
|
|
77
|
+
console.log(`🌐 Step 4/4: Getting Website URL...`);
|
|
78
|
+
},
|
|
79
|
+
|
|
80
|
+
[STEPS.ACCESS_READY]: async ({ appUrl, homeUrl, subscriptionUrl }) => {
|
|
81
|
+
console.log(`\n🔗 Your website is available at: ${chalk.cyan(homeUrl || appUrl)}`);
|
|
82
|
+
if (subscriptionUrl) {
|
|
83
|
+
console.log(`🔗 Your subscription management URL: ${chalk.cyan(subscriptionUrl)}\n`);
|
|
84
|
+
} else {
|
|
85
|
+
console.log("");
|
|
86
|
+
}
|
|
87
|
+
},
|
|
88
|
+
},
|
|
349
89
|
|
|
350
|
-
|
|
90
|
+
onError: (error, step) => {
|
|
91
|
+
console.error(`${chalk.red("❌")} Deployment failed at ${step || "unknown step"}:`);
|
|
92
|
+
console.error(` ${error.message}`);
|
|
351
93
|
},
|
|
352
|
-
maxAttempts: Math.ceil((TIMEOUTS.serviceStart * 1000) / INTERVAL_MS),
|
|
353
|
-
intervalMs: INTERVAL_MS,
|
|
354
|
-
timeoutMessage: "Website start timeout - website failed to start within 5 minutes",
|
|
355
|
-
stepName: "Website Start",
|
|
356
94
|
});
|
|
357
|
-
}
|
|
358
|
-
|
|
359
|
-
/**
|
|
360
|
-
* Get final URL - Step 5
|
|
361
|
-
*/
|
|
362
|
-
async function getDashboardAndUrl(checkoutId, runningVendors) {
|
|
363
|
-
try {
|
|
364
|
-
// 5. Get order details
|
|
365
|
-
const orderDetailUrl = joinURL(
|
|
366
|
-
BASE_URL,
|
|
367
|
-
prefix,
|
|
368
|
-
API_ENDPOINTS.orderDetail.replace("{id}", checkoutId),
|
|
369
|
-
);
|
|
370
|
-
const response = await fetch(orderDetailUrl);
|
|
371
|
-
|
|
372
|
-
if (!response.ok) {
|
|
373
|
-
throw new Error(`HTTP error! status: ${response.status}`);
|
|
374
|
-
}
|
|
375
|
-
|
|
376
|
-
const data = await response.json();
|
|
377
95
|
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
}
|
|
96
|
+
const { appUrl, homeUrl, subscriptionUrl, dashboardUrl, vendors } = result;
|
|
97
|
+
const token = vendors?.[0]?.token;
|
|
381
98
|
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
}
|
|
390
|
-
|
|
391
|
-
return {
|
|
392
|
-
appUrl,
|
|
393
|
-
subscriptionUrl: data.subscriptionUrl,
|
|
394
|
-
dashboardUrl: data.vendors[0]?.dashboardUrl,
|
|
395
|
-
homeUrl: data.vendors[0]?.homeUrl,
|
|
396
|
-
token: data.vendors[0]?.token,
|
|
397
|
-
};
|
|
398
|
-
} catch (error) {
|
|
399
|
-
console.error(`${chalk.red("❌")} Failed to get order details:`, error.message);
|
|
400
|
-
// If getting details fails, use the appUrl of running vendor
|
|
401
|
-
return {
|
|
402
|
-
appUrl: runningVendors[0]?.appUrl || null,
|
|
403
|
-
dashboardUrl: runningVendors[0]?.dashboardUrl || null,
|
|
404
|
-
homeUrl: runningVendors[0]?.homeUrl || null,
|
|
405
|
-
token: runningVendors[0]?.token || null,
|
|
406
|
-
};
|
|
407
|
-
}
|
|
99
|
+
return {
|
|
100
|
+
appUrl,
|
|
101
|
+
homeUrl,
|
|
102
|
+
dashboardUrl,
|
|
103
|
+
subscriptionUrl,
|
|
104
|
+
token,
|
|
105
|
+
};
|
|
408
106
|
}
|
|
409
|
-
|
|
410
|
-
export default deploy;
|
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
import { existsSync } from "node:fs";
|
|
2
|
+
import { mkdir, readFile, writeFile } from "node:fs/promises";
|
|
3
|
+
import { dirname, join } from "node:path";
|
|
4
|
+
import { fileURLToPath } from "node:url";
|
|
5
|
+
import { toRelativePath } from "../utils.mjs";
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Create report structure with evaluation data
|
|
9
|
+
* @param {Object} params - Parameters for creating the report
|
|
10
|
+
* @param {string} params.timestamp - Report generation timestamp
|
|
11
|
+
* @param {Object} params.metadata - Additional metadata for the report
|
|
12
|
+
* @param {Object} params.structureEvaluation - Structure evaluation results
|
|
13
|
+
* @param {Array} params.documentEvaluations - Individual document evaluations
|
|
14
|
+
* @param {string} params.projectName - Name of the project
|
|
15
|
+
* @param {string} params.projectDesc - Project description
|
|
16
|
+
* @param {string} params.projectLogo - Project logo URL
|
|
17
|
+
* @param {string} params.documentPurpose - Purpose of the documentation
|
|
18
|
+
* @param {Array} params.targetAudienceTypes - Types of target audience
|
|
19
|
+
* @param {string} params.readerKnowledgeLevel - Expected reader knowledge level
|
|
20
|
+
* @param {string} params.documentationDepth - Depth of documentation
|
|
21
|
+
* @param {string} params.targetAudience - Target audience description
|
|
22
|
+
* @returns {Object} Complete report structure
|
|
23
|
+
*/
|
|
24
|
+
export function createReportStructure({
|
|
25
|
+
timestamp,
|
|
26
|
+
metadata,
|
|
27
|
+
structureEvaluation,
|
|
28
|
+
documentEvaluations,
|
|
29
|
+
projectName,
|
|
30
|
+
projectDesc,
|
|
31
|
+
projectLogo,
|
|
32
|
+
documentPurpose,
|
|
33
|
+
targetAudienceTypes,
|
|
34
|
+
readerKnowledgeLevel,
|
|
35
|
+
documentationDepth,
|
|
36
|
+
targetAudience,
|
|
37
|
+
}) {
|
|
38
|
+
return {
|
|
39
|
+
documentInfo: {
|
|
40
|
+
projectName,
|
|
41
|
+
projectDesc,
|
|
42
|
+
projectLogo,
|
|
43
|
+
documentPurpose,
|
|
44
|
+
targetAudienceTypes,
|
|
45
|
+
readerKnowledgeLevel,
|
|
46
|
+
documentationDepth,
|
|
47
|
+
targetAudience,
|
|
48
|
+
},
|
|
49
|
+
metadata: {
|
|
50
|
+
version: "0.1.0",
|
|
51
|
+
generatedBy: "AIGNE Doc Smith",
|
|
52
|
+
generatedAt: timestamp,
|
|
53
|
+
documentCount: documentEvaluations.length,
|
|
54
|
+
...metadata,
|
|
55
|
+
},
|
|
56
|
+
structureEvaluation: {
|
|
57
|
+
type: "document-structure",
|
|
58
|
+
results: structureEvaluation,
|
|
59
|
+
},
|
|
60
|
+
documentEvaluations: {
|
|
61
|
+
type: "document-content",
|
|
62
|
+
results: documentEvaluations,
|
|
63
|
+
},
|
|
64
|
+
};
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
/**
|
|
68
|
+
* Ensure directory exists, create if it doesn't
|
|
69
|
+
* @param {string} dirPath - Directory path to ensure exists
|
|
70
|
+
*/
|
|
71
|
+
export async function ensureDirectoryExists(dirPath) {
|
|
72
|
+
if (!existsSync(dirPath)) {
|
|
73
|
+
await mkdir(dirPath, { recursive: true });
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
/**
|
|
78
|
+
* Generate timestamp formatted for folder names
|
|
79
|
+
* @param {Date} [date] - Date object, defaults to current date
|
|
80
|
+
* @returns {string} Formatted timestamp string
|
|
81
|
+
*/
|
|
82
|
+
export function generateTimestampForFolder(date = new Date()) {
|
|
83
|
+
const year = date.getFullYear();
|
|
84
|
+
const month = String(date.getMonth() + 1).padStart(2, "0");
|
|
85
|
+
const day = String(date.getDate()).padStart(2, "0");
|
|
86
|
+
const hours = String(date.getHours()).padStart(2, "0");
|
|
87
|
+
const minutes = String(date.getMinutes()).padStart(2, "0");
|
|
88
|
+
|
|
89
|
+
return `${year}-${month}-${day}_${hours}-${minutes}`;
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
/**
|
|
93
|
+
* Copy HTML report template to the report directory
|
|
94
|
+
* @param {string} targetDir - Target directory for the HTML report
|
|
95
|
+
* @returns {Promise<string>} Path to the copied HTML file
|
|
96
|
+
*/
|
|
97
|
+
export async function copyHtmlReportTemplate(targetDir, data) {
|
|
98
|
+
const __filename = fileURLToPath(import.meta.url);
|
|
99
|
+
const __dirname = dirname(__filename);
|
|
100
|
+
|
|
101
|
+
// Path to the HTML template
|
|
102
|
+
const templatePath = join(__dirname, "../../", "assets", "report-template", "report.html");
|
|
103
|
+
const targetPath = join(targetDir, "integrity-report.html");
|
|
104
|
+
|
|
105
|
+
const templateReport = await readFile(templatePath, "utf-8");
|
|
106
|
+
const templateData = templateReport.replace("window.__REPORT_DATA__", JSON.stringify(data));
|
|
107
|
+
await writeFile(targetPath, templateData);
|
|
108
|
+
return toRelativePath(targetPath);
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
/**
|
|
112
|
+
* Generate success message with report links
|
|
113
|
+
* @param {string} jsonReportPath - Path to the JSON report
|
|
114
|
+
* @param {string} htmlReportPath - Path to the HTML report
|
|
115
|
+
* @returns {string} Success message with links
|
|
116
|
+
*/
|
|
117
|
+
export function generateReportSuccessMessage(jsonReportPath, htmlReportPath) {
|
|
118
|
+
return `# ✅ Documentation Evaluation Report Generated Successfully!
|
|
119
|
+
|
|
120
|
+
Generated evaluation report and saved to:
|
|
121
|
+
|
|
122
|
+
\`${jsonReportPath}\`
|
|
123
|
+
|
|
124
|
+
## 📊 View HTML Report
|
|
125
|
+
|
|
126
|
+
Open in your browser to view detailed analysis:
|
|
127
|
+
|
|
128
|
+
\`${htmlReportPath}\`
|
|
129
|
+
|
|
130
|
+
`;
|
|
131
|
+
}
|
package/utils/file-utils.mjs
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { execSync } from "node:child_process";
|
|
2
|
-
import { access, readFile } from "node:fs/promises";
|
|
2
|
+
import { access, readFile, stat } from "node:fs/promises";
|
|
3
3
|
import path from "node:path";
|
|
4
4
|
import { glob } from "glob";
|
|
5
5
|
|
|
@@ -208,3 +208,38 @@ export async function getFilesWithGlob(dir, includePatterns, excludePatterns, gi
|
|
|
208
208
|
return [];
|
|
209
209
|
}
|
|
210
210
|
}
|
|
211
|
+
|
|
212
|
+
/**
|
|
213
|
+
* Check if a path exists
|
|
214
|
+
* @param {string} targetPath - Path to check
|
|
215
|
+
* @returns {Promise<boolean>} True if path exists
|
|
216
|
+
*/
|
|
217
|
+
export async function pathExists(targetPath) {
|
|
218
|
+
try {
|
|
219
|
+
await stat(targetPath);
|
|
220
|
+
return true;
|
|
221
|
+
} catch (error) {
|
|
222
|
+
if (error.code === "ENOENT") return false;
|
|
223
|
+
throw error;
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
/**
|
|
228
|
+
* Convert absolute path to display path relative to current working directory
|
|
229
|
+
* @param {string} targetPath - Absolute path to convert
|
|
230
|
+
* @returns {string} Display path (relative or absolute)
|
|
231
|
+
*/
|
|
232
|
+
export function toDisplayPath(targetPath) {
|
|
233
|
+
const rel = path.relative(process.cwd(), targetPath);
|
|
234
|
+
return rel.startsWith("..") ? targetPath : rel || ".";
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
/**
|
|
238
|
+
* Resolve path to absolute path
|
|
239
|
+
* @param {string} value - Path to resolve
|
|
240
|
+
* @returns {string|undefined} Absolute path or undefined if no value provided
|
|
241
|
+
*/
|
|
242
|
+
export function resolveToAbsolute(value) {
|
|
243
|
+
if (!value) return undefined;
|
|
244
|
+
return path.isAbsolute(value) ? value : path.resolve(process.cwd(), value);
|
|
245
|
+
}
|