gws-axi 0.1.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.
- package/LICENSE +21 -0
- package/README.md +91 -0
- package/dist/bin/gws-axi.d.ts +2 -0
- package/dist/bin/gws-axi.js +4 -0
- package/dist/bin/gws-axi.js.map +1 -0
- package/dist/src/auth/gcloud.d.ts +21 -0
- package/dist/src/auth/gcloud.js +134 -0
- package/dist/src/auth/gcloud.js.map +1 -0
- package/dist/src/auth/loopback.d.ts +50 -0
- package/dist/src/auth/loopback.js +420 -0
- package/dist/src/auth/loopback.js.map +1 -0
- package/dist/src/auth/pending.d.ts +15 -0
- package/dist/src/auth/pending.js +35 -0
- package/dist/src/auth/pending.js.map +1 -0
- package/dist/src/auth/scopes.d.ts +13 -0
- package/dist/src/auth/scopes.js +29 -0
- package/dist/src/auth/scopes.js.map +1 -0
- package/dist/src/auth/setup-html.d.ts +13 -0
- package/dist/src/auth/setup-html.js +245 -0
- package/dist/src/auth/setup-html.js.map +1 -0
- package/dist/src/auth/state.d.ts +4 -0
- package/dist/src/auth/state.js +41 -0
- package/dist/src/auth/state.js.map +1 -0
- package/dist/src/auth/steps.d.ts +30 -0
- package/dist/src/auth/steps.js +306 -0
- package/dist/src/auth/steps.js.map +1 -0
- package/dist/src/cli.d.ts +2 -0
- package/dist/src/cli.js +72 -0
- package/dist/src/cli.js.map +1 -0
- package/dist/src/commands/auth.d.ts +2 -0
- package/dist/src/commands/auth.js +453 -0
- package/dist/src/commands/auth.js.map +1 -0
- package/dist/src/commands/calendar/calendars.d.ts +2 -0
- package/dist/src/commands/calendar/calendars.js +98 -0
- package/dist/src/commands/calendar/calendars.js.map +1 -0
- package/dist/src/commands/calendar/events.d.ts +2 -0
- package/dist/src/commands/calendar/events.js +261 -0
- package/dist/src/commands/calendar/events.js.map +1 -0
- package/dist/src/commands/calendar/get.d.ts +2 -0
- package/dist/src/commands/calendar/get.js +176 -0
- package/dist/src/commands/calendar/get.js.map +1 -0
- package/dist/src/commands/calendar.d.ts +2 -0
- package/dist/src/commands/calendar.js +76 -0
- package/dist/src/commands/calendar.js.map +1 -0
- package/dist/src/commands/docs.d.ts +2 -0
- package/dist/src/commands/docs.js +19 -0
- package/dist/src/commands/docs.js.map +1 -0
- package/dist/src/commands/doctor.d.ts +2 -0
- package/dist/src/commands/doctor.js +213 -0
- package/dist/src/commands/doctor.js.map +1 -0
- package/dist/src/commands/drive.d.ts +2 -0
- package/dist/src/commands/drive.js +17 -0
- package/dist/src/commands/drive.js.map +1 -0
- package/dist/src/commands/gmail.d.ts +2 -0
- package/dist/src/commands/gmail.js +20 -0
- package/dist/src/commands/gmail.js.map +1 -0
- package/dist/src/commands/home.d.ts +1 -0
- package/dist/src/commands/home.js +42 -0
- package/dist/src/commands/home.js.map +1 -0
- package/dist/src/commands/service-stub.d.ts +8 -0
- package/dist/src/commands/service-stub.js +67 -0
- package/dist/src/commands/service-stub.js.map +1 -0
- package/dist/src/commands/slides.d.ts +2 -0
- package/dist/src/commands/slides.js +11 -0
- package/dist/src/commands/slides.js.map +1 -0
- package/dist/src/config.d.ts +46 -0
- package/dist/src/config.js +155 -0
- package/dist/src/config.js.map +1 -0
- package/dist/src/google/account.d.ts +12 -0
- package/dist/src/google/account.js +65 -0
- package/dist/src/google/account.js.map +1 -0
- package/dist/src/google/client.d.ts +29 -0
- package/dist/src/google/client.js +106 -0
- package/dist/src/google/client.js.map +1 -0
- package/dist/src/google/probe.d.ts +15 -0
- package/dist/src/google/probe.js +200 -0
- package/dist/src/google/probe.js.map +1 -0
- package/dist/src/google/tokens.d.ts +22 -0
- package/dist/src/google/tokens.js +91 -0
- package/dist/src/google/tokens.js.map +1 -0
- package/dist/src/output/index.d.ts +2 -0
- package/dist/src/output/index.js +3 -0
- package/dist/src/output/index.js.map +1 -0
- package/dist/src/output/render.d.ts +40 -0
- package/dist/src/output/render.js +65 -0
- package/dist/src/output/render.js.map +1 -0
- package/dist/src/output/schema.d.ts +32 -0
- package/dist/src/output/schema.js +69 -0
- package/dist/src/output/schema.js.map +1 -0
- package/package.json +61 -0
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
import { existsSync, readFileSync, writeFileSync } from "node:fs";
|
|
2
|
+
import { AxiError } from "axi-sdk-js";
|
|
3
|
+
import { credentialsPath, tokensPathForAccount } from "../config.js";
|
|
4
|
+
/** Access token lifetime safety buffer — refresh 5 min before expiry. */
|
|
5
|
+
const EXPIRY_BUFFER_MS = 5 * 60_000;
|
|
6
|
+
export function readTokens(email) {
|
|
7
|
+
const path = tokensPathForAccount(email);
|
|
8
|
+
if (!existsSync(path))
|
|
9
|
+
return null;
|
|
10
|
+
try {
|
|
11
|
+
return JSON.parse(readFileSync(path, "utf-8"));
|
|
12
|
+
}
|
|
13
|
+
catch {
|
|
14
|
+
return null;
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
function writeTokens(email, tokens) {
|
|
18
|
+
writeFileSync(tokensPathForAccount(email), `${JSON.stringify(tokens, null, 2)}\n`, { mode: 0o600 });
|
|
19
|
+
}
|
|
20
|
+
function readCredentials() {
|
|
21
|
+
if (!existsSync(credentialsPath())) {
|
|
22
|
+
throw new AxiError("credentials.json missing — run `gws-axi auth setup`", "CREDENTIALS_MISSING", ["Run `gws-axi auth setup --credentials-json <path>`"]);
|
|
23
|
+
}
|
|
24
|
+
const parsed = JSON.parse(readFileSync(credentialsPath(), "utf-8"));
|
|
25
|
+
if (!parsed.installed?.client_id || !parsed.installed?.client_secret) {
|
|
26
|
+
throw new AxiError("credentials.json is not a Desktop OAuth client", "INVALID_CREDENTIALS", ["Re-run `gws-axi auth setup --credentials-json <path>` with a Desktop client JSON"]);
|
|
27
|
+
}
|
|
28
|
+
return parsed.installed;
|
|
29
|
+
}
|
|
30
|
+
function isExpired(tokens) {
|
|
31
|
+
return tokens.expiry_date <= Date.now() + EXPIRY_BUFFER_MS;
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* Force-refresh the access token using the stored refresh_token. Persists
|
|
35
|
+
* the new access_token + expiry_date back to tokens.json (keeps the
|
|
36
|
+
* existing refresh_token since Google doesn't rotate it on every refresh).
|
|
37
|
+
*/
|
|
38
|
+
export async function refreshAccessToken(email) {
|
|
39
|
+
const tokens = readTokens(email);
|
|
40
|
+
if (!tokens) {
|
|
41
|
+
throw new AxiError(`No stored tokens for ${email}`, "TOKENS_MISSING", [`Run \`gws-axi auth login --account ${email}\` to authenticate`]);
|
|
42
|
+
}
|
|
43
|
+
if (!tokens.refresh_token) {
|
|
44
|
+
throw new AxiError(`No refresh token for ${email} — access token cannot be renewed`, "REFRESH_TOKEN_MISSING", [`Run \`gws-axi auth login --account ${email}\` to re-authenticate`]);
|
|
45
|
+
}
|
|
46
|
+
const creds = readCredentials();
|
|
47
|
+
const body = new URLSearchParams({
|
|
48
|
+
client_id: creds.client_id,
|
|
49
|
+
client_secret: creds.client_secret,
|
|
50
|
+
refresh_token: tokens.refresh_token,
|
|
51
|
+
grant_type: "refresh_token",
|
|
52
|
+
});
|
|
53
|
+
const res = await fetch("https://oauth2.googleapis.com/token", {
|
|
54
|
+
method: "POST",
|
|
55
|
+
headers: { "content-type": "application/x-www-form-urlencoded" },
|
|
56
|
+
body,
|
|
57
|
+
});
|
|
58
|
+
if (!res.ok) {
|
|
59
|
+
const txt = await res.text();
|
|
60
|
+
// invalid_grant means the refresh token itself is revoked/expired
|
|
61
|
+
if (res.status === 400 && txt.includes("invalid_grant")) {
|
|
62
|
+
throw new AxiError(`Refresh token for ${email} has been revoked or expired (Testing-mode tokens expire after 7 days)`, "REFRESH_TOKEN_REVOKED", [`Run \`gws-axi auth login --account ${email}\` to re-authenticate`]);
|
|
63
|
+
}
|
|
64
|
+
throw new AxiError(`Token refresh failed (${res.status}): ${txt.slice(0, 200)}`, "REFRESH_FAILED", [`Run \`gws-axi auth login --account ${email}\` to re-authenticate`]);
|
|
65
|
+
}
|
|
66
|
+
const fresh = (await res.json());
|
|
67
|
+
const updated = {
|
|
68
|
+
...tokens,
|
|
69
|
+
access_token: fresh.access_token,
|
|
70
|
+
expiry_date: Date.now() + fresh.expires_in * 1000,
|
|
71
|
+
scope: fresh.scope || tokens.scope,
|
|
72
|
+
token_type: fresh.token_type,
|
|
73
|
+
};
|
|
74
|
+
writeTokens(email, updated);
|
|
75
|
+
return updated;
|
|
76
|
+
}
|
|
77
|
+
/**
|
|
78
|
+
* Return a valid access token for the account — auto-refreshing if the
|
|
79
|
+
* stored one is expired or within EXPIRY_BUFFER_MS of expiry. Throws
|
|
80
|
+
* AxiError if the account isn't authenticated or refresh fails.
|
|
81
|
+
*/
|
|
82
|
+
export async function getValidAccessToken(email) {
|
|
83
|
+
const tokens = readTokens(email);
|
|
84
|
+
if (!tokens) {
|
|
85
|
+
throw new AxiError(`No stored tokens for ${email}`, "TOKENS_MISSING", [`Run \`gws-axi auth login --account ${email}\` to authenticate`]);
|
|
86
|
+
}
|
|
87
|
+
if (!isExpired(tokens))
|
|
88
|
+
return tokens;
|
|
89
|
+
return refreshAccessToken(email);
|
|
90
|
+
}
|
|
91
|
+
//# sourceMappingURL=tokens.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tokens.js","sourceRoot":"","sources":["../../../src/google/tokens.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/output/index.ts"],"names":[],"mappings":"AAAA,cAAc,aAAa,CAAC;AAC5B,cAAc,aAAa,CAAC"}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import type { FieldDef } from "./schema.js";
|
|
2
|
+
/**
|
|
3
|
+
* Render a list of items as a TOON table with the given field schema.
|
|
4
|
+
* Returns a raw TOON string (not wrapped in an object) so it can be
|
|
5
|
+
* composed into a larger output.
|
|
6
|
+
*
|
|
7
|
+
* Output shape:
|
|
8
|
+
* <name>[N]{col1,col2,col3}:
|
|
9
|
+
* val1,val2,val3
|
|
10
|
+
* val1,val2,val3
|
|
11
|
+
*/
|
|
12
|
+
export declare function renderList(name: string, items: Array<Record<string, unknown>>, schema: FieldDef[]): string;
|
|
13
|
+
/**
|
|
14
|
+
* Render a simple key/value object as TOON.
|
|
15
|
+
*/
|
|
16
|
+
export declare function renderObject(value: Record<string, unknown>): string;
|
|
17
|
+
/**
|
|
18
|
+
* Render a help array. Returns empty string for empty help to keep output
|
|
19
|
+
* clean.
|
|
20
|
+
*/
|
|
21
|
+
export declare function renderHelp(suggestions: string[]): string;
|
|
22
|
+
/**
|
|
23
|
+
* Join multiple rendered blocks with newlines, dropping empty ones.
|
|
24
|
+
*/
|
|
25
|
+
export declare function joinBlocks(...blocks: string[]): string;
|
|
26
|
+
/**
|
|
27
|
+
* Compose a list response with optional header (e.g. account info),
|
|
28
|
+
* the list itself, and help suggestions. Every block is optional.
|
|
29
|
+
*/
|
|
30
|
+
export declare function renderListResponse(options: {
|
|
31
|
+
header?: Record<string, unknown>;
|
|
32
|
+
name: string;
|
|
33
|
+
items: Array<Record<string, unknown>>;
|
|
34
|
+
schema: FieldDef[];
|
|
35
|
+
suggestions?: string[];
|
|
36
|
+
/** Emitted after the header but before the list — e.g. "count: 3 of 47 total". */
|
|
37
|
+
summary?: Record<string, unknown>;
|
|
38
|
+
/** Message when items is empty — replaces the list block entirely. */
|
|
39
|
+
emptyMessage?: string;
|
|
40
|
+
}): string;
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
import { encode } from "@toon-format/toon";
|
|
2
|
+
/**
|
|
3
|
+
* Render a list of items as a TOON table with the given field schema.
|
|
4
|
+
* Returns a raw TOON string (not wrapped in an object) so it can be
|
|
5
|
+
* composed into a larger output.
|
|
6
|
+
*
|
|
7
|
+
* Output shape:
|
|
8
|
+
* <name>[N]{col1,col2,col3}:
|
|
9
|
+
* val1,val2,val3
|
|
10
|
+
* val1,val2,val3
|
|
11
|
+
*/
|
|
12
|
+
export function renderList(name, items, schema) {
|
|
13
|
+
const projected = items.map((item) => Object.fromEntries(schema.map((f) => [f.name, f.extract(item) ?? ""])));
|
|
14
|
+
return encode({ [name]: projected });
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* Render a simple key/value object as TOON.
|
|
18
|
+
*/
|
|
19
|
+
export function renderObject(value) {
|
|
20
|
+
return encode(value);
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* Render a help array. Returns empty string for empty help to keep output
|
|
24
|
+
* clean.
|
|
25
|
+
*/
|
|
26
|
+
export function renderHelp(suggestions) {
|
|
27
|
+
if (suggestions.length === 0)
|
|
28
|
+
return "";
|
|
29
|
+
return encode({ help: suggestions });
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* Join multiple rendered blocks with newlines, dropping empty ones.
|
|
33
|
+
*/
|
|
34
|
+
export function joinBlocks(...blocks) {
|
|
35
|
+
return blocks.filter((b) => b.length > 0).join("\n");
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* Compose a list response with optional header (e.g. account info),
|
|
39
|
+
* the list itself, and help suggestions. Every block is optional.
|
|
40
|
+
*/
|
|
41
|
+
export function renderListResponse(options) {
|
|
42
|
+
const blocks = [];
|
|
43
|
+
if (options.header)
|
|
44
|
+
blocks.push(renderObject(options.header));
|
|
45
|
+
if (options.summary)
|
|
46
|
+
blocks.push(renderObject(options.summary));
|
|
47
|
+
if (options.items.length === 0) {
|
|
48
|
+
// Emit an empty array so `<name>` stays polymorphically-stable as a
|
|
49
|
+
// list type (strict parsers don't need to handle string-valued
|
|
50
|
+
// variants of the same field). Put the human-readable reason in a
|
|
51
|
+
// separate `message` sibling when provided.
|
|
52
|
+
blocks.push(renderObject({ [options.name]: [] }));
|
|
53
|
+
if (options.emptyMessage) {
|
|
54
|
+
blocks.push(renderObject({ message: options.emptyMessage }));
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
else {
|
|
58
|
+
blocks.push(renderList(options.name, options.items, options.schema));
|
|
59
|
+
}
|
|
60
|
+
if (options.suggestions?.length) {
|
|
61
|
+
blocks.push(renderHelp(options.suggestions));
|
|
62
|
+
}
|
|
63
|
+
return joinBlocks(...blocks);
|
|
64
|
+
}
|
|
65
|
+
//# sourceMappingURL=render.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"render.js","sourceRoot":"","sources":["../../../src/output/render.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,mBAAmB,CAAC;AAG3C;;;;;;;;;GASG;AACH,MAAM,UAAU,UAAU,CACxB,IAAY,EACZ,KAAqC,EACrC,MAAkB;IAElB,MAAM,SAAS,GAAG,KAAK,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CACnC,MAAM,CAAC,WAAW,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,OAAO,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,CACvE,CAAC;IACF,OAAO,MAAM,CAAC,EAAE,CAAC,IAAI,CAAC,EAAE,SAAS,EAAE,CAAC,CAAC;AACvC,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,YAAY,CAAC,KAA8B;IACzD,OAAO,MAAM,CAAC,KAAK,CAAC,CAAC;AACvB,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,UAAU,CAAC,WAAqB;IAC9C,IAAI,WAAW,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,EAAE,CAAC;IACxC,OAAO,MAAM,CAAC,EAAE,IAAI,EAAE,WAAW,EAAE,CAAC,CAAC;AACvC,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,UAAU,CAAC,GAAG,MAAgB;IAC5C,OAAO,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AACvD,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,kBAAkB,CAAC,OAUlC;IACC,MAAM,MAAM,GAAa,EAAE,CAAC;IAC5B,IAAI,OAAO,CAAC,MAAM;QAAE,MAAM,CAAC,IAAI,CAAC,YAAY,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC;IAC9D,IAAI,OAAO,CAAC,OAAO;QAAE,MAAM,CAAC,IAAI,CAAC,YAAY,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC,CAAC;IAChE,IAAI,OAAO,CAAC,KAAK,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAC/B,oEAAoE;QACpE,+DAA+D;QAC/D,kEAAkE;QAClE,4CAA4C;QAC5C,MAAM,CAAC,IAAI,CAAC,YAAY,CAAC,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC,CAAC;QAClD,IAAI,OAAO,CAAC,YAAY,EAAE,CAAC;YACzB,MAAM,CAAC,IAAI,CAAC,YAAY,CAAC,EAAE,OAAO,EAAE,OAAO,CAAC,YAAY,EAAE,CAAC,CAAC,CAAC;QAC/D,CAAC;IACH,CAAC;SAAM,CAAC;QACN,MAAM,CAAC,IAAI,CAAC,UAAU,CAAC,OAAO,CAAC,IAAI,EAAE,OAAO,CAAC,KAAK,EAAE,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC;IACvE,CAAC;IACD,IAAI,OAAO,CAAC,WAAW,EAAE,MAAM,EAAE,CAAC;QAChC,MAAM,CAAC,IAAI,CAAC,UAAU,CAAC,OAAO,CAAC,WAAW,CAAC,CAAC,CAAC;IAC/C,CAAC;IACD,OAAO,UAAU,CAAC,GAAG,MAAM,CAAC,CAAC;AAC/B,CAAC"}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shared schema builders for TOON table rendering. Each FieldDef is a
|
|
3
|
+
* projection from a source object (usually a Google API response row)
|
|
4
|
+
* onto a named column in the output table.
|
|
5
|
+
*
|
|
6
|
+
* Usage:
|
|
7
|
+
* const schema = [
|
|
8
|
+
* field("id"),
|
|
9
|
+
* pluck("creator", "email", "creator_email"),
|
|
10
|
+
* mapEnum("status", { confirmed: "✓", tentative: "?" }, "unknown"),
|
|
11
|
+
* lower("visibility"),
|
|
12
|
+
* ];
|
|
13
|
+
* renderList("events", items, schema);
|
|
14
|
+
*/
|
|
15
|
+
export interface FieldDef {
|
|
16
|
+
name: string;
|
|
17
|
+
extract: (item: Record<string, unknown>) => unknown;
|
|
18
|
+
}
|
|
19
|
+
export declare function field(name: string): FieldDef;
|
|
20
|
+
export declare function lower(name: string): FieldDef;
|
|
21
|
+
export declare function pluck(parent: string, child: string, alias?: string): FieldDef;
|
|
22
|
+
export declare function mapEnum(name: string, mapping: Record<string, string>, fallback: string, alias?: string): FieldDef;
|
|
23
|
+
/**
|
|
24
|
+
* Compute a field from the whole item. Use for derived values (e.g.
|
|
25
|
+
* "5/8 attendees confirmed", "tomorrow 2pm").
|
|
26
|
+
*/
|
|
27
|
+
export declare function computed(name: string, fn: (item: Record<string, unknown>) => unknown): FieldDef;
|
|
28
|
+
/**
|
|
29
|
+
* Truncate a string to `max` chars with ellipsis. Returns the original
|
|
30
|
+
* value when it's not a string.
|
|
31
|
+
*/
|
|
32
|
+
export declare function truncated(name: string, max: number, alias?: string): FieldDef;
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shared schema builders for TOON table rendering. Each FieldDef is a
|
|
3
|
+
* projection from a source object (usually a Google API response row)
|
|
4
|
+
* onto a named column in the output table.
|
|
5
|
+
*
|
|
6
|
+
* Usage:
|
|
7
|
+
* const schema = [
|
|
8
|
+
* field("id"),
|
|
9
|
+
* pluck("creator", "email", "creator_email"),
|
|
10
|
+
* mapEnum("status", { confirmed: "✓", tentative: "?" }, "unknown"),
|
|
11
|
+
* lower("visibility"),
|
|
12
|
+
* ];
|
|
13
|
+
* renderList("events", items, schema);
|
|
14
|
+
*/
|
|
15
|
+
export function field(name) {
|
|
16
|
+
return { name, extract: (item) => item[name] };
|
|
17
|
+
}
|
|
18
|
+
export function lower(name) {
|
|
19
|
+
return {
|
|
20
|
+
name,
|
|
21
|
+
extract: (item) => {
|
|
22
|
+
const value = item[name];
|
|
23
|
+
return typeof value === "string" ? value.toLowerCase() : value;
|
|
24
|
+
},
|
|
25
|
+
};
|
|
26
|
+
}
|
|
27
|
+
export function pluck(parent, child, alias) {
|
|
28
|
+
return {
|
|
29
|
+
name: alias ?? `${parent}_${child}`,
|
|
30
|
+
extract: (item) => {
|
|
31
|
+
const parentVal = item[parent];
|
|
32
|
+
return parentVal?.[child];
|
|
33
|
+
},
|
|
34
|
+
};
|
|
35
|
+
}
|
|
36
|
+
export function mapEnum(name, mapping, fallback, alias) {
|
|
37
|
+
return {
|
|
38
|
+
name: alias ?? name,
|
|
39
|
+
extract: (item) => {
|
|
40
|
+
const value = item[name];
|
|
41
|
+
if (typeof value !== "string")
|
|
42
|
+
return fallback;
|
|
43
|
+
return mapping[value] ?? fallback;
|
|
44
|
+
},
|
|
45
|
+
};
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* Compute a field from the whole item. Use for derived values (e.g.
|
|
49
|
+
* "5/8 attendees confirmed", "tomorrow 2pm").
|
|
50
|
+
*/
|
|
51
|
+
export function computed(name, fn) {
|
|
52
|
+
return { name, extract: fn };
|
|
53
|
+
}
|
|
54
|
+
/**
|
|
55
|
+
* Truncate a string to `max` chars with ellipsis. Returns the original
|
|
56
|
+
* value when it's not a string.
|
|
57
|
+
*/
|
|
58
|
+
export function truncated(name, max, alias) {
|
|
59
|
+
return {
|
|
60
|
+
name: alias ?? name,
|
|
61
|
+
extract: (item) => {
|
|
62
|
+
const value = item[name];
|
|
63
|
+
if (typeof value !== "string")
|
|
64
|
+
return value;
|
|
65
|
+
return value.length > max ? `${value.slice(0, max - 1)}…` : value;
|
|
66
|
+
},
|
|
67
|
+
};
|
|
68
|
+
}
|
|
69
|
+
//# sourceMappingURL=schema.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"schema.js","sourceRoot":"","sources":["../../../src/output/schema.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAOH,MAAM,UAAU,KAAK,CAAC,IAAY;IAChC,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC;AACjD,CAAC;AAED,MAAM,UAAU,KAAK,CAAC,IAAY;IAChC,OAAO;QACL,IAAI;QACJ,OAAO,EAAE,CAAC,IAAI,EAAE,EAAE;YAChB,MAAM,KAAK,GAAG,IAAI,CAAC,IAAI,CAAC,CAAC;YACzB,OAAO,OAAO,KAAK,KAAK,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAC,WAAW,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC;QACjE,CAAC;KACF,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,KAAK,CACnB,MAAc,EACd,KAAa,EACb,KAAc;IAEd,OAAO;QACL,IAAI,EAAE,KAAK,IAAI,GAAG,MAAM,IAAI,KAAK,EAAE;QACnC,OAAO,EAAE,CAAC,IAAI,EAAE,EAAE;YAChB,MAAM,SAAS,GAAG,IAAI,CAAC,MAAM,CAAwC,CAAC;YACtE,OAAO,SAAS,EAAE,CAAC,KAAK,CAAC,CAAC;QAC5B,CAAC;KACF,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,OAAO,CACrB,IAAY,EACZ,OAA+B,EAC/B,QAAgB,EAChB,KAAc;IAEd,OAAO;QACL,IAAI,EAAE,KAAK,IAAI,IAAI;QACnB,OAAO,EAAE,CAAC,IAAI,EAAE,EAAE;YAChB,MAAM,KAAK,GAAG,IAAI,CAAC,IAAI,CAAC,CAAC;YACzB,IAAI,OAAO,KAAK,KAAK,QAAQ;gBAAE,OAAO,QAAQ,CAAC;YAC/C,OAAO,OAAO,CAAC,KAAK,CAAC,IAAI,QAAQ,CAAC;QACpC,CAAC;KACF,CAAC;AACJ,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,QAAQ,CACtB,IAAY,EACZ,EAA8C;IAE9C,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,EAAE,EAAE,CAAC;AAC/B,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,SAAS,CAAC,IAAY,EAAE,GAAW,EAAE,KAAc;IACjE,OAAO;QACL,IAAI,EAAE,KAAK,IAAI,IAAI;QACnB,OAAO,EAAE,CAAC,IAAI,EAAE,EAAE;YAChB,MAAM,KAAK,GAAG,IAAI,CAAC,IAAI,CAAC,CAAC;YACzB,IAAI,OAAO,KAAK,KAAK,QAAQ;gBAAE,OAAO,KAAK,CAAC;YAC5C,OAAO,KAAK,CAAC,MAAM,GAAG,GAAG,CAAC,CAAC,CAAC,GAAG,KAAK,CAAC,KAAK,CAAC,CAAC,EAAE,GAAG,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,KAAK,CAAC;QACpE,CAAC;KACF,CAAC;AACJ,CAAC"}
|
package/package.json
ADDED
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "gws-axi",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "AXI-compliant Google Workspace CLI — token-efficient TOON output, agent-guided auth setup, unified interface for Gmail, Calendar, Docs, Drive, Slides",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"repository": {
|
|
7
|
+
"type": "git",
|
|
8
|
+
"url": "git+https://github.com/JarvusInnovations/gws-axi.git"
|
|
9
|
+
},
|
|
10
|
+
"keywords": [
|
|
11
|
+
"google",
|
|
12
|
+
"google-workspace",
|
|
13
|
+
"gmail",
|
|
14
|
+
"calendar",
|
|
15
|
+
"docs",
|
|
16
|
+
"drive",
|
|
17
|
+
"slides",
|
|
18
|
+
"cli",
|
|
19
|
+
"agent",
|
|
20
|
+
"axi",
|
|
21
|
+
"toon"
|
|
22
|
+
],
|
|
23
|
+
"bin": {
|
|
24
|
+
"gws-axi": "dist/bin/gws-axi.js"
|
|
25
|
+
},
|
|
26
|
+
"files": [
|
|
27
|
+
"dist",
|
|
28
|
+
"LICENSE",
|
|
29
|
+
"README.md"
|
|
30
|
+
],
|
|
31
|
+
"publishConfig": {
|
|
32
|
+
"access": "public"
|
|
33
|
+
},
|
|
34
|
+
"scripts": {
|
|
35
|
+
"build": "tsc && chmod +x dist/bin/gws-axi.js",
|
|
36
|
+
"dev": "bun bin/gws-axi.ts",
|
|
37
|
+
"test": "vitest run",
|
|
38
|
+
"test:watch": "vitest",
|
|
39
|
+
"prepublishOnly": "bun run build"
|
|
40
|
+
},
|
|
41
|
+
"license": "MIT",
|
|
42
|
+
"engines": {
|
|
43
|
+
"node": ">=20"
|
|
44
|
+
},
|
|
45
|
+
"dependencies": {
|
|
46
|
+
"@toon-format/toon": "^2.1.0",
|
|
47
|
+
"axi-sdk-js": "^0.1.4",
|
|
48
|
+
"google-auth-library": "^10.6.2",
|
|
49
|
+
"googleapis": "^171.4.0"
|
|
50
|
+
},
|
|
51
|
+
"devDependencies": {
|
|
52
|
+
"@types/node": "^25.6.0",
|
|
53
|
+
"typescript": "^6.0.3",
|
|
54
|
+
"vitest": "^4.1.4"
|
|
55
|
+
},
|
|
56
|
+
"author": "Jarvus Innovations <hello@jarv.us>",
|
|
57
|
+
"homepage": "https://github.com/JarvusInnovations/gws-axi#readme",
|
|
58
|
+
"bugs": {
|
|
59
|
+
"url": "https://github.com/JarvusInnovations/gws-axi/issues"
|
|
60
|
+
}
|
|
61
|
+
}
|