@dune2/cli 0.1.25 → 0.1.26

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.
@@ -0,0 +1,302 @@
1
+ // src/shared/index.ts
2
+ import cac from "cac";
3
+ import debug from "debug";
4
+ import path from "path";
5
+ import fs from "fs-extra";
6
+ var cli = cac("dune");
7
+ var createLogger = (name) => {
8
+ const info = debug(`${cli.name}:${name}`);
9
+ return {
10
+ ...info,
11
+ info,
12
+ error: info.extend("error")
13
+ };
14
+ };
15
+ debug.enable(`${cli.name}:*`);
16
+ var homeConfigDir = (() => {
17
+ const isWin = process.platform === "win32";
18
+ const USER_HOME_DIR = isWin ? process.env.USERPROFILE : process.env.HOME;
19
+ const configDir = path.join(USER_HOME_DIR, ".config", cli.name);
20
+ if (!fs.existsSync(configDir)) {
21
+ fs.mkdirSync(configDir);
22
+ }
23
+ return homeConfigDir2;
24
+ function homeConfigDir2(p) {
25
+ if (!p) {
26
+ return configDir;
27
+ }
28
+ return path.join(configDir, p);
29
+ }
30
+ })();
31
+
32
+ // src/shared/resolveSheetId.ts
33
+ import { match } from "path-to-regexp";
34
+ function resolveSheetId(str) {
35
+ var _a;
36
+ if (!str || !(str == null ? void 0 : str.startsWith("http"))) {
37
+ return str;
38
+ }
39
+ const url = new URL(str);
40
+ const matched = match("/spreadsheets/d/:id*", {
41
+ decode: decodeURIComponent
42
+ })(url.pathname);
43
+ return matched ? (_a = matched.params.id) == null ? void 0 : _a[0] : str;
44
+ }
45
+
46
+ // src/shared/config.ts
47
+ import JoyCon from "joycon";
48
+ import path2 from "path";
49
+ var joycon = new JoyCon();
50
+ function defineConfig(c) {
51
+ return c;
52
+ }
53
+ var configName = "dune.config.js";
54
+ async function getConfig() {
55
+ var _a;
56
+ const res = await joycon.load([configName]);
57
+ const defaultI18nConfig = {
58
+ i18nDir: "./src/i18n",
59
+ i18nFileName: "{locale}.i18n.json",
60
+ position: { key: "B", zh: "C", en: "D", in: "E" },
61
+ parseStartIndex: 2
62
+ };
63
+ let config = res.data ?? {};
64
+ config.cwd ??= process.cwd();
65
+ config.cacheDir ??= path2.join(config.cwd, "node_modules/.cache/dune-cli");
66
+ if (!config.i18n || !((_a = config.i18n) == null ? void 0 : _a.length)) {
67
+ config.i18n = [defaultI18nConfig];
68
+ }
69
+ config.i18n = config.i18n.map((item) => {
70
+ item = Object.assign({}, defaultI18nConfig, item);
71
+ item.cwd ??= config.cwd;
72
+ item.locales = Object.keys(item.position).filter((item2) => item2 !== "key");
73
+ item.sheetId = resolveSheetId(item.sheetId);
74
+ item.keySorter = (a, b) => {
75
+ return a.localeCompare(b);
76
+ };
77
+ item.enabled ??= true;
78
+ return item;
79
+ });
80
+ config.api ??= [];
81
+ config.api = config.api.map(apiConfigNormalizer);
82
+ return config;
83
+ }
84
+ function apiConfigNormalizer(item) {
85
+ item.output ??= "./src/apis";
86
+ item.requestFnImportPath ??= `import requestFn from '@/utils/request';`;
87
+ item.RequestBuilderImportPath ??= `import { RequestBuilder } from '@dune2/tools';`;
88
+ item.enableTs ??= true;
89
+ item.enabled ??= true;
90
+ item.format ??= true;
91
+ item.responseSchemaTransformer ??= (schema) => {
92
+ var _a;
93
+ return ((_a = schema.properties) == null ? void 0 : _a.data) ?? schema;
94
+ };
95
+ return item;
96
+ }
97
+
98
+ // src/shared/letters.ts
99
+ function letterToNumber(letters) {
100
+ if (typeof letters === "number" || !Number.isNaN(+letters)) {
101
+ return +letters;
102
+ }
103
+ let n = 0;
104
+ letters = letters.toUpperCase();
105
+ for (let p = 0; p < letters.length; p++) {
106
+ n = letters[p].charCodeAt(0) - 64 + n * 26;
107
+ }
108
+ return Math.max(0, n - 1);
109
+ }
110
+ var alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
111
+ var base = alphabet.length;
112
+ function numberToLetter(n) {
113
+ const digits = [];
114
+ do {
115
+ const v = n % base;
116
+ digits.push(v);
117
+ n = Math.floor(n / base);
118
+ } while (n-- > 0);
119
+ const chars = [];
120
+ while (digits.length) {
121
+ chars.push(alphabet[digits.pop()]);
122
+ }
123
+ return chars.join("");
124
+ }
125
+
126
+ // src/shared/google/sheet.ts
127
+ import { google as google2 } from "googleapis";
128
+
129
+ // src/shared/google/auth.ts
130
+ import fs2 from "fs-extra";
131
+ import { google } from "googleapis";
132
+
133
+ // src/shared/google/shared.ts
134
+ import connect from "connect";
135
+ import open from "open";
136
+ import { URL as URL2 } from "url";
137
+ var log = createLogger("google:shared");
138
+ function openBrowser(url) {
139
+ log.info(`\u5982\u672A\u81EA\u52A8\u6253\u5F00\u6D4F\u89C8\u5668\uFF0C\u53EF\u8BBF\u95EE\u4EE5\u4E0B\u5730\u5740\uFF1A${url}`);
140
+ open(url, { app: { name: open.apps.chrome } });
141
+ }
142
+ function openAndWaitReturnQuery(toOpenUrl, port, queryKey) {
143
+ return new Promise((resolve) => {
144
+ openBrowser(toOpenUrl);
145
+ const app = connect();
146
+ app.use((req, res, next) => {
147
+ const parsedUrl = new URL2(req.url, `http://localhost:${port}`);
148
+ const target = parsedUrl.searchParams.get(queryKey);
149
+ if (target) {
150
+ res.writeHead(200, {
151
+ "content-type": "text/html;charset=utf8"
152
+ });
153
+ res.end(
154
+ `<div>\u5F53\u524D\u7A97\u53E3\u53EF\u76F4\u63A5\u5173\u95ED</div>
155
+ <script>
156
+ window.open("", "_self", "");
157
+ window.close();
158
+ <\/script>`
159
+ );
160
+ server.close();
161
+ server.unref();
162
+ resolve(target);
163
+ }
164
+ next();
165
+ });
166
+ const server = app.listen(port);
167
+ });
168
+ }
169
+
170
+ // src/shared/google/auth.ts
171
+ var log2 = createLogger("google:auth");
172
+ var GoogleAuth = class {
173
+ constructor(options) {
174
+ this.options = options;
175
+ this.tokens = null;
176
+ this.tokensCachePath = homeConfigDir("chromeAuthToken.json");
177
+ this.oauth2Client = new google.auth.OAuth2(
178
+ this.options.client_id,
179
+ this.options.client_secret,
180
+ "http://localhost:12345"
181
+ );
182
+ this.initCredentialsPromise = null;
183
+ this.options.scope = this.options.scope ?? ["spreadsheets"];
184
+ const scopePrefix = `https://www.googleapis.com/auth/`;
185
+ this.scope = this.options.scope.map((item) => {
186
+ if (item.startsWith(scopePrefix)) {
187
+ return item;
188
+ }
189
+ return `${scopePrefix}${item}`;
190
+ });
191
+ try {
192
+ this.tokens = fs2.readJsonSync(this.tokensCachePath);
193
+ } catch (e) {
194
+ log2.info("\u672A\u83B7\u53D6\u5230\u7F13\u5B58\u7684token");
195
+ this.tokens = null;
196
+ }
197
+ }
198
+ async saveTokens(tokens) {
199
+ this.tokens = tokens;
200
+ await fs2.writeJSON(this.tokensCachePath, tokens);
201
+ log2.info("\u4FDD\u5B58token\u6210\u529F");
202
+ }
203
+ async getCode() {
204
+ log2.info("\u5C06\u6253\u5F00chrome\u6D4F\u89C8\u5668\u8FDB\u884C\u6388\u6743");
205
+ const authUrl = this.oauth2Client.generateAuthUrl({
206
+ access_type: "offline",
207
+ scope: this.scope
208
+ });
209
+ return await openAndWaitReturnQuery(authUrl, 12345, "code");
210
+ }
211
+ async initCredentialsImpl() {
212
+ if (!this.tokens) {
213
+ const code = await this.getCode();
214
+ const { tokens } = await this.oauth2Client.getToken(code);
215
+ await this.saveTokens(tokens);
216
+ }
217
+ this.oauth2Client.setCredentials(this.tokens);
218
+ }
219
+ async initCredentials() {
220
+ if (!this.initCredentialsPromise) {
221
+ this.initCredentialsPromise = this.initCredentialsImpl();
222
+ }
223
+ return await this.initCredentialsPromise;
224
+ }
225
+ };
226
+ var clientSecret = {
227
+ client_id: "467670582023-3sr5gnfsuebgtde1mk3vp78om43no4kv.apps.googleusercontent.com",
228
+ project_id: "dune-cli-376503",
229
+ auth_uri: "https://accounts.google.com/o/oauth2/auth",
230
+ token_uri: "https://oauth2.googleapis.com/token",
231
+ auth_provider_x509_cert_url: "https://www.googleapis.com/oauth2/v1/certs",
232
+ client_secret: "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",
233
+ redirect_uris: ["http://localhost"],
234
+ javascript_origins: ["http://localhost"]
235
+ };
236
+ var googleAuth = new GoogleAuth(clientSecret);
237
+
238
+ // src/shared/google/sheet.ts
239
+ var log3 = createLogger("google:sheets");
240
+ var GoogleSheet = class {
241
+ constructor() {
242
+ this.initPromise = null;
243
+ this.get = async (options) => {
244
+ await this.init();
245
+ return this.sheets.spreadsheets.values.get(options);
246
+ };
247
+ }
248
+ async initImpl() {
249
+ if (!this.sheets) {
250
+ await googleAuth.initCredentials();
251
+ this.sheets = google2.sheets({
252
+ version: "v4",
253
+ auth: googleAuth.oauth2Client
254
+ });
255
+ }
256
+ }
257
+ async init() {
258
+ if (!this.initPromise) {
259
+ this.initPromise = this.initImpl();
260
+ }
261
+ await this.initPromise;
262
+ }
263
+ async update(spreadsheetId, range, colIndex, rowIndex, values) {
264
+ await this.init();
265
+ const colLetter = numberToLetter(colIndex);
266
+ const sheetNeedRange = `${range}!${colLetter}${rowIndex}`;
267
+ const res = await this.sheets.spreadsheets.values.update({
268
+ spreadsheetId,
269
+ range: sheetNeedRange,
270
+ valueInputOption: "USER_ENTERED",
271
+ requestBody: { values }
272
+ });
273
+ if (res.status === 200) {
274
+ log3.info(`\u66F4\u65B0 ${sheetNeedRange} \u7684\u503C\u6210\u529F`);
275
+ } else {
276
+ log3.error("some thing wrong", res);
277
+ }
278
+ return res;
279
+ }
280
+ async updateCell(spreadsheetId, range, colIndex, rowIndex, values) {
281
+ return this.update(spreadsheetId, range, colIndex, rowIndex, [[values]]);
282
+ }
283
+ async updateColumn(spreadsheetId, range, colIndex, rowIndex, values) {
284
+ return this.update(spreadsheetId, range, colIndex, rowIndex, [
285
+ ...values.map((v) => [v])
286
+ ]);
287
+ }
288
+ };
289
+ var googleSheet = new GoogleSheet();
290
+
291
+ export {
292
+ cli,
293
+ createLogger,
294
+ resolveSheetId,
295
+ defineConfig,
296
+ configName,
297
+ getConfig,
298
+ letterToNumber,
299
+ numberToLetter,
300
+ googleSheet
301
+ };
302
+ //# sourceMappingURL=chunk-IPRK5TYY.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/shared/index.ts","../src/shared/resolveSheetId.ts","../src/shared/config.ts","../src/shared/letters.ts","../src/shared/google/sheet.ts","../src/shared/google/auth.ts","../src/shared/google/shared.ts"],"sourcesContent":["import cac from \"cac\";\nimport debug from \"debug\";\nimport path from \"path\";\nimport fs from \"fs-extra\";\n\nexport const cli = cac(\"dune\");\n\nexport const createLogger = (name: string) => {\n const info = debug(`${cli.name}:${name}`);\n return {\n ...info,\n info,\n error: info.extend(\"error\"),\n };\n};\n\ndebug.enable(`${cli.name}:*`);\n\n/**\n * same with chacheDir\n * homeDir();\n * //=> '~/name'\n *\n * homeDir('bar.js')\n * //=> '~/name/bar.js'\n */\n// eslint-disable-next-line @typescript-eslint/explicit-function-return-type\nexport const homeConfigDir = (() => {\n const isWin = process.platform === \"win32\";\n const USER_HOME_DIR = isWin ? process.env.USERPROFILE : process.env.HOME;\n const configDir = path.join(USER_HOME_DIR!, \".config\", cli.name);\n\n if (!fs.existsSync(configDir)) {\n fs.mkdirSync(configDir);\n }\n return homeConfigDir;\n\n function homeConfigDir(p?: string): string {\n if (!p) {\n return configDir;\n }\n return path.join(configDir, p);\n }\n})();\n","/**\n * input:\n * \"https://docs.google.com/spreadsheets/d/1C9-Dol3oO20W9_FhiVlxNsDhOaaejJIgAZYRkonGmfk/edit#gid=1740568548\"\n * output:\n * \"1C9-Dol3oO20W9_FhiVlxNsDhOaaejJIgAZYRkonGmfk\"\n * --\n * input: \"1C9-Dol3oO20W9_FhiVlxNsDhOaaejJIgAZYRkonGmfk\"\n * output: \"1C9-Dol3oO20W9_FhiVlxNsDhOaaejJIgAZYRkonGmfk\"\n */\nimport { match } from \"path-to-regexp\";\n\nexport function resolveSheetId(str?: string) {\n if (!str || !str?.startsWith(\"http\")) {\n return str;\n }\n const url = new URL(str);\n const matched = match<{ id: string[] }>(\"/spreadsheets/d/:id*\", {\n decode: decodeURIComponent,\n })(url.pathname);\n return matched ? matched.params.id?.[0] : str;\n}\n","import JoyCon from \"joycon\";\nimport { resolveSheetId } from \"./resolveSheetId\";\nimport { OpenAPIV3 } from \"openapi-types\";\nimport path from \"path\";\n\nconst joycon = new JoyCon();\n\nexport interface I18nConfig {\n // 语言文件存放目录,默认为项目根目录的 \"./src/i18n\"\n i18nDir?: string;\n // 语言文件名,默认为 \"{locale}.i18n.json\",其中 {locale} 会被替换为 locales 中的语言\n i18nFileName?: string;\n // 默认语言,默认为 \"zh\",影响到提出出来的文案的默认值\n defaultLocale?: string;\n /**\n * 可以是 id 或者 url,如果是 url 则会自动解析出 id\n * id: 1C9-Dol3oO20W9_FhiVlxNsDhOaaejJIgAZYRkonGmfk\n * url: https://docs.google.com/spreadsheets/d/1C9-Dol3oO20W9_FhiVlxNsDhOaaejJIgAZYRkonGmfk/edit#gid=1740568548\n */\n sheetId?: string;\n // google sheets 工作表名称\n sheetRange?: string;\n /**\n * 对应 语言、i18nKey 所在的列标识符 如(A,B,C...)\n * 传入时将忽略默认的配置\n * @default {key: \"B\", zh: \"C\", en: \"D\", in: \"E\",}\n */\n position?: {\n key: string;\n [key: string]: string;\n };\n\n /**\n * 从 Google Sheets 哪一行开始解析\n * 默认从第2行开始,模板文件第一行是表头\n * @default 2\n */\n parseStartIndex?: number;\n\n /**\n * 默认是 命令运行的目录,一般是项目根目录\n * @internal\n */\n cwd?: string;\n /**\n * 支持的语言列表,从 position 中解析出来\n * @internal\n */\n locales?: string[];\n\n /**\n * 翻译key的排序\n * @internal\n */\n keySorter?: (a: string, b: string) => number;\n /**\n * 是否启用\n * @internal\n */\n enabled?: boolean;\n\n /**\n * 包括的文件\n * glob 语法\n */\n include?: string[];\n}\n\nexport interface ApiConfig {\n /**\n * swagger JSON 的路径 可以是 本地 可以是远程\n */\n swaggerJSONPath: string;\n /**\n * 用在生成代码里快捷连接跳转到 swagger ui\n * 必须携带 urls.primaryName 参数\n * @example http://192.168.104.10:31082/swagger/?urls.primaryName=%E5%90%8E%E5%8F%B0%E7%AE%A1%E7%90%86%E7%9B%B8%E5%85%B3API\n */\n swaggerUiUrl?: string;\n /**\n * 输出的文件夹路径\n * @default \"./src/apis\"\n */\n output?: string;\n /**\n * 配置`requestFn` 方法引入的路径,生成的代码里会用到,生成代码如下\n * 导入的变量必须是命名为`requestFn`\n * ```ts\n * // 需要命名为 requestFn\n * import requestFn from '@/utils/request'\n * import { foo as requestFn } from '@/utils/request'\n * ```\n * @default `import requestFn from '@/utils/request'`\n */\n requestFnImportPath?: string;\n /**\n * 配置`queryClient` 路径,导入的变量必须是命名为`queryClient`\n * @example `import queryClient from '@/utils/request'`\n * @example `import { queryClient } from '@/utils/request'`\n * @example `import { xxClient as queryClient } from '@/utils/request'`\n */\n queryClientImportPath?: string;\n\n /**\n * 配置`RequestBuilder` 路径,导入的变量必须是命名为`RequestBuilder`\n * @example `import RequestBuilder from '@/utils/RequestBuilder'`\n * @default `import { RequestBuilder } from '@dune2/tools'`\n */\n RequestBuilderImportPath?: string;\n\n /**\n * 是否启用ts,`true`会生成`.ts`文件,`false`会生成`.js`文件\n * @default true\n */\n enableTs?: boolean;\n\n /**\n * 响应的scheme转换,默认获取获取 data 字段,取不到回退到 scheme\n * @default (schema) => schema.properties?.data ?? schema\n */\n responseSchemaTransformer?: (schema: OpenAPIV3.SchemaObject) => any;\n /**\n * 是否启用\n * @internal\n */\n enabled?: boolean;\n\n /**\n * 生成代码完毕后是否自动格式化,默认格式化\n * 需要安装 prettier\n * @default true\n */\n format?: boolean;\n}\n\nexport interface Config {\n i18n?: I18nConfig[];\n api?: ApiConfig[];\n /**\n * 默认是 命令运行的目录,一般是项目根目录\n * @internal\n */\n cwd?: string;\n\n /**\n * 默认是 node_modules/.cache/dune-cli\n * @internal\n */\n cacheDir?: string;\n}\nexport function defineConfig<T = Config>(c: T) {\n return c;\n}\n\nexport const configName = \"dune.config.js\";\n\nexport async function getConfig(): Promise<Config> {\n const res = await joycon.load([configName]);\n\n const defaultI18nConfig: I18nConfig = {\n i18nDir: \"./src/i18n\",\n i18nFileName: \"{locale}.i18n.json\",\n position: { key: \"B\", zh: \"C\", en: \"D\", in: \"E\" },\n parseStartIndex: 2,\n };\n\n let config = (res.data ?? {}) as Config;\n config.cwd ??= process.cwd();\n config.cacheDir ??= path.join(config.cwd, \"node_modules/.cache/dune-cli\");\n\n //#region i18n 配置标准化\n if (!config.i18n || !config.i18n?.length) {\n config.i18n = [defaultI18nConfig];\n }\n\n // 格式化 i18n 配置\n config.i18n = config.i18n.map((item) => {\n item = Object.assign({}, defaultI18nConfig, item);\n item.cwd ??= config.cwd;\n item.locales = Object.keys(item.position!).filter((item) => item !== \"key\");\n item.sheetId = resolveSheetId(item.sheetId);\n item.keySorter = (a, b) => {\n return a.localeCompare(b);\n };\n item.enabled ??= true;\n return item;\n });\n //#endregion\n\n //#region api 配置标准化\n config.api ??= [];\n config.api = config.api.map(apiConfigNormalizer);\n //#endregion\n\n return config;\n}\n\nexport function apiConfigNormalizer(item: ApiConfig) {\n item.output ??= \"./src/apis\";\n item.requestFnImportPath ??= `import requestFn from '@/utils/request';`;\n item.RequestBuilderImportPath ??= `import { RequestBuilder } from '@dune2/tools';`;\n item.enableTs ??= true;\n item.enabled ??= true;\n item.format ??= true;\n item.responseSchemaTransformer ??= (schema) =>\n schema.properties?.data ?? schema;\n return item;\n}\n","/**\n *\n * - input : A\n * output : 0\n * - input : Z\n * output : 25\n * - input : AA\n * output : 26\n * - input : a\n * output : 0\n */\nexport function letterToNumber(letters: string | number) {\n if (typeof letters === \"number\" || !Number.isNaN(+letters)) {\n return +letters;\n }\n\n let n = 0;\n letters = letters.toUpperCase();\n for (let p = 0; p < letters.length; p++) {\n n = letters[p].charCodeAt(0) - 64 + n * 26;\n }\n\n return Math.max(0, n - 1);\n}\n\n/**\n * fork from https://github.com/matthewmueller/number-to-letter\n */\nconst alphabet = \"ABCDEFGHIJKLMNOPQRSTUVWXYZ\";\nconst base = alphabet.length;\n/**\n * numberToLetter(0) // A\n * numberToLetter(25) // Z\n * numberToLetter(26) // AA\n * numberToLetter(51) // AZ\n * numberToLetter(52) // BA\n * numberToLetter(676) // ZA\n * numberToLetter(701) // ZZ\n * numberToLetter(702) // AAA\n */\nexport function numberToLetter(n: number) {\n const digits: number[] = [];\n\n do {\n const v = n % base;\n digits.push(v);\n n = Math.floor(n / base);\n } while (n-- > 0);\n\n const chars: string[] = [];\n while (digits.length) {\n chars.push(alphabet[digits.pop()!]);\n }\n\n return chars.join(\"\");\n}\n","import { GaxiosResponse } from \"gaxios\";\nimport type { sheets_v4 } from \"googleapis\";\nimport { google } from \"googleapis\";\nimport { createLogger } from \"../index\";\nimport { numberToLetter } from \"../letters\";\nimport { googleAuth } from \"./auth\";\n\nconst log = createLogger(\"google:sheets\");\n\nclass GoogleSheet {\n private sheets: sheets_v4.Sheets;\n\n private initPromise: Promise<void> | null = null;\n private async initImpl() {\n if (!this.sheets) {\n await googleAuth.initCredentials();\n this.sheets = google.sheets({\n version: \"v4\",\n auth: googleAuth.oauth2Client,\n });\n }\n }\n /**\n * 调用sheets其他方法的时候需要先初始化\n */\n async init() {\n if (!this.initPromise) {\n this.initPromise = this.initImpl();\n }\n await this.initPromise;\n }\n\n get = async (options: sheets_v4.Params$Resource$Spreadsheets$Values$Get) => {\n await this.init();\n return this.sheets.spreadsheets.values.get(options);\n };\n\n private async update(\n spreadsheetId: string,\n range: string,\n colIndex: number,\n rowIndex: number,\n values: string[][]\n ): Promise<GaxiosResponse<sheets_v4.Schema$UpdateValuesResponse>> {\n await this.init();\n\n const colLetter = numberToLetter(colIndex);\n const sheetNeedRange = `${range}!${colLetter}${rowIndex}`;\n\n const res = await this.sheets.spreadsheets.values.update({\n spreadsheetId,\n range: sheetNeedRange,\n valueInputOption: \"USER_ENTERED\",\n requestBody: { values },\n });\n\n if (res.status === 200) {\n log.info(`更新 ${sheetNeedRange} 的值成功`);\n } else {\n log.error(\"some thing wrong\", res);\n }\n return res;\n }\n\n /**\n * 更新某一个单元格\n */\n async updateCell(\n spreadsheetId: string,\n range: string,\n colIndex: number,\n rowIndex: number,\n values: string\n ) {\n return this.update(spreadsheetId, range, colIndex, rowIndex, [[values]]);\n }\n\n /**\n * 更新某一列\n */\n async updateColumn(\n spreadsheetId: string,\n range: string,\n colIndex: number,\n rowIndex: number,\n values: string[]\n ) {\n return this.update(spreadsheetId, range, colIndex, rowIndex, [\n ...values.map((v) => [v]),\n ]);\n }\n}\n\nexport const googleSheet = new GoogleSheet();\n","import fs from \"fs-extra\";\nimport { OAuth2Client } from \"google-auth-library\";\nimport { google } from \"googleapis\";\nimport { homeConfigDir, createLogger } from \"../index\";\nimport { openAndWaitReturnQuery } from \"./shared\";\n\ninterface AuthOptions {\n client_id: string;\n client_secret: string;\n /**\n * @default ['spreadsheets']\n */\n scope?: string[];\n}\n\nconst log = createLogger(\"google:auth\");\n\nclass GoogleAuth {\n private tokens: any = null;\n\n private tokensCachePath = homeConfigDir(\"chromeAuthToken.json\");\n\n private readonly scope: string[];\n\n oauth2Client: OAuth2Client = new google.auth.OAuth2(\n this.options.client_id,\n this.options.client_secret,\n \"http://localhost:12345\"\n );\n\n constructor(private options: AuthOptions) {\n this.options.scope = this.options.scope ?? [\"spreadsheets\"];\n const scopePrefix = `https://www.googleapis.com/auth/`;\n this.scope = this.options.scope.map((item) => {\n if (item.startsWith(scopePrefix)) {\n return item;\n }\n return `${scopePrefix}${item}`;\n });\n\n try {\n this.tokens = fs.readJsonSync(this.tokensCachePath);\n } catch (e) {\n log.info(\"未获取到缓存的token\");\n this.tokens = null;\n }\n }\n\n private async saveTokens(tokens: any): Promise<void> {\n this.tokens = tokens;\n await fs.writeJSON(this.tokensCachePath, tokens);\n log.info(\"保存token成功\");\n }\n\n async getCode(): Promise<string> {\n log.info(\"将打开chrome浏览器进行授权\");\n const authUrl = this.oauth2Client.generateAuthUrl({\n access_type: \"offline\",\n scope: this.scope,\n });\n return await openAndWaitReturnQuery(authUrl, 12345, \"code\");\n }\n\n private async initCredentialsImpl(): Promise<void> {\n if (!this.tokens) {\n const code = await this.getCode();\n const { tokens } = await this.oauth2Client.getToken(code);\n await this.saveTokens(tokens);\n }\n this.oauth2Client.setCredentials(this.tokens);\n }\n private initCredentialsPromise: Promise<void> | null = null;\n async initCredentials() {\n if (!this.initCredentialsPromise) {\n this.initCredentialsPromise = this.initCredentialsImpl();\n }\n return await this.initCredentialsPromise;\n }\n}\n\n// see in https://console.cloud.google.com/apis/credentials?organizationId=286245507762&orgonly=true&project=dune-cli&supportedpurview=organizationId\nconst clientSecret = {\n client_id:\n \"467670582023-3sr5gnfsuebgtde1mk3vp78om43no4kv.apps.googleusercontent.com\",\n project_id: \"dune-cli-376503\",\n auth_uri: \"https://accounts.google.com/o/oauth2/auth\",\n token_uri: \"https://oauth2.googleapis.com/token\",\n auth_provider_x509_cert_url: \"https://www.googleapis.com/oauth2/v1/certs\",\n client_secret: \"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\",\n redirect_uris: [\"http://localhost\"],\n javascript_origins: [\"http://localhost\"],\n};\nexport const googleAuth = new GoogleAuth(clientSecret);\n","import connect from \"connect\";\nimport open from \"open\";\nimport { URL } from \"url\";\nimport { createLogger } from \"../index\";\n\nconst log = createLogger(\"google:shared\");\n\nfunction openBrowser(url: string) {\n log.info(`如未自动打开浏览器,可访问以下地址:${url}`);\n open(url, { app: { name: open.apps.chrome } });\n}\n\nexport function openAndWaitReturnQuery(\n toOpenUrl: string,\n port: number,\n queryKey: string\n) {\n return new Promise<string>((resolve) => {\n openBrowser(toOpenUrl);\n\n const app = connect();\n app.use((req, res, next) => {\n const parsedUrl = new URL(req.url, `http://localhost:${port}`);\n const target = parsedUrl.searchParams.get(queryKey);\n if (target) {\n res.writeHead(200, {\n \"content-type\": \"text/html;charset=utf8\",\n });\n res.end(\n `<div>当前窗口可直接关闭</div>\n <script>\n window.open(\"\", \"_self\", \"\");\n window.close();\n </script>`\n );\n server.close();\n server.unref();\n resolve(target);\n }\n next();\n });\n\n const server = app.listen(port);\n });\n}\n"],"mappings":"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","names":["homeConfigDir","path","item","google","fs","URL","URL","log","fs","log","google"]}