@aigne/doc-smith 0.9.2 → 0.9.3-beta
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/CHANGELOG.md +7 -0
- package/agents/publish/publish-docs.mjs +25 -14
- package/package.json +5 -5
- package/utils/auth-utils.mjs +107 -86
- package/utils/deploy.mjs +5 -5
- package/utils/request.mjs +3 -0
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,12 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## [0.9.3-beta](https://github.com/AIGNE-io/aigne-doc-smith/compare/v0.9.2...v0.9.3-beta) (2025-11-13)
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
### Features
|
|
7
|
+
|
|
8
|
+
* **docs:** Enhance publishing with Discuss Kit and localized access tokens ([#301](https://github.com/AIGNE-io/aigne-doc-smith/issues/301)) ([c34f16f](https://github.com/AIGNE-io/aigne-doc-smith/commit/c34f16fdc3a07cb1408f50c5e10aa80f1c7b90cf))
|
|
9
|
+
|
|
3
10
|
## [0.9.2](https://github.com/AIGNE-io/aigne-doc-smith/compare/v0.9.2-beta...v0.9.2) (2025-11-12)
|
|
4
11
|
|
|
5
12
|
## [0.9.2-beta](https://github.com/AIGNE-io/aigne-doc-smith/compare/v0.9.1...v0.9.2-beta) (2025-11-12)
|
|
@@ -4,7 +4,11 @@ import { BrokerClient } from "@blocklet/payment-broker-client/node";
|
|
|
4
4
|
import chalk from "chalk";
|
|
5
5
|
import fs from "fs-extra";
|
|
6
6
|
|
|
7
|
-
import {
|
|
7
|
+
import {
|
|
8
|
+
getAccessToken,
|
|
9
|
+
getDiscussKitMountPoint,
|
|
10
|
+
getOfficialAccessToken,
|
|
11
|
+
} from "../../utils/auth-utils.mjs";
|
|
8
12
|
import {
|
|
9
13
|
CLOUD_SERVICE_URL_PROD,
|
|
10
14
|
DISCUSS_KIT_STORE_URL,
|
|
@@ -17,6 +21,7 @@ import { deploy } from "../../utils/deploy.mjs";
|
|
|
17
21
|
import { getGithubRepoUrl, loadConfigFromFile, saveValueToConfig } from "../../utils/utils.mjs";
|
|
18
22
|
import updateBranding from "../utils/update-branding.mjs";
|
|
19
23
|
import { isRemoteFile, downloadAndUploadImage } from "../../utils/file-utils.mjs";
|
|
24
|
+
import { joinURL } from "ufo";
|
|
20
25
|
|
|
21
26
|
const BASE_URL = process.env.DOC_SMITH_BASE_URL || CLOUD_SERVICE_URL_PROD;
|
|
22
27
|
|
|
@@ -72,13 +77,12 @@ export default async function publishDocs(
|
|
|
72
77
|
let client = null;
|
|
73
78
|
let authToken = null;
|
|
74
79
|
let sessionId = null;
|
|
80
|
+
let locale = config?.locale;
|
|
75
81
|
|
|
76
82
|
if (!hasInputAppUrl) {
|
|
77
83
|
authToken = await getOfficialAccessToken(BASE_URL, false);
|
|
78
84
|
|
|
79
85
|
sessionId = "";
|
|
80
|
-
let paymentLink = "";
|
|
81
|
-
|
|
82
86
|
if (authToken) {
|
|
83
87
|
client = new BrokerClient({ baseUrl: BASE_URL, authToken });
|
|
84
88
|
const info = await client.checkCacheSession({
|
|
@@ -86,7 +90,6 @@ export default async function publishDocs(
|
|
|
86
90
|
sessionId: config?.checkoutId,
|
|
87
91
|
});
|
|
88
92
|
sessionId = info.sessionId;
|
|
89
|
-
paymentLink = info.paymentLink;
|
|
90
93
|
}
|
|
91
94
|
|
|
92
95
|
const choice = await options.prompts.select({
|
|
@@ -137,7 +140,8 @@ export default async function publishDocs(
|
|
|
137
140
|
appUrl = userInput.includes("://") ? userInput : `https://${userInput}`;
|
|
138
141
|
} else if (["new-instance", "new-instance-continue"].includes(choice)) {
|
|
139
142
|
// resume previous website setup
|
|
140
|
-
|
|
143
|
+
const isNewInstance = choice === "new-instance";
|
|
144
|
+
if (!isNewInstance) {
|
|
141
145
|
shouldSyncBranding = config?.shouldSyncBranding ?? void 0;
|
|
142
146
|
if (shouldSyncBranding !== void 0) {
|
|
143
147
|
shouldWithBranding = shouldWithBranding ?? shouldSyncBranding;
|
|
@@ -165,7 +169,7 @@ export default async function publishDocs(
|
|
|
165
169
|
|
|
166
170
|
try {
|
|
167
171
|
let id = "";
|
|
168
|
-
if (
|
|
172
|
+
if (!isNewInstance) {
|
|
169
173
|
id = sessionId;
|
|
170
174
|
console.log(`\nResuming your previous website setup...`);
|
|
171
175
|
} else {
|
|
@@ -175,11 +179,13 @@ export default async function publishDocs(
|
|
|
175
179
|
appUrl: homeUrl,
|
|
176
180
|
token: ltToken,
|
|
177
181
|
sessionId: newSessionId,
|
|
178
|
-
|
|
182
|
+
data,
|
|
183
|
+
} = (await deploy(id, isNewInstance ? locale : undefined)) || {};
|
|
179
184
|
|
|
180
185
|
sessionId = newSessionId;
|
|
181
186
|
appUrl = homeUrl;
|
|
182
187
|
token = ltToken;
|
|
188
|
+
locale = data?.preferredLocale || locale;
|
|
183
189
|
} catch (error) {
|
|
184
190
|
const errorMsg = error?.message || "Unknown error occurred";
|
|
185
191
|
return { message: `${chalk.red("❌ Failed to create website:")} ${errorMsg}` };
|
|
@@ -189,9 +195,14 @@ export default async function publishDocs(
|
|
|
189
195
|
|
|
190
196
|
appUrl = appUrl ?? CLOUD_SERVICE_URL_PROD;
|
|
191
197
|
|
|
192
|
-
|
|
198
|
+
const appUrlInfo = new URL(appUrl);
|
|
199
|
+
|
|
200
|
+
const discussKitMountPoint = await getDiscussKitMountPoint(appUrlInfo.origin);
|
|
201
|
+
const discussKitUrl = joinURL(appUrlInfo.origin, discussKitMountPoint);
|
|
202
|
+
|
|
203
|
+
console.log(`\nPublishing your documentation to ${chalk.cyan(discussKitUrl)}\n`);
|
|
193
204
|
|
|
194
|
-
const accessToken = await getAccessToken(
|
|
205
|
+
const accessToken = await getAccessToken(appUrlInfo.origin, token, locale);
|
|
195
206
|
|
|
196
207
|
process.env.DOC_ROOT_DIR = docsDir;
|
|
197
208
|
|
|
@@ -211,7 +222,7 @@ export default async function publishDocs(
|
|
|
211
222
|
const { url: uploadedImageUrl, downloadFinalPath } = await downloadAndUploadImage(
|
|
212
223
|
projectInfo.icon,
|
|
213
224
|
docsDir,
|
|
214
|
-
|
|
225
|
+
discussKitUrl,
|
|
215
226
|
accessToken,
|
|
216
227
|
);
|
|
217
228
|
projectInfo.icon = uploadedImageUrl;
|
|
@@ -219,7 +230,7 @@ export default async function publishDocs(
|
|
|
219
230
|
}
|
|
220
231
|
|
|
221
232
|
if (shouldWithBranding) {
|
|
222
|
-
updateBranding({ appUrl, projectInfo, accessToken, finalPath });
|
|
233
|
+
updateBranding({ appUrl: discussKitUrl, projectInfo, accessToken, finalPath });
|
|
223
234
|
}
|
|
224
235
|
|
|
225
236
|
// Construct boardMeta object
|
|
@@ -243,7 +254,7 @@ export default async function publishDocs(
|
|
|
243
254
|
} = await publishDocsFn({
|
|
244
255
|
sidebarPath,
|
|
245
256
|
accessToken,
|
|
246
|
-
appUrl,
|
|
257
|
+
appUrl: discussKitUrl,
|
|
247
258
|
boardId,
|
|
248
259
|
autoCreateBoard: true,
|
|
249
260
|
// Pass additional project information if available
|
|
@@ -259,7 +270,7 @@ export default async function publishDocs(
|
|
|
259
270
|
if (success) {
|
|
260
271
|
// Save appUrl to config only when not using environment variable
|
|
261
272
|
if (!useEnvAppUrl) {
|
|
262
|
-
await saveValueToConfig("appUrl",
|
|
273
|
+
await saveValueToConfig("appUrl", appUrlInfo.origin);
|
|
263
274
|
}
|
|
264
275
|
|
|
265
276
|
// Save boardId to config if it was auto-created
|
|
@@ -286,7 +297,7 @@ export default async function publishDocs(
|
|
|
286
297
|
// clean up tmp work dir
|
|
287
298
|
await fs.rm(docsDir, { recursive: true, force: true });
|
|
288
299
|
} catch (error) {
|
|
289
|
-
message = `❌ Sorry, I encountered an error while publishing your documentation: ${error.message}`;
|
|
300
|
+
message = `❌ Sorry, I encountered an error while publishing your documentation: \n\n${error.message}`;
|
|
290
301
|
|
|
291
302
|
// clean up tmp work dir in case of error
|
|
292
303
|
try {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@aigne/doc-smith",
|
|
3
|
-
"version": "0.9.
|
|
3
|
+
"version": "0.9.3-beta",
|
|
4
4
|
"description": "AI-driven documentation generation tool built on the AIGNE Framework",
|
|
5
5
|
"publishConfig": {
|
|
6
6
|
"access": "public"
|
|
@@ -24,10 +24,10 @@
|
|
|
24
24
|
"author": "Arcblock <blocklet@arcblock.io> https://github.com/blocklet",
|
|
25
25
|
"license": "Elastic-2.0",
|
|
26
26
|
"dependencies": {
|
|
27
|
-
"@aigne/cli": "^1.
|
|
28
|
-
"@aigne/core": "^1.
|
|
29
|
-
"@aigne/publish-docs": "^0.
|
|
30
|
-
"@blocklet/payment-broker-client": "^1.22.
|
|
27
|
+
"@aigne/cli": "^1.54.1",
|
|
28
|
+
"@aigne/core": "^1.67.0",
|
|
29
|
+
"@aigne/publish-docs": "^0.13.0",
|
|
30
|
+
"@blocklet/payment-broker-client": "^1.22.10",
|
|
31
31
|
"@terrastruct/d2": "^0.1.33",
|
|
32
32
|
"chalk": "^5.5.0",
|
|
33
33
|
"debug": "^4.4.1",
|
package/utils/auth-utils.mjs
CHANGED
|
@@ -20,36 +20,44 @@ import {
|
|
|
20
20
|
DISCUSS_KIT_DID,
|
|
21
21
|
DISCUSS_KIT_STORE_URL,
|
|
22
22
|
DOC_OFFICIAL_ACCESS_TOKEN,
|
|
23
|
+
PAYMENT_KIT_DID,
|
|
23
24
|
} from "./constants/index.mjs";
|
|
25
|
+
import { requestWithAuthToken } from "./request.mjs";
|
|
26
|
+
import { withQuery } from "ufo";
|
|
24
27
|
|
|
25
28
|
const WELLKNOWN_SERVICE_PATH_PREFIX = "/.well-known/service";
|
|
26
29
|
|
|
30
|
+
const TIMEOUT_MINUTES = 5; // Just wait 5 min
|
|
31
|
+
const FETCH_INTERVAL = 3000; // 3 seconds
|
|
32
|
+
|
|
33
|
+
const RETRY_COUNT = (TIMEOUT_MINUTES * 60 * 1000) / FETCH_INTERVAL;
|
|
34
|
+
|
|
27
35
|
export function getDocSmithEnvFilePath() {
|
|
28
36
|
return join(homedir(), ".aigne", "doc-smith-connected.yaml");
|
|
29
37
|
}
|
|
30
38
|
|
|
31
39
|
/**
|
|
32
40
|
* Get access token from environment, config file, or prompt user for authorization
|
|
33
|
-
* @param {string}
|
|
41
|
+
* @param {string} baseUrl - The application URL
|
|
34
42
|
* @returns {Promise<string>} - The access token
|
|
35
43
|
*/
|
|
36
|
-
|
|
37
|
-
const { hostname } = new URL(
|
|
44
|
+
async function getCachedAccessToken(baseUrl) {
|
|
45
|
+
const { hostname: targetHostname } = new URL(baseUrl);
|
|
38
46
|
const DOC_SMITH_ENV_FILE = getDocSmithEnvFilePath();
|
|
39
47
|
|
|
40
48
|
let accessToken =
|
|
41
|
-
process.env.DOC_SMITH_PUBLISH_ACCESS_TOKEN || process.env
|
|
49
|
+
process.env.DOC_SMITH_PUBLISH_ACCESS_TOKEN || process.env[DOC_OFFICIAL_ACCESS_TOKEN];
|
|
42
50
|
|
|
43
51
|
// Check if access token exists in environment or config file
|
|
44
52
|
if (!accessToken) {
|
|
45
53
|
try {
|
|
46
54
|
if (existsSync(DOC_SMITH_ENV_FILE)) {
|
|
47
55
|
const data = await readFile(DOC_SMITH_ENV_FILE, "utf8");
|
|
48
|
-
if (data.includes(
|
|
56
|
+
if (data.includes(DOC_OFFICIAL_ACCESS_TOKEN)) {
|
|
49
57
|
// Handle empty or invalid YAML files
|
|
50
58
|
const envs = data.trim() ? parse(data) : null;
|
|
51
|
-
if (envs?.[
|
|
52
|
-
accessToken = envs[
|
|
59
|
+
if (envs?.[targetHostname]?.[DOC_OFFICIAL_ACCESS_TOKEN]) {
|
|
60
|
+
accessToken = envs[targetHostname][DOC_OFFICIAL_ACCESS_TOKEN];
|
|
53
61
|
}
|
|
54
62
|
}
|
|
55
63
|
}
|
|
@@ -58,14 +66,13 @@ export async function getAccessToken(appUrl, ltToken = "") {
|
|
|
58
66
|
}
|
|
59
67
|
}
|
|
60
68
|
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
return accessToken;
|
|
64
|
-
}
|
|
69
|
+
return accessToken;
|
|
70
|
+
}
|
|
65
71
|
|
|
66
|
-
|
|
72
|
+
export const getDiscussKitMountPoint = async (origin) => {
|
|
67
73
|
try {
|
|
68
|
-
await getComponentMountPoint(
|
|
74
|
+
const mountPoint = await getComponentMountPoint(origin, DISCUSS_KIT_DID);
|
|
75
|
+
return mountPoint;
|
|
69
76
|
} catch (error) {
|
|
70
77
|
const storeLink = chalk.cyan(DISCUSS_KIT_STORE_URL);
|
|
71
78
|
if (error instanceof InvalidBlockletError) {
|
|
@@ -83,7 +90,7 @@ export async function getAccessToken(appUrl, ltToken = "") {
|
|
|
83
90
|
);
|
|
84
91
|
} else {
|
|
85
92
|
throw new Error(
|
|
86
|
-
`❌ Could not connect to: ${chalk.cyan(
|
|
93
|
+
`❌ Could not connect to: ${chalk.cyan(origin)}\n\n` +
|
|
87
94
|
`${chalk.bold("Possible causes:")}\n` +
|
|
88
95
|
`• There may be a network issue.\n` +
|
|
89
96
|
`• The server may be temporarily unavailable.\n` +
|
|
@@ -92,9 +99,24 @@ export async function getAccessToken(appUrl, ltToken = "") {
|
|
|
92
99
|
);
|
|
93
100
|
}
|
|
94
101
|
}
|
|
102
|
+
};
|
|
103
|
+
|
|
104
|
+
/**
|
|
105
|
+
* Get access token from environment, config file, or prompt user for authorization
|
|
106
|
+
* @param {string} appUrl - The application URL
|
|
107
|
+
* @returns {Promise<string>} - The access token
|
|
108
|
+
*/
|
|
109
|
+
export async function getAccessToken(appUrl, ltToken = "", locale = "en") {
|
|
110
|
+
const { hostname: targetHostname, origin: targetOrigin } = new URL(appUrl);
|
|
111
|
+
|
|
112
|
+
let accessToken = await getCachedAccessToken(targetOrigin);
|
|
113
|
+
|
|
114
|
+
// If still no access token, prompt user to authorize
|
|
115
|
+
if (accessToken) {
|
|
116
|
+
return accessToken;
|
|
117
|
+
}
|
|
95
118
|
|
|
96
|
-
const
|
|
97
|
-
const connectUrl = joinURL(new URL(DISCUSS_KIT_URL).origin, WELLKNOWN_SERVICE_PATH_PREFIX);
|
|
119
|
+
const connectUrl = joinURL(targetOrigin, WELLKNOWN_SERVICE_PATH_PREFIX);
|
|
98
120
|
|
|
99
121
|
try {
|
|
100
122
|
const result = await createConnect({
|
|
@@ -104,49 +126,63 @@ export async function getAccessToken(appUrl, ltToken = "") {
|
|
|
104
126
|
closeOnSuccess: true,
|
|
105
127
|
appName: "AIGNE DocSmith",
|
|
106
128
|
appLogo: "https://docsmith.aigne.io/image-bin/uploads/9645caf64b4232699982c4d940b03b90.svg",
|
|
107
|
-
|
|
129
|
+
retry: RETRY_COUNT,
|
|
130
|
+
fetchInterval: FETCH_INTERVAL,
|
|
131
|
+
openPage: async (pageUrl) => {
|
|
108
132
|
const url = new URL(pageUrl);
|
|
109
|
-
|
|
133
|
+
const isOfficial = [CLOUD_SERVICE_URL_PROD, CLOUD_SERVICE_URL_STAGING].includes(url.origin);
|
|
134
|
+
if (!isOfficial) {
|
|
110
135
|
url.searchParams.set("required_roles", "owner,admin");
|
|
111
136
|
}
|
|
112
137
|
if (ltToken) {
|
|
113
138
|
url.searchParams.set("__lt", ltToken);
|
|
114
139
|
}
|
|
140
|
+
url.searchParams.set("locale", locale);
|
|
115
141
|
|
|
116
|
-
|
|
142
|
+
let connectUrl = url.toString();
|
|
143
|
+
open(connectUrl);
|
|
144
|
+
|
|
145
|
+
try {
|
|
146
|
+
const officialBaseUrl = process.env.DOC_SMITH_BASE_URL || CLOUD_SERVICE_URL_PROD;
|
|
147
|
+
const officialAccessToken = await getOfficialAccessToken(officialBaseUrl, false);
|
|
148
|
+
if (officialAccessToken) {
|
|
149
|
+
const mountPoint = await getComponentMountPoint(officialBaseUrl, PAYMENT_KIT_DID);
|
|
150
|
+
const data = await requestWithAuthToken(
|
|
151
|
+
withQuery(joinURL(officialBaseUrl, mountPoint, "/api/tool/short-url"), {
|
|
152
|
+
url: connectUrl,
|
|
153
|
+
}),
|
|
154
|
+
{},
|
|
155
|
+
officialAccessToken,
|
|
156
|
+
);
|
|
157
|
+
connectUrl = data.url;
|
|
158
|
+
}
|
|
159
|
+
} catch {
|
|
160
|
+
// Ignore error
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
console.log(
|
|
164
|
+
"🔗 Please open the following URL in your browser to authorize access: ",
|
|
165
|
+
chalk.cyan(connectUrl),
|
|
166
|
+
"\n",
|
|
167
|
+
);
|
|
117
168
|
},
|
|
118
169
|
});
|
|
119
170
|
|
|
120
171
|
accessToken = result.accessKeySecret;
|
|
121
172
|
process.env.DOC_SMITH_PUBLISH_ACCESS_TOKEN = accessToken;
|
|
173
|
+
process.env[DOC_OFFICIAL_ACCESS_TOKEN] = accessToken;
|
|
122
174
|
|
|
123
175
|
// Save the access token to config file
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
let existingConfig = {};
|
|
130
|
-
if (existsSync(DOC_SMITH_ENV_FILE)) {
|
|
131
|
-
const fileContent = await readFile(DOC_SMITH_ENV_FILE, "utf8");
|
|
132
|
-
const parsedConfig = fileContent.trim() ? parse(fileContent) : null;
|
|
133
|
-
existingConfig = parsedConfig || {};
|
|
134
|
-
}
|
|
135
|
-
|
|
136
|
-
await writeFile(
|
|
137
|
-
DOC_SMITH_ENV_FILE,
|
|
138
|
-
stringify({
|
|
139
|
-
...existingConfig,
|
|
140
|
-
[hostname]: {
|
|
141
|
-
DOC_DISCUSS_KIT_ACCESS_TOKEN: accessToken,
|
|
142
|
-
DOC_DISCUSS_KIT_URL: DISCUSS_KIT_URL,
|
|
143
|
-
},
|
|
144
|
-
}),
|
|
145
|
-
);
|
|
146
|
-
} catch (error) {
|
|
147
|
-
console.debug(error);
|
|
176
|
+
await saveTokenToConfigFile(targetHostname, {
|
|
177
|
+
[DOC_OFFICIAL_ACCESS_TOKEN]: accessToken,
|
|
178
|
+
});
|
|
179
|
+
} catch {
|
|
148
180
|
throw new Error(
|
|
149
|
-
"
|
|
181
|
+
`${chalk.yellow("⚠️ Failed to obtain access token. This may be due to network issues or authorization timeout.")}\n\n` +
|
|
182
|
+
`${chalk.bold("💡 Solution:")}\n` +
|
|
183
|
+
` • Step 1: Ensure your network can access the service URL: ${chalk.cyan(targetOrigin)}\n` +
|
|
184
|
+
` • Step 2: Run ${chalk.cyan("aigne doc publish")} again\n` +
|
|
185
|
+
` • Step 3: If prompted, select ${chalk.cyan("Resume previous website setup")} to continue from where you left off\n\n`,
|
|
150
186
|
);
|
|
151
187
|
}
|
|
152
188
|
|
|
@@ -158,34 +194,16 @@ export async function getAccessToken(appUrl, ltToken = "") {
|
|
|
158
194
|
* @param {string} baseUrl - The official service URL.
|
|
159
195
|
* @returns {Promise<string>} The access token.
|
|
160
196
|
*/
|
|
161
|
-
export async function getOfficialAccessToken(baseUrl, openPage = true) {
|
|
197
|
+
export async function getOfficialAccessToken(baseUrl, openPage = true, locale = "en") {
|
|
162
198
|
if (!baseUrl) {
|
|
163
199
|
throw new Error("The baseUrl parameter is required for getOfficialAccessToken.");
|
|
164
200
|
}
|
|
165
201
|
|
|
166
202
|
// Parse URL once and reuse
|
|
167
|
-
const
|
|
168
|
-
const { hostname, origin } = urlObj;
|
|
169
|
-
const DOC_SMITH_ENV_FILE = getDocSmithEnvFilePath();
|
|
203
|
+
const { hostname: targetHostname, origin: targetOrigin } = new URL(baseUrl);
|
|
170
204
|
|
|
171
205
|
// 1. Check environment variable
|
|
172
|
-
let accessToken =
|
|
173
|
-
|
|
174
|
-
// 2. Check config file if not in env
|
|
175
|
-
if (!accessToken) {
|
|
176
|
-
try {
|
|
177
|
-
if (existsSync(DOC_SMITH_ENV_FILE)) {
|
|
178
|
-
const data = await readFile(DOC_SMITH_ENV_FILE, "utf8");
|
|
179
|
-
// Handle empty or invalid YAML files
|
|
180
|
-
const envs = data.trim() ? parse(data) : null;
|
|
181
|
-
if (envs) {
|
|
182
|
-
accessToken = envs[hostname]?.[DOC_OFFICIAL_ACCESS_TOKEN];
|
|
183
|
-
}
|
|
184
|
-
}
|
|
185
|
-
} catch (_error) {
|
|
186
|
-
// Ignore errors
|
|
187
|
-
}
|
|
188
|
-
}
|
|
206
|
+
let accessToken = await getCachedAccessToken(targetOrigin);
|
|
189
207
|
|
|
190
208
|
// If token is found, return it
|
|
191
209
|
if (accessToken || !openPage) {
|
|
@@ -193,7 +211,7 @@ export async function getOfficialAccessToken(baseUrl, openPage = true) {
|
|
|
193
211
|
}
|
|
194
212
|
|
|
195
213
|
// Generate new access token
|
|
196
|
-
const connectUrl = joinURL(
|
|
214
|
+
const connectUrl = joinURL(targetOrigin, WELLKNOWN_SERVICE_PATH_PREFIX);
|
|
197
215
|
|
|
198
216
|
try {
|
|
199
217
|
const result = await createConnect({
|
|
@@ -201,15 +219,22 @@ export async function getOfficialAccessToken(baseUrl, openPage = true) {
|
|
|
201
219
|
connectAction: "gen-simple-access-key",
|
|
202
220
|
source: "AIGNE DocSmith connect to official service",
|
|
203
221
|
closeOnSuccess: true,
|
|
222
|
+
retry: RETRY_COUNT,
|
|
223
|
+
fetchInterval: FETCH_INTERVAL,
|
|
204
224
|
appName: "AIGNE DocSmith",
|
|
205
225
|
appLogo: "https://docsmith.aigne.io/image-bin/uploads/9645caf64b4232699982c4d940b03b90.svg",
|
|
206
226
|
openPage: (pageUrl) => {
|
|
227
|
+
const url = new URL(pageUrl);
|
|
228
|
+
if (locale) {
|
|
229
|
+
url.searchParams.set("locale", locale);
|
|
230
|
+
}
|
|
231
|
+
open(url.toString());
|
|
232
|
+
|
|
207
233
|
console.log(
|
|
208
234
|
"🔗 Please open the following URL in your browser to authorize access: ",
|
|
209
|
-
chalk.cyan(
|
|
235
|
+
chalk.cyan(url.toString()),
|
|
210
236
|
"\n",
|
|
211
237
|
);
|
|
212
|
-
open(pageUrl);
|
|
213
238
|
},
|
|
214
239
|
});
|
|
215
240
|
|
|
@@ -217,16 +242,15 @@ export async function getOfficialAccessToken(baseUrl, openPage = true) {
|
|
|
217
242
|
process.env[DOC_OFFICIAL_ACCESS_TOKEN] = accessToken;
|
|
218
243
|
|
|
219
244
|
// Save the access token to config file
|
|
220
|
-
await saveTokenToConfigFile(
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
accessToken,
|
|
225
|
-
);
|
|
226
|
-
} catch (error) {
|
|
227
|
-
console.debug(error);
|
|
245
|
+
await saveTokenToConfigFile(targetHostname, {
|
|
246
|
+
[DOC_OFFICIAL_ACCESS_TOKEN]: accessToken,
|
|
247
|
+
});
|
|
248
|
+
} catch {
|
|
228
249
|
throw new Error(
|
|
229
|
-
"
|
|
250
|
+
`${chalk.yellow("⚠️ Failed to obtain official access token. This may be due to network issues or authorization timeout.")}\n\n` +
|
|
251
|
+
`${chalk.bold("💡 Solution:")}\n` +
|
|
252
|
+
` • Step 1: Ensure your network can access the official service URL: ${chalk.cyan(targetOrigin)}\n` +
|
|
253
|
+
` • Step 2: Run ${chalk.cyan("aigne doc publish")} again\n\n`,
|
|
230
254
|
);
|
|
231
255
|
}
|
|
232
256
|
|
|
@@ -234,14 +258,15 @@ export async function getOfficialAccessToken(baseUrl, openPage = true) {
|
|
|
234
258
|
}
|
|
235
259
|
|
|
236
260
|
/**
|
|
237
|
-
* Saves the access token to the configuration file.
|
|
261
|
+
* Saves the access token and related fields to the configuration file.
|
|
238
262
|
* @param {string} configFile - The path to the config file.
|
|
239
263
|
* @param {string} hostname - The hostname key.
|
|
240
|
-
* @param {
|
|
241
|
-
* @param {string} tokenValue - The token value.
|
|
264
|
+
* @param {Object} fields - Fields to save (e.g., { DOC_DISCUSS_KIT_ACCESS_TOKEN: "..." }).
|
|
242
265
|
*/
|
|
243
|
-
async function saveTokenToConfigFile(
|
|
266
|
+
async function saveTokenToConfigFile(hostname, fields) {
|
|
244
267
|
try {
|
|
268
|
+
const configFile = getDocSmithEnvFilePath();
|
|
269
|
+
|
|
245
270
|
const aigneDir = join(homedir(), ".aigne");
|
|
246
271
|
if (!existsSync(aigneDir)) {
|
|
247
272
|
mkdirSync(aigneDir, { recursive: true });
|
|
@@ -250,7 +275,6 @@ async function saveTokenToConfigFile(configFile, hostname, tokenKey, tokenValue)
|
|
|
250
275
|
let existingConfig = {};
|
|
251
276
|
if (existsSync(configFile)) {
|
|
252
277
|
const fileContent = await readFile(configFile, "utf8");
|
|
253
|
-
// Handle empty or invalid YAML files
|
|
254
278
|
const parsedConfig = fileContent.trim() ? parse(fileContent) : null;
|
|
255
279
|
existingConfig = parsedConfig || {};
|
|
256
280
|
}
|
|
@@ -259,10 +283,7 @@ async function saveTokenToConfigFile(configFile, hostname, tokenKey, tokenValue)
|
|
|
259
283
|
configFile,
|
|
260
284
|
stringify({
|
|
261
285
|
...existingConfig,
|
|
262
|
-
[hostname]:
|
|
263
|
-
...existingConfig[hostname],
|
|
264
|
-
[tokenKey]: tokenValue,
|
|
265
|
-
},
|
|
286
|
+
[hostname]: fields,
|
|
266
287
|
}),
|
|
267
288
|
);
|
|
268
289
|
} catch (error) {
|
package/utils/deploy.mjs
CHANGED
|
@@ -14,11 +14,11 @@ const SUCCESS_MESSAGE = {
|
|
|
14
14
|
/**
|
|
15
15
|
* Deploys a new Discuss Kit Website and returns the installation URL.
|
|
16
16
|
* @param {string} id - The cached checkout ID (optional).
|
|
17
|
-
* @param {string}
|
|
17
|
+
* @param {string} locale - preferred locale
|
|
18
18
|
* @returns {Promise<Object>} The deployment result with URLs.
|
|
19
19
|
*/
|
|
20
|
-
export async function deploy(id,
|
|
21
|
-
const authToken = await getOfficialAccessToken(BASE_URL);
|
|
20
|
+
export async function deploy(id, locale) {
|
|
21
|
+
const authToken = await getOfficialAccessToken(BASE_URL, true, locale);
|
|
22
22
|
|
|
23
23
|
if (!authToken) {
|
|
24
24
|
throw new Error("Could not get an official access token.");
|
|
@@ -30,7 +30,6 @@ export async function deploy(id, cachedUrl) {
|
|
|
30
30
|
|
|
31
31
|
const result = await client.deploy({
|
|
32
32
|
cachedCheckoutId: id,
|
|
33
|
-
cachedPaymentUrl: cachedUrl,
|
|
34
33
|
needShortUrl: true,
|
|
35
34
|
pageInfo: { successMessage: SUCCESS_MESSAGE },
|
|
36
35
|
hooks: {
|
|
@@ -72,7 +71,7 @@ export async function deploy(id, cachedUrl) {
|
|
|
72
71
|
},
|
|
73
72
|
});
|
|
74
73
|
|
|
75
|
-
const { appUrl, homeUrl, subscriptionUrl, dashboardUrl, vendors, sessionId } = result;
|
|
74
|
+
const { appUrl, homeUrl, subscriptionUrl, dashboardUrl, vendors, sessionId, data } = result;
|
|
76
75
|
const token = vendors?.[0]?.token;
|
|
77
76
|
|
|
78
77
|
return {
|
|
@@ -82,5 +81,6 @@ export async function deploy(id, cachedUrl) {
|
|
|
82
81
|
subscriptionUrl,
|
|
83
82
|
token,
|
|
84
83
|
sessionId,
|
|
84
|
+
data,
|
|
85
85
|
};
|
|
86
86
|
}
|
package/utils/request.mjs
CHANGED
|
@@ -1,4 +1,7 @@
|
|
|
1
1
|
export async function requestWithAuthToken(url, options, authToken) {
|
|
2
|
+
if (!authToken) {
|
|
3
|
+
console.error("No authentication token provided");
|
|
4
|
+
}
|
|
2
5
|
const response = await fetch(url, {
|
|
3
6
|
...options,
|
|
4
7
|
headers: { ...options.headers, Authorization: `Bearer ${authToken}` },
|