gws-axi 0.10.2 → 0.12.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,7 @@
1
+ export declare const MKDIR_HELP = "usage: gws-axi drive mkdir <name> [flags]\nargs[1]:\n <name> REQUIRED \u2014 the folder name\nflags[2]:\n --parent <folder-id> Parent folder ID (default: My Drive root)\n --account <email> REQUIRED when 2+ accounts are authenticated\nexamples:\n gws-axi drive mkdir \"Q2 Reports\"\n gws-axi drive mkdir Invoices --parent 1AbC...\nnotes:\n Drive allows duplicate folder names \u2014 re-running creates ANOTHER folder.\n Capture the returned id to nest uploads with `drive upload --parent <id>`.\noutput:\n An `action: created` line plus a `folder{...}` object with id, name,\n parents, and web_view_link.\n";
2
+ export interface ParsedFlags {
3
+ name: string | undefined;
4
+ parent: string | undefined;
5
+ }
6
+ export declare function parseFlags(args: string[]): ParsedFlags;
7
+ export declare function driveMkdirCommand(account: string, args: string[]): Promise<string>;
@@ -0,0 +1,101 @@
1
+ import { AxiError } from "axi-sdk-js";
2
+ import { driveClient, translateGoogleError } from "../../google/client.js";
3
+ import { joinBlocks, renderHelp, renderObject } from "../../output/index.js";
4
+ export const MKDIR_HELP = `usage: gws-axi drive mkdir <name> [flags]
5
+ args[1]:
6
+ <name> REQUIRED — the folder name
7
+ flags[2]:
8
+ --parent <folder-id> Parent folder ID (default: My Drive root)
9
+ --account <email> REQUIRED when 2+ accounts are authenticated
10
+ examples:
11
+ gws-axi drive mkdir "Q2 Reports"
12
+ gws-axi drive mkdir Invoices --parent 1AbC...
13
+ notes:
14
+ Drive allows duplicate folder names — re-running creates ANOTHER folder.
15
+ Capture the returned id to nest uploads with \`drive upload --parent <id>\`.
16
+ output:
17
+ An \`action: created\` line plus a \`folder{...}\` object with id, name,
18
+ parents, and web_view_link.
19
+ `;
20
+ const FOLDER_MIME = "application/vnd.google-apps.folder";
21
+ const MKDIR_FIELDS = "id,name,parents,webViewLink";
22
+ export function parseFlags(args) {
23
+ const flags = { name: undefined, parent: undefined };
24
+ for (let i = 0; i < args.length; i++) {
25
+ const arg = args[i];
26
+ const next = args[i + 1];
27
+ switch (arg) {
28
+ case "--parent":
29
+ flags.parent = next;
30
+ i++;
31
+ break;
32
+ default:
33
+ if (!arg.startsWith("--") && flags.name === undefined) {
34
+ flags.name = arg;
35
+ }
36
+ break;
37
+ }
38
+ }
39
+ return flags;
40
+ }
41
+ export async function driveMkdirCommand(account, args) {
42
+ const flags = parseFlags(args);
43
+ if (!flags.name) {
44
+ throw new AxiError("Missing folder name", "VALIDATION_ERROR", [
45
+ "Usage: gws-axi drive mkdir <name> [--parent <folder-id>]",
46
+ ]);
47
+ }
48
+ const api = await driveClient(account);
49
+ const requestBody = {
50
+ name: flags.name,
51
+ mimeType: FOLDER_MIME,
52
+ };
53
+ if (flags.parent)
54
+ requestBody.parents = [flags.parent];
55
+ let folder;
56
+ try {
57
+ const res = await api.files.create({
58
+ requestBody,
59
+ fields: MKDIR_FIELDS,
60
+ supportsAllDrives: true,
61
+ });
62
+ folder = res.data;
63
+ }
64
+ catch (err) {
65
+ const translated = translateGoogleError(err, {
66
+ account,
67
+ operation: "drive.files.create",
68
+ });
69
+ if (translated.code === "NOT_FOUND") {
70
+ throw new AxiError(`Parent folder '${flags.parent}' not found (or ${account} can't write to it)`, "FILE_NOT_FOUND", [
71
+ "Verify the --parent ID is correct (from a Drive URL or `drive ls` / `drive search`)",
72
+ `Confirm ${account} has edit access`,
73
+ ]);
74
+ }
75
+ throw translated;
76
+ }
77
+ const id = folder.id ?? "";
78
+ const details = {
79
+ id,
80
+ name: folder.name ?? flags.name,
81
+ parents: folder.parents?.length ? folder.parents.join(", ") : "",
82
+ };
83
+ if (folder.webViewLink)
84
+ details.web_view_link = folder.webViewLink;
85
+ const blocks = [];
86
+ blocks.push(renderObject({ action: "created", account }));
87
+ blocks.push(renderObject({ folder: details }));
88
+ const suggestions = [
89
+ `Run \`gws-axi drive upload <file> --parent ${id}\` to put a file in this folder`,
90
+ `Run \`gws-axi drive ls ${id}\` to list its contents`,
91
+ `Run \`gws-axi drive get ${id}\` for full metadata`,
92
+ `Run \`gws-axi drive permissions ${id}\` to see / change who has access`,
93
+ `Re-running creates another folder (Drive allows duplicate names) — capture this id to reuse it`,
94
+ ];
95
+ if (folder.webViewLink) {
96
+ suggestions.push(`Open in browser: ${folder.webViewLink}`);
97
+ }
98
+ blocks.push(renderHelp(suggestions));
99
+ return joinBlocks(...blocks);
100
+ }
101
+ //# sourceMappingURL=mkdir.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mkdir.js","sourceRoot":"","sources":["../../../../src/commands/drive/mkdir.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,40 @@
1
+ import { describe, expect, it } from "vitest";
2
+ import { AxiError } from "axi-sdk-js";
3
+ import { parseFlags, driveMkdirCommand } from "./mkdir.js";
4
+ describe("drive mkdir parseFlags", () => {
5
+ it("parses a bare name with no parent", () => {
6
+ const f = parseFlags(["Reports"]);
7
+ expect(f.name).toBe("Reports");
8
+ expect(f.parent).toBeUndefined();
9
+ });
10
+ it("parses a quoted multi-word name and --parent", () => {
11
+ const f = parseFlags(["Q2 Reports", "--parent", "1AbC"]);
12
+ expect(f.name).toBe("Q2 Reports");
13
+ expect(f.parent).toBe("1AbC");
14
+ });
15
+ it("takes the first positional as the name, ignoring later ones", () => {
16
+ const f = parseFlags(["first", "second"]);
17
+ expect(f.name).toBe("first");
18
+ });
19
+ it("leaves name undefined when only flags are given", () => {
20
+ const f = parseFlags(["--parent", "1AbC"]);
21
+ expect(f.name).toBeUndefined();
22
+ expect(f.parent).toBe("1AbC");
23
+ });
24
+ });
25
+ describe("drive mkdir command validation", () => {
26
+ it("throws VALIDATION_ERROR when the name is missing", async () => {
27
+ await expect(driveMkdirCommand("a@b.com", ["--parent", "1AbC"])).rejects.toMatchObject({ code: "VALIDATION_ERROR" });
28
+ });
29
+ it("rejects with an AxiError (not a raw throw) on missing name", async () => {
30
+ try {
31
+ await driveMkdirCommand("a@b.com", []);
32
+ throw new Error("should have thrown");
33
+ }
34
+ catch (err) {
35
+ expect(err).toBeInstanceOf(AxiError);
36
+ expect(err.code).toBe("VALIDATION_ERROR");
37
+ }
38
+ });
39
+ });
40
+ //# sourceMappingURL=mkdir.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mkdir.test.js","sourceRoot":"","sources":["../../../../src/commands/drive/mkdir.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,QAAQ,CAAC;AAC9C,OAAO,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AACtC,OAAO,EAAE,UAAU,EAAE,iBAAiB,EAAE,MAAM,YAAY,CAAC;AAE3D,QAAQ,CAAC,wBAAwB,EAAE,GAAG,EAAE;IACtC,EAAE,CAAC,mCAAmC,EAAE,GAAG,EAAE;QAC3C,MAAM,CAAC,GAAG,UAAU,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC;QAClC,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;QAC/B,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,aAAa,EAAE,CAAC;IACnC,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,8CAA8C,EAAE,GAAG,EAAE;QACtD,MAAM,CAAC,GAAG,UAAU,CAAC,CAAC,YAAY,EAAE,UAAU,EAAE,MAAM,CAAC,CAAC,CAAC;QACzD,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC;QAClC,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;IAChC,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,6DAA6D,EAAE,GAAG,EAAE;QACrE,MAAM,CAAC,GAAG,UAAU,CAAC,CAAC,OAAO,EAAE,QAAQ,CAAC,CAAC,CAAC;QAC1C,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;IAC/B,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,iDAAiD,EAAE,GAAG,EAAE;QACzD,MAAM,CAAC,GAAG,UAAU,CAAC,CAAC,UAAU,EAAE,MAAM,CAAC,CAAC,CAAC;QAC3C,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,aAAa,EAAE,CAAC;QAC/B,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;IAChC,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC;AAEH,QAAQ,CAAC,gCAAgC,EAAE,GAAG,EAAE;IAC9C,EAAE,CAAC,kDAAkD,EAAE,KAAK,IAAI,EAAE;QAChE,MAAM,MAAM,CAAC,iBAAiB,CAAC,SAAS,EAAE,CAAC,UAAU,EAAE,MAAM,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,aAAa,CACpF,EAAE,IAAI,EAAE,kBAAkB,EAAE,CAC7B,CAAC;IACJ,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,4DAA4D,EAAE,KAAK,IAAI,EAAE;QAC1E,IAAI,CAAC;YACH,MAAM,iBAAiB,CAAC,SAAS,EAAE,EAAE,CAAC,CAAC;YACvC,MAAM,IAAI,KAAK,CAAC,oBAAoB,CAAC,CAAC;QACxC,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,MAAM,CAAC,GAAG,CAAC,CAAC,cAAc,CAAC,QAAQ,CAAC,CAAC;YACrC,MAAM,CAAE,GAAgB,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,kBAAkB,CAAC,CAAC;QAC1D,CAAC;IACH,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC"}
@@ -0,0 +1,17 @@
1
+ export declare const UPLOAD_HELP = "usage: gws-axi drive upload <local-path> [flags]\nargs[1]:\n <local-path> REQUIRED \u2014 path to a readable local file to upload\nflags[5]:\n --parent <folder-id> Destination folder ID (default: My Drive root).\n Cannot be combined with --update.\n --name <name> Name to give the file in Drive (default: the local\n file's basename). With --update, renames the target.\n --mime <type> Override the source content type (default: detected\n from the file extension; unknown \u2192 application/octet-stream)\n --convert Convert to the matching native Google format on upload\n (.docx\u2192Doc, .xlsx/.csv\u2192Sheet, .pptx\u2192Slides). Cannot be\n combined with --update.\n --update <file-id> Replace an existing file's content (new revision)\n instead of creating a new file.\n --account <email> REQUIRED when 2+ accounts are authenticated\nexamples:\n gws-axi drive upload ./report.pdf\n gws-axi drive upload ./report.pdf --parent 1AbC... --name \"Q2 Report.pdf\"\n gws-axi drive upload ./notes.docx --convert\n gws-axi drive upload ./report.pdf --update 1XyZ...\nnotes:\n Without --update, every upload creates a NEW Drive file \u2014 re-running makes\n another copy (Drive allows duplicate names). Use --update <id> to replace an\n existing file's content in place.\noutput:\n An `action: created` (or `updated`) line plus a `file{...}` object with\n id, name, mime_type, size_bytes, parents, and web_view_link.\n";
2
+ export interface ParsedFlags {
3
+ localPath: string | undefined;
4
+ parent: string | undefined;
5
+ name: string | undefined;
6
+ mime: string | undefined;
7
+ convert: boolean;
8
+ update: string | undefined;
9
+ }
10
+ export declare function parseFlags(args: string[]): ParsedFlags;
11
+ /**
12
+ * Validate the local path is present and the flag combination is legal,
13
+ * before any FS/network work. Pure — throws `AxiError` on the same cases the
14
+ * spec enumerates, so it's unit-testable without touching disk or Google.
15
+ */
16
+ export declare function validateFlags(flags: ParsedFlags): void;
17
+ export declare function driveUploadCommand(account: string, args: string[]): Promise<string>;
@@ -0,0 +1,217 @@
1
+ import { createReadStream } from "node:fs";
2
+ import { stat } from "node:fs/promises";
3
+ import { basename, resolve } from "node:path";
4
+ import { AxiError } from "axi-sdk-js";
5
+ import { driveClient, translateGoogleError } from "../../google/client.js";
6
+ import { joinBlocks, renderHelp, renderObject } from "../../output/index.js";
7
+ import { detectMimeType, googleConversionTarget, } from "../../util/mime-types.js";
8
+ export const UPLOAD_HELP = `usage: gws-axi drive upload <local-path> [flags]
9
+ args[1]:
10
+ <local-path> REQUIRED — path to a readable local file to upload
11
+ flags[5]:
12
+ --parent <folder-id> Destination folder ID (default: My Drive root).
13
+ Cannot be combined with --update.
14
+ --name <name> Name to give the file in Drive (default: the local
15
+ file's basename). With --update, renames the target.
16
+ --mime <type> Override the source content type (default: detected
17
+ from the file extension; unknown → application/octet-stream)
18
+ --convert Convert to the matching native Google format on upload
19
+ (.docx→Doc, .xlsx/.csv→Sheet, .pptx→Slides). Cannot be
20
+ combined with --update.
21
+ --update <file-id> Replace an existing file's content (new revision)
22
+ instead of creating a new file.
23
+ --account <email> REQUIRED when 2+ accounts are authenticated
24
+ examples:
25
+ gws-axi drive upload ./report.pdf
26
+ gws-axi drive upload ./report.pdf --parent 1AbC... --name "Q2 Report.pdf"
27
+ gws-axi drive upload ./notes.docx --convert
28
+ gws-axi drive upload ./report.pdf --update 1XyZ...
29
+ notes:
30
+ Without --update, every upload creates a NEW Drive file — re-running makes
31
+ another copy (Drive allows duplicate names). Use --update <id> to replace an
32
+ existing file's content in place.
33
+ output:
34
+ An \`action: created\` (or \`updated\`) line plus a \`file{...}\` object with
35
+ id, name, mime_type, size_bytes, parents, and web_view_link.
36
+ `;
37
+ export function parseFlags(args) {
38
+ const flags = {
39
+ localPath: undefined,
40
+ parent: undefined,
41
+ name: undefined,
42
+ mime: undefined,
43
+ convert: false,
44
+ update: undefined,
45
+ };
46
+ for (let i = 0; i < args.length; i++) {
47
+ const arg = args[i];
48
+ const next = args[i + 1];
49
+ switch (arg) {
50
+ case "--parent":
51
+ flags.parent = next;
52
+ i++;
53
+ break;
54
+ case "--name":
55
+ flags.name = next;
56
+ i++;
57
+ break;
58
+ case "--mime":
59
+ flags.mime = next;
60
+ i++;
61
+ break;
62
+ case "--convert":
63
+ flags.convert = true;
64
+ break;
65
+ case "--update":
66
+ flags.update = next;
67
+ i++;
68
+ break;
69
+ default:
70
+ if (!arg.startsWith("--") && flags.localPath === undefined) {
71
+ flags.localPath = arg;
72
+ }
73
+ break;
74
+ }
75
+ }
76
+ return flags;
77
+ }
78
+ const UPLOAD_FIELDS = "id,name,mimeType,size,parents,webViewLink";
79
+ /**
80
+ * Validate the local path is present and the flag combination is legal,
81
+ * before any FS/network work. Pure — throws `AxiError` on the same cases the
82
+ * spec enumerates, so it's unit-testable without touching disk or Google.
83
+ */
84
+ export function validateFlags(flags) {
85
+ if (!flags.localPath) {
86
+ throw new AxiError("Missing local file path", "VALIDATION_ERROR", [
87
+ "Usage: gws-axi drive upload <local-path> [flags]",
88
+ ]);
89
+ }
90
+ if (flags.update && flags.parent) {
91
+ throw new AxiError("--parent cannot be combined with --update", "VALIDATION_ERROR", [
92
+ "--update replaces a file's content in place; moving folders is not supported here",
93
+ "Drop --parent, or upload as a new file (omit --update) to place it in a folder",
94
+ ]);
95
+ }
96
+ if (flags.update && flags.convert) {
97
+ throw new AxiError("--convert cannot be combined with --update", "VALIDATION_ERROR", [
98
+ "Converting a file's type in place is not supported",
99
+ "Drop --convert to replace content as-is, or upload a new file (omit --update) with --convert",
100
+ ]);
101
+ }
102
+ }
103
+ export async function driveUploadCommand(account, args) {
104
+ const flags = parseFlags(args);
105
+ validateFlags(flags);
106
+ const absolutePath = resolve(process.cwd(), flags.localPath);
107
+ let fileStat;
108
+ try {
109
+ fileStat = await stat(absolutePath);
110
+ }
111
+ catch {
112
+ throw new AxiError(`Local file not found: ${flags.localPath}`, "LOCAL_FILE_NOT_FOUND", ["Check the path; it must be a readable file on this machine"]);
113
+ }
114
+ if (fileStat.isDirectory()) {
115
+ throw new AxiError(`Local path is a directory, not a file: ${flags.localPath}`, "LOCAL_PATH_NOT_FILE", ["Upload a single file; recursive directory upload is not supported"]);
116
+ }
117
+ const name = flags.name ?? basename(absolutePath);
118
+ const sourceMime = flags.mime ?? detectMimeType(absolutePath);
119
+ let targetMime;
120
+ if (flags.convert) {
121
+ const target = googleConversionTarget(sourceMime);
122
+ if (!target) {
123
+ throw new AxiError(`Cannot convert ${sourceMime} to a native Google format`, "UNSUPPORTED_CONVERSION", [
124
+ "Supported: word-processing/text → Doc, spreadsheets/CSV → Sheet, presentations → Slides",
125
+ "Drop --convert to upload the file as-is",
126
+ ]);
127
+ }
128
+ targetMime = target;
129
+ }
130
+ const api = await driveClient(account);
131
+ const media = {
132
+ mimeType: sourceMime,
133
+ body: createReadStream(absolutePath),
134
+ };
135
+ let file;
136
+ const updating = Boolean(flags.update);
137
+ try {
138
+ if (flags.update) {
139
+ const res = await api.files.update({
140
+ fileId: flags.update,
141
+ requestBody: flags.name ? { name } : {},
142
+ media,
143
+ fields: UPLOAD_FIELDS,
144
+ supportsAllDrives: true,
145
+ });
146
+ file = res.data;
147
+ }
148
+ else {
149
+ const requestBody = { name };
150
+ if (flags.parent)
151
+ requestBody.parents = [flags.parent];
152
+ if (targetMime)
153
+ requestBody.mimeType = targetMime;
154
+ const res = await api.files.create({
155
+ requestBody,
156
+ media,
157
+ fields: UPLOAD_FIELDS,
158
+ supportsAllDrives: true,
159
+ });
160
+ file = res.data;
161
+ }
162
+ }
163
+ catch (err) {
164
+ const translated = translateGoogleError(err, {
165
+ account,
166
+ operation: updating ? "drive.files.update" : "drive.files.create",
167
+ });
168
+ if (translated.code === "NOT_FOUND") {
169
+ // For --update, the missing item is the target file; for create it's the
170
+ // --parent folder. Re-wrap with an access-check suggestion (cf. drive get).
171
+ const missing = updating
172
+ ? `File '${flags.update}' not found (or ${account} can't write to it)`
173
+ : `Parent folder '${flags.parent}' not found (or ${account} can't write to it)`;
174
+ throw new AxiError(missing, "FILE_NOT_FOUND", [
175
+ "Verify the ID is correct (from a Drive URL or `drive search` / `drive ls`)",
176
+ `Confirm ${account} has edit access`,
177
+ ]);
178
+ }
179
+ throw translated;
180
+ }
181
+ const details = {
182
+ id: file.id ?? "",
183
+ name: file.name ?? name,
184
+ mime_type: file.mimeType ?? "",
185
+ };
186
+ if (file.size)
187
+ details.size_bytes = parseInt(file.size, 10);
188
+ details.parents = file.parents?.length ? file.parents.join(", ") : "";
189
+ if (file.webViewLink)
190
+ details.web_view_link = file.webViewLink;
191
+ const blocks = [];
192
+ blocks.push(renderObject({ action: updating ? "updated" : "created", account }));
193
+ blocks.push(renderObject({ file: details }));
194
+ const suggestions = [];
195
+ const id = file.id ?? "";
196
+ const isNativeDoc = file.mimeType === "application/vnd.google-apps.document";
197
+ if (isNativeDoc) {
198
+ suggestions.push(`Run \`gws-axi docs read ${id}\` to read it as markdown`);
199
+ }
200
+ else if ((file.mimeType ?? "").startsWith("application/vnd.google-apps.")) {
201
+ suggestions.push(`Native Google file — run \`gws-axi docs download ${id} --as <mime>\` to export it`);
202
+ }
203
+ else {
204
+ suggestions.push(`Run \`gws-axi docs download ${id} --out <path>\` to fetch the bytes back`);
205
+ }
206
+ suggestions.push(`Run \`gws-axi drive get ${id}\` for full metadata`);
207
+ suggestions.push(`Run \`gws-axi drive permissions ${id}\` to see / change who has access`);
208
+ if (!updating) {
209
+ suggestions.push(`Re-running creates another copy — pass \`--update ${id}\` to replace this file's content instead`);
210
+ }
211
+ if (file.webViewLink) {
212
+ suggestions.push(`Open in browser: ${file.webViewLink}`);
213
+ }
214
+ blocks.push(renderHelp(suggestions));
215
+ return joinBlocks(...blocks);
216
+ }
217
+ //# sourceMappingURL=upload.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"upload.js","sourceRoot":"","sources":["../../../../src/commands/drive/upload.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,86 @@
1
+ import { describe, expect, it } from "vitest";
2
+ import { AxiError } from "axi-sdk-js";
3
+ import { parseFlags, validateFlags } from "./upload.js";
4
+ describe("drive upload parseFlags", () => {
5
+ it("parses a bare local path with defaults", () => {
6
+ const f = parseFlags(["./report.pdf"]);
7
+ expect(f.localPath).toBe("./report.pdf");
8
+ expect(f.parent).toBeUndefined();
9
+ expect(f.name).toBeUndefined();
10
+ expect(f.mime).toBeUndefined();
11
+ expect(f.convert).toBe(false);
12
+ expect(f.update).toBeUndefined();
13
+ });
14
+ it("parses all flags", () => {
15
+ const f = parseFlags([
16
+ "./report.pdf",
17
+ "--parent",
18
+ "1AbC",
19
+ "--name",
20
+ "Q2 Report.pdf",
21
+ "--mime",
22
+ "application/pdf",
23
+ "--convert",
24
+ ]);
25
+ expect(f.localPath).toBe("./report.pdf");
26
+ expect(f.parent).toBe("1AbC");
27
+ expect(f.name).toBe("Q2 Report.pdf");
28
+ expect(f.mime).toBe("application/pdf");
29
+ expect(f.convert).toBe(true);
30
+ });
31
+ it("parses --update with a file id", () => {
32
+ const f = parseFlags(["./report.pdf", "--update", "1XyZ"]);
33
+ expect(f.update).toBe("1XyZ");
34
+ });
35
+ it("takes the first positional as the local path, ignoring later ones", () => {
36
+ const f = parseFlags(["./a.pdf", "./b.pdf"]);
37
+ expect(f.localPath).toBe("./a.pdf");
38
+ });
39
+ });
40
+ describe("drive upload validateFlags", () => {
41
+ const base = {
42
+ localPath: "./report.pdf",
43
+ parent: undefined,
44
+ name: undefined,
45
+ mime: undefined,
46
+ convert: false,
47
+ update: undefined,
48
+ };
49
+ it("accepts a valid create invocation", () => {
50
+ expect(() => validateFlags({ ...base, parent: "1AbC" })).not.toThrow();
51
+ });
52
+ it("accepts a valid update invocation", () => {
53
+ expect(() => validateFlags({ ...base, update: "1XyZ" })).not.toThrow();
54
+ });
55
+ it("throws VALIDATION_ERROR when the local path is missing", () => {
56
+ try {
57
+ validateFlags({ ...base, localPath: undefined });
58
+ throw new Error("should have thrown");
59
+ }
60
+ catch (err) {
61
+ expect(err).toBeInstanceOf(AxiError);
62
+ expect(err.code).toBe("VALIDATION_ERROR");
63
+ }
64
+ });
65
+ it("rejects --parent combined with --update", () => {
66
+ try {
67
+ validateFlags({ ...base, parent: "1AbC", update: "1XyZ" });
68
+ throw new Error("should have thrown");
69
+ }
70
+ catch (err) {
71
+ expect(err).toBeInstanceOf(AxiError);
72
+ expect(err.code).toBe("VALIDATION_ERROR");
73
+ }
74
+ });
75
+ it("rejects --convert combined with --update", () => {
76
+ try {
77
+ validateFlags({ ...base, convert: true, update: "1XyZ" });
78
+ throw new Error("should have thrown");
79
+ }
80
+ catch (err) {
81
+ expect(err).toBeInstanceOf(AxiError);
82
+ expect(err.code).toBe("VALIDATION_ERROR");
83
+ }
84
+ });
85
+ });
86
+ //# sourceMappingURL=upload.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"upload.test.js","sourceRoot":"","sources":["../../../../src/commands/drive/upload.test.ts"],"names":[],"mappings":"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"}
@@ -7,6 +7,8 @@ import { drivePermissionsCommand, PERMISSIONS_HELP, } from "./drive/permissions.
7
7
  import { driveActivityCommand, ACTIVITY_HELP } from "./drive/activity.js";
8
8
  import { driveRevisionsCommand, REVISIONS_HELP, } from "./drive/revisions.js";
9
9
  import { driveSearchCommand, SEARCH_HELP } from "./drive/search.js";
10
+ import { driveUploadCommand, UPLOAD_HELP } from "./drive/upload.js";
11
+ import { driveMkdirCommand, MKDIR_HELP } from "./drive/mkdir.js";
10
12
  // Drive `download` shares the docs/download.ts implementation — same code
11
13
  // path handles native Google file export + uploaded-file media fetch.
12
14
  const DOWNLOAD_HELP = `usage: gws-axi drive download <file-id> [flags]
@@ -45,9 +47,6 @@ status: planned for v1 writes — not yet implemented
45
47
  const DELETE_HELP = `usage: gws-axi drive delete <file-id> [flags]
46
48
  status: planned for v1 writes — not yet implemented
47
49
  `;
48
- const MKDIR_HELP = `usage: gws-axi drive mkdir --name <name> --parent <folder-id> [flags]
49
- status: planned for v1 writes — not yet implemented
50
- `;
51
50
  const SUBCOMMANDS = [
52
51
  { name: "search", mutation: false, help: SEARCH_HELP, handler: driveSearchCommand },
53
52
  { name: "get", mutation: false, help: GET_HELP, handler: driveGetCommand },
@@ -77,12 +76,23 @@ const SUBCOMMANDS = [
77
76
  help: ACTIVITY_HELP,
78
77
  handler: driveActivityCommand,
79
78
  },
79
+ {
80
+ name: "upload",
81
+ mutation: true,
82
+ help: UPLOAD_HELP,
83
+ handler: driveUploadCommand,
84
+ },
80
85
  { name: "create", mutation: true, help: CREATE_HELP },
81
86
  { name: "copy", mutation: true, help: COPY_HELP },
82
87
  { name: "move", mutation: true, help: MOVE_HELP },
83
88
  { name: "rename", mutation: true, help: RENAME_HELP },
84
89
  { name: "delete", mutation: true, help: DELETE_HELP },
85
- { name: "mkdir", mutation: true, help: MKDIR_HELP },
90
+ {
91
+ name: "mkdir",
92
+ mutation: true,
93
+ help: MKDIR_HELP,
94
+ handler: driveMkdirCommand,
95
+ },
86
96
  ];
87
97
  const SUB_BY_NAME = Object.fromEntries(SUBCOMMANDS.map((s) => [s.name, s]));
88
98
  function parseAccountFlag(args) {
@@ -109,20 +119,24 @@ writes[${writes.length}]:
109
119
  notes:
110
120
  Writes require --account <email> when 2+ accounts are authenticated.
111
121
  Reads use the default account when --account is not provided.
112
- Write subcommands are scaffolded for the next slice; they throw
113
- NOT_IMPLEMENTED after account resolution runs.
122
+ upload and mkdir are live; the remaining write subcommands are scaffolded
123
+ for the next slice and throw NOT_IMPLEMENTED after account resolution runs.
114
124
  subcommand help:
115
125
  gws-axi drive ls --help for folder listing (incl. --recursive)
116
126
  gws-axi drive get --help for full file metadata
117
127
  gws-axi drive search --help for full-text search
118
128
  gws-axi drive permissions --help for access / sharing
119
129
  gws-axi drive download --help for fetching bytes (alias of docs download)
130
+ gws-axi drive upload --help for uploading a local file (incl. --convert)
131
+ gws-axi drive mkdir --help for creating a folder
120
132
  examples:
121
133
  gws-axi drive ls
122
134
  gws-axi drive ls <folder-id> --recursive
123
135
  gws-axi drive search --query "project plan"
124
136
  gws-axi drive get <file-id>
125
137
  gws-axi drive permissions <file-id>
138
+ gws-axi drive upload ./report.pdf --account you@example.com
139
+ gws-axi drive mkdir "Q2 Reports" --account you@example.com
126
140
  `;
127
141
  export async function driveCommand(args) {
128
142
  if (args.length === 0 || (args.length === 1 && args[0] === "--help")) {
@@ -1 +1 @@
1
- {"version":3,"file":"drive.js","sourceRoot":"","sources":["../../../src/commands/drive.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"drive.js","sourceRoot":"","sources":["../../../src/commands/drive.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AACtC,OAAO,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AACtD,OAAO,EAAE,mBAAmB,EAAE,MAAM,oBAAoB,CAAC;AACzD,OAAO,EAAE,eAAe,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAC;AAC3D,OAAO,EAAE,cAAc,EAAE,OAAO,EAAE,MAAM,eAAe,CAAC;AACxD,OAAO,EACL,uBAAuB,EACvB,gBAAgB,GACjB,MAAM,wBAAwB,CAAC;AAChC,OAAO,EAAE,oBAAoB,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AAC1E,OAAO,EACL,qBAAqB,EACrB,cAAc,GACf,MAAM,sBAAsB,CAAC;AAC9B,OAAO,EAAE,kBAAkB,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AACpE,OAAO,EAAE,kBAAkB,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AACpE,OAAO,EAAE,iBAAiB,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AASjE,0EAA0E;AAC1E,sEAAsE;AACtE,MAAM,aAAa,GAAG;;;;;;;;;;;;;;;;;;;CAmBrB,CAAC;AAEF,2EAA2E;AAC3E,MAAM,WAAW,GAAG;;CAEnB,CAAC;AACF,MAAM,SAAS,GAAG;;CAEjB,CAAC;AACF,MAAM,SAAS,GAAG;;CAEjB,CAAC;AACF,MAAM,WAAW,GAAG;;CAEnB,CAAC;AACF,MAAM,WAAW,GAAG;;CAEnB,CAAC;AAEF,MAAM,WAAW,GAAsB;IACrC,EAAE,IAAI,EAAE,QAAQ,EAAE,QAAQ,EAAE,KAAK,EAAE,IAAI,EAAE,WAAW,EAAE,OAAO,EAAE,kBAAkB,EAAE;IACnF,EAAE,IAAI,EAAE,KAAK,EAAE,QAAQ,EAAE,KAAK,EAAE,IAAI,EAAE,QAAQ,EAAE,OAAO,EAAE,eAAe,EAAE;IAC1E,EAAE,IAAI,EAAE,IAAI,EAAE,QAAQ,EAAE,KAAK,EAAE,IAAI,EAAE,OAAO,EAAE,OAAO,EAAE,cAAc,EAAE;IACvE;QACE,IAAI,EAAE,aAAa;QACnB,QAAQ,EAAE,KAAK;QACf,IAAI,EAAE,gBAAgB;QACtB,OAAO,EAAE,uBAAuB;KACjC;IACD;QACE,IAAI,EAAE,UAAU;QAChB,QAAQ,EAAE,KAAK;QACf,IAAI,EAAE,aAAa;QACnB,oEAAoE;QACpE,OAAO,EAAE,mBAAmB;KAC7B;IACD;QACE,IAAI,EAAE,WAAW;QACjB,QAAQ,EAAE,KAAK;QACf,IAAI,EAAE,cAAc;QACpB,OAAO,EAAE,qBAAqB;KAC/B;IACD;QACE,IAAI,EAAE,UAAU;QAChB,QAAQ,EAAE,KAAK;QACf,IAAI,EAAE,aAAa;QACnB,OAAO,EAAE,oBAAoB;KAC9B;IACD;QACE,IAAI,EAAE,QAAQ;QACd,QAAQ,EAAE,IAAI;QACd,IAAI,EAAE,WAAW;QACjB,OAAO,EAAE,kBAAkB;KAC5B;IACD,EAAE,IAAI,EAAE,QAAQ,EAAE,QAAQ,EAAE,IAAI,EAAE,IAAI,EAAE,WAAW,EAAE;IACrD,EAAE,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,IAAI,EAAE,IAAI,EAAE,SAAS,EAAE;IACjD,EAAE,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,IAAI,EAAE,IAAI,EAAE,SAAS,EAAE;IACjD,EAAE,IAAI,EAAE,QAAQ,EAAE,QAAQ,EAAE,IAAI,EAAE,IAAI,EAAE,WAAW,EAAE;IACrD,EAAE,IAAI,EAAE,QAAQ,EAAE,QAAQ,EAAE,IAAI,EAAE,IAAI,EAAE,WAAW,EAAE;IACrD;QACE,IAAI,EAAE,OAAO;QACb,QAAQ,EAAE,IAAI;QACd,IAAI,EAAE,UAAU;QAChB,OAAO,EAAE,iBAAiB;KAC3B;CACF,CAAC;AAEF,MAAM,WAAW,GAAoC,MAAM,CAAC,WAAW,CACrE,WAAW,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,CACpC,CAAC;AAEF,SAAS,gBAAgB,CAAC,IAAc;IAItC,MAAM,IAAI,GAAa,EAAE,CAAC;IAC1B,IAAI,OAA2B,CAAC;IAChC,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,IAAI,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QACrC,MAAM,GAAG,GAAG,IAAI,CAAC,CAAC,CAAC,CAAC;QACpB,IAAI,GAAG,KAAK,WAAW,IAAI,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,EAAE,CAAC;YACvC,OAAO,GAAG,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC;YACtB,CAAC,EAAE,CAAC;YACJ,SAAS;QACX,CAAC;QACD,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IACjB,CAAC;IACD,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC;AAC3B,CAAC;AAED,MAAM,KAAK,GAAG,WAAW,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;AACxE,MAAM,MAAM,GAAG,WAAW,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;AAExE,MAAM,CAAC,MAAM,UAAU,GAAG;QAClB,KAAK,CAAC,MAAM;IAChB,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC;SACX,MAAM,CAAC,MAAM;IAClB,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC;;;;;;;;;;;;;;;;;;;;;;CAsBpB,CAAC;AAEF,MAAM,CAAC,KAAK,UAAU,YAAY,CAAC,IAAc;IAC/C,IAAI,IAAI,CAAC,MAAM,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,KAAK,CAAC,IAAI,IAAI,CAAC,CAAC,CAAC,KAAK,QAAQ,CAAC,EAAE,CAAC;QACrE,OAAO,UAAU,CAAC;IACpB,CAAC;IAED,MAAM,GAAG,GAAG,IAAI,CAAC,CAAC,CAAC,CAAC;IACpB,MAAM,GAAG,GAAG,WAAW,CAAC,GAAG,CAAC,CAAC;IAC7B,IAAI,CAAC,GAAG,EAAE,CAAC;QACT,MAAM,IAAI,QAAQ,CAChB,6BAA6B,GAAG,EAAE,EAClC,kBAAkB,EAClB,CAAC,2DAA2D,CAAC,CAC9D,CAAC;IACJ,CAAC;IAED,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;IAC3B,IAAI,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,EAAE,CAAC;QAC5B,OAAO,GAAG,CAAC,IAAI,CAAC;IAClB,CAAC;IAED,MAAM,EAAE,OAAO,EAAE,WAAW,EAAE,IAAI,EAAE,SAAS,EAAE,GAAG,gBAAgB,CAAC,IAAI,CAAC,CAAC;IACzE,MAAM,UAAU,GAAG,cAAc,CAAC,WAAW,EAAE;QAC7C,QAAQ,EAAE,GAAG,CAAC,QAAQ;QACtB,WAAW,EAAE,SAAS,GAAG,EAAE;KAC5B,CAAC,CAAC;IAEH,IAAI,CAAC,GAAG,CAAC,OAAO,EAAE,CAAC;QACjB,MAAM,IAAI,QAAQ,CAChB,iBAAiB,GAAG,yBAAyB,EAC7C,iBAAiB,EACjB;YACE,8CAA8C,UAAU,CAAC,OAAO,EAAE;YAClE,uBAAuB,GAAG,mCAAmC;SAC9D,CACF,CAAC;IACJ,CAAC;IAED,OAAO,GAAG,CAAC,OAAO,CAAC,UAAU,CAAC,OAAO,EAAE,SAAS,CAAC,CAAC;AACpD,CAAC"}
@@ -0,0 +1,7 @@
1
+ export declare const DEFAULT_MIME_TYPE = "application/octet-stream";
2
+ /**
3
+ * Detect a MIME type from a file path's extension. Case-insensitive; returns
4
+ * `application/octet-stream` for unknown or absent extensions.
5
+ */
6
+ export declare function detectMimeType(path: string): string;
7
+ export declare function googleConversionTarget(sourceMime: string): string | null;
@@ -0,0 +1,95 @@
1
+ import { extname } from "node:path";
2
+ /**
3
+ * Minimal extension → MIME table for `drive upload`. Node has no built-in
4
+ * MIME lookup, and pulling in a full database is overkill: this covers the
5
+ * office/document/text/image/archive types an agent actually uploads. Unknown
6
+ * extensions fall back to `application/octet-stream` (a safe generic binary
7
+ * type Drive accepts), so detection never throws — it only ever under-labels.
8
+ */
9
+ const EXTENSION_MIME = {
10
+ // Office (OOXML)
11
+ docx: "application/vnd.openxmlformats-officedocument.wordprocessingml.document",
12
+ xlsx: "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
13
+ pptx: "application/vnd.openxmlformats-officedocument.presentationml.presentation",
14
+ // Office (legacy)
15
+ doc: "application/msword",
16
+ xls: "application/vnd.ms-excel",
17
+ ppt: "application/vnd.ms-powerpoint",
18
+ // Text & delimited
19
+ txt: "text/plain",
20
+ md: "text/markdown",
21
+ markdown: "text/markdown",
22
+ csv: "text/csv",
23
+ tsv: "text/tab-separated-values",
24
+ rtf: "application/rtf",
25
+ html: "text/html",
26
+ htm: "text/html",
27
+ json: "application/json",
28
+ xml: "application/xml",
29
+ yaml: "application/yaml",
30
+ yml: "application/yaml",
31
+ // Documents
32
+ pdf: "application/pdf",
33
+ // Images
34
+ png: "image/png",
35
+ jpg: "image/jpeg",
36
+ jpeg: "image/jpeg",
37
+ gif: "image/gif",
38
+ webp: "image/webp",
39
+ svg: "image/svg+xml",
40
+ bmp: "image/bmp",
41
+ tif: "image/tiff",
42
+ tiff: "image/tiff",
43
+ heic: "image/heic",
44
+ // Audio / video
45
+ mp3: "audio/mpeg",
46
+ wav: "audio/wav",
47
+ mp4: "video/mp4",
48
+ mov: "video/quicktime",
49
+ // Archives
50
+ zip: "application/zip",
51
+ gz: "application/gzip",
52
+ tar: "application/x-tar",
53
+ };
54
+ export const DEFAULT_MIME_TYPE = "application/octet-stream";
55
+ /**
56
+ * Detect a MIME type from a file path's extension. Case-insensitive; returns
57
+ * `application/octet-stream` for unknown or absent extensions.
58
+ */
59
+ export function detectMimeType(path) {
60
+ const ext = extname(path).replace(/^\./, "").toLowerCase();
61
+ if (!ext)
62
+ return DEFAULT_MIME_TYPE;
63
+ return EXTENSION_MIME[ext] ?? DEFAULT_MIME_TYPE;
64
+ }
65
+ const GOOGLE_DOC = "application/vnd.google-apps.document";
66
+ const GOOGLE_SHEET = "application/vnd.google-apps.spreadsheet";
67
+ const GOOGLE_SLIDES = "application/vnd.google-apps.presentation";
68
+ /**
69
+ * Map a source MIME type to the native Google Workspace target Drive can
70
+ * convert it into on upload (the `--convert` flag). Returns `null` when the
71
+ * source has no sensible native target — the caller surfaces
72
+ * `UNSUPPORTED_CONVERSION`.
73
+ */
74
+ const CONVERSION_TARGETS = {
75
+ // → Google Doc
76
+ "application/vnd.openxmlformats-officedocument.wordprocessingml.document": GOOGLE_DOC,
77
+ "application/msword": GOOGLE_DOC,
78
+ "application/rtf": GOOGLE_DOC,
79
+ "text/rtf": GOOGLE_DOC,
80
+ "text/plain": GOOGLE_DOC,
81
+ "text/markdown": GOOGLE_DOC,
82
+ "text/html": GOOGLE_DOC,
83
+ // → Google Sheet
84
+ "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet": GOOGLE_SHEET,
85
+ "application/vnd.ms-excel": GOOGLE_SHEET,
86
+ "text/csv": GOOGLE_SHEET,
87
+ "text/tab-separated-values": GOOGLE_SHEET,
88
+ // → Google Slides
89
+ "application/vnd.openxmlformats-officedocument.presentationml.presentation": GOOGLE_SLIDES,
90
+ "application/vnd.ms-powerpoint": GOOGLE_SLIDES,
91
+ };
92
+ export function googleConversionTarget(sourceMime) {
93
+ return CONVERSION_TARGETS[sourceMime.toLowerCase()] ?? null;
94
+ }
95
+ //# sourceMappingURL=mime-types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mime-types.js","sourceRoot":"","sources":["../../../src/util/mime-types.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAEpC;;;;;;GAMG;AACH,MAAM,cAAc,GAA2B;IAC7C,iBAAiB;IACjB,IAAI,EAAE,yEAAyE;IAC/E,IAAI,EAAE,mEAAmE;IACzE,IAAI,EAAE,2EAA2E;IACjF,kBAAkB;IAClB,GAAG,EAAE,oBAAoB;IACzB,GAAG,EAAE,0BAA0B;IAC/B,GAAG,EAAE,+BAA+B;IACpC,mBAAmB;IACnB,GAAG,EAAE,YAAY;IACjB,EAAE,EAAE,eAAe;IACnB,QAAQ,EAAE,eAAe;IACzB,GAAG,EAAE,UAAU;IACf,GAAG,EAAE,2BAA2B;IAChC,GAAG,EAAE,iBAAiB;IACtB,IAAI,EAAE,WAAW;IACjB,GAAG,EAAE,WAAW;IAChB,IAAI,EAAE,kBAAkB;IACxB,GAAG,EAAE,iBAAiB;IACtB,IAAI,EAAE,kBAAkB;IACxB,GAAG,EAAE,kBAAkB;IACvB,YAAY;IACZ,GAAG,EAAE,iBAAiB;IACtB,SAAS;IACT,GAAG,EAAE,WAAW;IAChB,GAAG,EAAE,YAAY;IACjB,IAAI,EAAE,YAAY;IAClB,GAAG,EAAE,WAAW;IAChB,IAAI,EAAE,YAAY;IAClB,GAAG,EAAE,eAAe;IACpB,GAAG,EAAE,WAAW;IAChB,GAAG,EAAE,YAAY;IACjB,IAAI,EAAE,YAAY;IAClB,IAAI,EAAE,YAAY;IAClB,gBAAgB;IAChB,GAAG,EAAE,YAAY;IACjB,GAAG,EAAE,WAAW;IAChB,GAAG,EAAE,WAAW;IAChB,GAAG,EAAE,iBAAiB;IACtB,WAAW;IACX,GAAG,EAAE,iBAAiB;IACtB,EAAE,EAAE,kBAAkB;IACtB,GAAG,EAAE,mBAAmB;CACzB,CAAC;AAEF,MAAM,CAAC,MAAM,iBAAiB,GAAG,0BAA0B,CAAC;AAE5D;;;GAGG;AACH,MAAM,UAAU,cAAc,CAAC,IAAY;IACzC,MAAM,GAAG,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC,OAAO,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC,WAAW,EAAE,CAAC;IAC3D,IAAI,CAAC,GAAG;QAAE,OAAO,iBAAiB,CAAC;IACnC,OAAO,cAAc,CAAC,GAAG,CAAC,IAAI,iBAAiB,CAAC;AAClD,CAAC;AAED,MAAM,UAAU,GAAG,sCAAsC,CAAC;AAC1D,MAAM,YAAY,GAAG,yCAAyC,CAAC;AAC/D,MAAM,aAAa,GAAG,0CAA0C,CAAC;AAEjE;;;;;GAKG;AACH,MAAM,kBAAkB,GAA2B;IACjD,eAAe;IACf,yEAAyE,EACvE,UAAU;IACZ,oBAAoB,EAAE,UAAU;IAChC,iBAAiB,EAAE,UAAU;IAC7B,UAAU,EAAE,UAAU;IACtB,YAAY,EAAE,UAAU;IACxB,eAAe,EAAE,UAAU;IAC3B,WAAW,EAAE,UAAU;IACvB,iBAAiB;IACjB,mEAAmE,EACjE,YAAY;IACd,0BAA0B,EAAE,YAAY;IACxC,UAAU,EAAE,YAAY;IACxB,2BAA2B,EAAE,YAAY;IACzC,kBAAkB;IAClB,2EAA2E,EACzE,aAAa;IACf,+BAA+B,EAAE,aAAa;CAC/C,CAAC;AAEF,MAAM,UAAU,sBAAsB,CAAC,UAAkB;IACvD,OAAO,kBAAkB,CAAC,UAAU,CAAC,WAAW,EAAE,CAAC,IAAI,IAAI,CAAC;AAC9D,CAAC"}
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,47 @@
1
+ import { describe, expect, it } from "vitest";
2
+ import { DEFAULT_MIME_TYPE, detectMimeType, googleConversionTarget, } from "./mime-types.js";
3
+ describe("detectMimeType", () => {
4
+ it("maps common office and document extensions", () => {
5
+ expect(detectMimeType("report.docx")).toBe("application/vnd.openxmlformats-officedocument.wordprocessingml.document");
6
+ expect(detectMimeType("data.xlsx")).toBe("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
7
+ expect(detectMimeType("deck.pptx")).toBe("application/vnd.openxmlformats-officedocument.presentationml.presentation");
8
+ expect(detectMimeType("notes.pdf")).toBe("application/pdf");
9
+ expect(detectMimeType("rows.csv")).toBe("text/csv");
10
+ });
11
+ it("is case-insensitive on the extension", () => {
12
+ expect(detectMimeType("PHOTO.JPG")).toBe("image/jpeg");
13
+ expect(detectMimeType("Report.DOCX")).toBe("application/vnd.openxmlformats-officedocument.wordprocessingml.document");
14
+ });
15
+ it("resolves full and relative paths by their extension", () => {
16
+ expect(detectMimeType("/home/me/pics/cat.png")).toBe("image/png");
17
+ expect(detectMimeType("./sub/dir/file.md")).toBe("text/markdown");
18
+ });
19
+ it("falls back to octet-stream for unknown or absent extensions", () => {
20
+ expect(detectMimeType("mystery.xyz")).toBe(DEFAULT_MIME_TYPE);
21
+ expect(detectMimeType("Makefile")).toBe(DEFAULT_MIME_TYPE);
22
+ expect(detectMimeType("archive.")).toBe(DEFAULT_MIME_TYPE);
23
+ });
24
+ });
25
+ describe("googleConversionTarget", () => {
26
+ it("maps word-processing and text sources to Google Doc", () => {
27
+ expect(googleConversionTarget("application/vnd.openxmlformats-officedocument.wordprocessingml.document")).toBe("application/vnd.google-apps.document");
28
+ expect(googleConversionTarget("text/plain")).toBe("application/vnd.google-apps.document");
29
+ expect(googleConversionTarget("text/markdown")).toBe("application/vnd.google-apps.document");
30
+ });
31
+ it("maps spreadsheet and delimited sources to Google Sheet", () => {
32
+ expect(googleConversionTarget("text/csv")).toBe("application/vnd.google-apps.spreadsheet");
33
+ expect(googleConversionTarget("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet")).toBe("application/vnd.google-apps.spreadsheet");
34
+ });
35
+ it("maps presentation sources to Google Slides", () => {
36
+ expect(googleConversionTarget("application/vnd.ms-powerpoint")).toBe("application/vnd.google-apps.presentation");
37
+ });
38
+ it("is case-insensitive on the source mime", () => {
39
+ expect(googleConversionTarget("TEXT/CSV")).toBe("application/vnd.google-apps.spreadsheet");
40
+ });
41
+ it("returns null for unsupported source types", () => {
42
+ expect(googleConversionTarget("application/pdf")).toBeNull();
43
+ expect(googleConversionTarget("image/png")).toBeNull();
44
+ expect(googleConversionTarget("application/zip")).toBeNull();
45
+ });
46
+ });
47
+ //# sourceMappingURL=mime-types.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mime-types.test.js","sourceRoot":"","sources":["../../../src/util/mime-types.test.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "gws-axi",
3
- "version": "0.10.2",
3
+ "version": "0.12.0",
4
4
  "description": "AXI-compliant Google Workspace CLI — token-efficient TOON output, agent-guided auth setup, unified interface for Gmail, Calendar, Docs, Drive, Slides",
5
5
  "type": "module",
6
6
  "repository": {