@aigne/doc-smith 0.9.2-beta → 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 CHANGED
@@ -1,5 +1,14 @@
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
+
10
+ ## [0.9.2](https://github.com/AIGNE-io/aigne-doc-smith/compare/v0.9.2-beta...v0.9.2) (2025-11-12)
11
+
3
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
13
 
5
14
 
@@ -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 { getAccessToken, getOfficialAccessToken } from "../../utils/auth-utils.mjs";
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
- if (choice === "new-instance-continue") {
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 (choice === "new-instance-continue") {
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
- } = (await deploy(id, paymentLink)) || {};
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
- console.log(`\nPublishing your documentation to ${chalk.cyan(appUrl)}\n`);
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(appUrl, token);
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
- appUrl,
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", 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.2-beta",
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.53.1-beta.4",
28
- "@aigne/core": "^1.65.1-beta.3",
29
- "@aigne/publish-docs": "^0.12.1",
30
- "@blocklet/payment-broker-client": "^1.22.8",
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",
@@ -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} appUrl - The application URL
41
+ * @param {string} baseUrl - The application URL
34
42
  * @returns {Promise<string>} - The access token
35
43
  */
36
- export async function getAccessToken(appUrl, ltToken = "") {
37
- const { hostname } = new URL(appUrl);
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.DOC_DISCUSS_KIT_ACCESS_TOKEN;
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("DOC_DISCUSS_KIT_ACCESS_TOKEN")) {
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?.[hostname]?.DOC_DISCUSS_KIT_ACCESS_TOKEN) {
52
- accessToken = envs[hostname].DOC_DISCUSS_KIT_ACCESS_TOKEN;
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
- // If still no access token, prompt user to authorize
62
- if (accessToken) {
63
- return accessToken;
64
- }
69
+ return accessToken;
70
+ }
65
71
 
66
- // Check if Discuss Kit is running at the provided URL
72
+ export const getDiscussKitMountPoint = async (origin) => {
67
73
  try {
68
- await getComponentMountPoint(appUrl, DISCUSS_KIT_DID);
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(appUrl)}\n\n` +
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 DISCUSS_KIT_URL = appUrl;
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
- openPage: (pageUrl) => {
129
+ retry: RETRY_COUNT,
130
+ fetchInterval: FETCH_INTERVAL,
131
+ openPage: async (pageUrl) => {
108
132
  const url = new URL(pageUrl);
109
- if ([CLOUD_SERVICE_URL_PROD, CLOUD_SERVICE_URL_STAGING].includes(url.origin) === false) {
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
- open(url.toString());
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
- const aigneDir = join(homedir(), ".aigne");
125
- if (!existsSync(aigneDir)) {
126
- mkdirSync(aigneDir, { recursive: true });
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
- "Could not get an access token. Please check your network connection and try again.",
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 urlObj = new URL(baseUrl);
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 = process.env[DOC_OFFICIAL_ACCESS_TOKEN];
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(origin, WELLKNOWN_SERVICE_PATH_PREFIX);
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(pageUrl),
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
- DOC_SMITH_ENV_FILE,
222
- hostname,
223
- DOC_OFFICIAL_ACCESS_TOKEN,
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
- "Could not get an official access token. Please check your network connection and try again.",
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 {string} tokenKey - The token key name.
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(configFile, hostname, tokenKey, tokenValue) {
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} cachedUrl - The cached payment URL (optional).
17
+ * @param {string} locale - preferred locale
18
18
  * @returns {Promise<Object>} The deployment result with URLs.
19
19
  */
20
- export async function deploy(id, cachedUrl) {
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}` },