@plotday/tool-google-contacts 0.1.0-alpha.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 ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2025 Plot Technologies Inc.
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,77 @@
1
+ # Google Contacts Tool
2
+
3
+ A Plot tool for syncing with Google Contacts.
4
+
5
+ ## Installation
6
+
7
+ ```bash
8
+ npm install @plotday/tool-google-contacts @plotday/sdk
9
+ ```
10
+
11
+ ## Usage
12
+
13
+ ```typescript
14
+ import { Agent, Tools, createAgent } from "@plotday/sdk";
15
+ import { GoogleContacts } from "@plotday/tool-google-contacts";
16
+ import { Auth, AuthLevel, AuthProvider } from "@plotday/sdk/tools/auth";
17
+
18
+ export default createAgent(
19
+ class extends Agent {
20
+ private googleContacts: GoogleContacts;
21
+ private auth: Auth;
22
+
23
+ constructor(tools: Tools) {
24
+ super();
25
+ this.googleContacts = tools.get(GoogleContacts);
26
+ this.auth = tools.get(Auth);
27
+ }
28
+
29
+ async activate(priority: { id: string }) {
30
+ // Request Google Contacts access
31
+ const authLink = await this.auth.request(
32
+ {
33
+ provider: AuthProvider.Google,
34
+ level: AuthLevel.User,
35
+ scopes: ["https://www.googleapis.com/auth/contacts.readonly"],
36
+ },
37
+ {
38
+ functionName: "onAuthComplete",
39
+ context: { priorityId: priority.id },
40
+ }
41
+ );
42
+
43
+ // User will authenticate via authLink
44
+ }
45
+
46
+ async onAuthComplete(authorization: any, context: any) {
47
+ const authToken = await this.auth.get(authorization);
48
+
49
+ // Start syncing contacts
50
+ await this.googleContacts.startSync(authToken, "onContact");
51
+ }
52
+
53
+ async onContact(contact: any) {
54
+ // Handle contact updates
55
+ console.log("Contact:", contact.names?.[0]?.displayName);
56
+ }
57
+ }
58
+ );
59
+ ```
60
+
61
+ ## API
62
+
63
+ ### `getContacts(authToken: string, options?: object)`
64
+
65
+ Retrieves contacts from Google Contacts.
66
+
67
+ ### `startSync(authToken: string, callbackName: string)`
68
+
69
+ Starts syncing contacts from Google Contacts.
70
+
71
+ ### `stopSync(authToken: string)`
72
+
73
+ Stops syncing contacts from Google Contacts.
74
+
75
+ ## License
76
+
77
+ MIT © Plot Technologies Inc.
@@ -0,0 +1,24 @@
1
+ import { Tool, type Tools } from "@plotday/sdk";
2
+ import type { Contact, GoogleContacts } from "./types";
3
+ export default class extends Tool implements GoogleContacts {
4
+ protected tools: Tools;
5
+ static readonly id = "google-contacts";
6
+ private auth;
7
+ private store;
8
+ private run;
9
+ private callback;
10
+ constructor(tools: Tools);
11
+ requestAuth(callbackFunctionName: string, callbackContext?: any): Promise<any>;
12
+ getContacts(authToken: string): Promise<Contact[]>;
13
+ startSync(authToken: string, callbackFunctionName: string, options?: {
14
+ context?: any;
15
+ }): Promise<void>;
16
+ stopSync(authToken: string): Promise<void>;
17
+ syncBatch(context: {
18
+ batchNumber: number;
19
+ authToken: string;
20
+ }): Promise<void>;
21
+ private processContacts;
22
+ onAuthSuccess(authResult: any, context: any): Promise<void>;
23
+ }
24
+ //# sourceMappingURL=google-contacts.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"google-contacts.d.ts","sourceRoot":"","sources":["../src/google-contacts.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,KAAK,KAAK,EAAE,MAAM,cAAc,CAAC;AAKhD,OAAO,KAAK,EAAE,OAAO,EAAe,cAAc,EAAE,MAAM,SAAS,CAAC;AA4OpE,MAAM,CAAC,OAAO,MAAO,SAAQ,IAAK,YAAW,cAAc;IAQ7C,SAAS,CAAC,KAAK,EAAE,KAAK;IAPlC,MAAM,CAAC,QAAQ,CAAC,EAAE,qBAAqB;IAEvC,OAAO,CAAC,IAAI,CAAO;IACnB,OAAO,CAAC,KAAK,CAAQ;IACrB,OAAO,CAAC,GAAG,CAAM;IACjB,OAAO,CAAC,QAAQ,CAAe;gBAET,KAAK,EAAE,KAAK;IAQ5B,WAAW,CACf,oBAAoB,EAAE,MAAM,EAC5B,eAAe,CAAC,EAAE,GAAG,GACpB,OAAO,CAAC,GAAG,CAAC;IAiCT,WAAW,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,EAAE,CAAC;IAkBlD,SAAS,CACb,SAAS,EAAE,MAAM,EACjB,oBAAoB,EAAE,MAAM,EAC5B,OAAO,CAAC,EAAE;QACR,OAAO,CAAC,EAAE,GAAG,CAAC;KACf,GACA,OAAO,CAAC,IAAI,CAAC;IA+BV,QAAQ,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAM1C,SAAS,CAAC,OAAO,EAAE;QACvB,WAAW,EAAE,MAAM,CAAC;QACpB,SAAS,EAAE,MAAM,CAAC;KACnB,GAAG,OAAO,CAAC,IAAI,CAAC;YAuDH,eAAe;IAYvB,aAAa,CAAC,UAAU,EAAE,GAAG,EAAE,OAAO,EAAE,GAAG,GAAG,OAAO,CAAC,IAAI,CAAC;CA4BlE"}
@@ -0,0 +1,305 @@
1
+ import { Tool } from "@plotday/sdk";
2
+ import { Auth, AuthLevel, AuthProvider } from "@plotday/sdk/tools/auth";
3
+ import { CallbackTool } from "@plotday/sdk/tools/callback";
4
+ import { Run } from "@plotday/sdk/tools/run";
5
+ import { Store } from "@plotday/sdk/tools/store";
6
+ class GoogleApi {
7
+ accessToken;
8
+ constructor(accessToken) {
9
+ this.accessToken = accessToken;
10
+ }
11
+ async call(method, url, params, body) {
12
+ const query = params ? `?${new URLSearchParams(params)}` : "";
13
+ const headers = {
14
+ Authorization: `Bearer ${this.accessToken}`,
15
+ Accept: "application/json",
16
+ ...(body ? { "Content-Type": "application/json" } : {}),
17
+ };
18
+ const response = await fetch(url + query, {
19
+ method,
20
+ headers,
21
+ ...(body ? { body: JSON.stringify(body) } : {}),
22
+ });
23
+ switch (response.status) {
24
+ case 400:
25
+ const responseBody = await response.json();
26
+ if (responseBody.status === "FAILED_PRECONDITION") {
27
+ return null;
28
+ }
29
+ throw new Error("Invalid request", { cause: responseBody });
30
+ case 401:
31
+ throw new Error("Authentication failed - token may be expired");
32
+ case 410:
33
+ return null;
34
+ case 200:
35
+ return await response.json();
36
+ default:
37
+ throw new Error(await response.text());
38
+ }
39
+ }
40
+ }
41
+ function parseContact(contact) {
42
+ const name = contact.names?.[0]?.displayName;
43
+ const avatar = contact.photos?.filter((p) => !p.default && p.metadata?.primary)?.[0]?.url;
44
+ return { name, avatar };
45
+ }
46
+ async function getGoogleContacts(api, scopes, state) {
47
+ let tokens = JSON.parse(state.state ?? "{}");
48
+ const contacts = {};
49
+ let more = false;
50
+ if (!state.more || tokens.connections?.nextPageToken) {
51
+ if (scopes?.some?.((scope) => scope === "https://www.googleapis.com/auth/contacts.readonly")) {
52
+ let response;
53
+ while (true) {
54
+ response = (await api.call("GET", "https://people.googleapis.com/v1/people/me/connections", {
55
+ requestSyncToken: true,
56
+ ...(tokens.connections?.nextPageToken
57
+ ? {
58
+ pageToken: tokens.connections?.nextPageToken,
59
+ }
60
+ : tokens.connections?.nextSyncToken
61
+ ? {
62
+ syncToken: tokens.connections?.nextSyncToken,
63
+ }
64
+ : {}),
65
+ personFields: "names,emailAddresses,photos",
66
+ }));
67
+ if (response !== null)
68
+ break;
69
+ if (!tokens.connections)
70
+ break;
71
+ tokens.connections = undefined;
72
+ continue;
73
+ }
74
+ if (response) {
75
+ for (const c of response.connections ?? []) {
76
+ for (const e of c.emailAddresses ?? []) {
77
+ if (!e.value)
78
+ continue;
79
+ const { name, avatar } = parseContact(c);
80
+ contacts[e.value] = {
81
+ ...contacts[e.value],
82
+ email: e.value,
83
+ ...(name ? { name } : {}),
84
+ ...(avatar ? { avatar } : {}),
85
+ };
86
+ }
87
+ }
88
+ more = true;
89
+ tokens = {
90
+ ...tokens,
91
+ connections: {
92
+ nextPageToken: response.nextPageToken ?? undefined,
93
+ nextSyncToken: response.nextSyncToken ?? undefined,
94
+ },
95
+ };
96
+ }
97
+ }
98
+ else {
99
+ more = true;
100
+ tokens = {
101
+ ...tokens,
102
+ connections: {},
103
+ };
104
+ }
105
+ }
106
+ else {
107
+ if (scopes?.some?.((scope) => scope === "https://www.googleapis.com/auth/contacts.other.readonly")) {
108
+ let response;
109
+ while (true) {
110
+ response = (await api.call("GET", "https://people.googleapis.com/v1/otherContacts", {
111
+ requestSyncToken: true,
112
+ ...(tokens.other?.nextPageToken
113
+ ? {
114
+ pageToken: tokens.other?.nextPageToken,
115
+ }
116
+ : tokens.other?.nextSyncToken
117
+ ? {
118
+ syncToken: tokens.other?.nextSyncToken,
119
+ }
120
+ : {}),
121
+ readMask: "names,emailAddresses,photos",
122
+ }));
123
+ if (response !== null)
124
+ break;
125
+ if (!tokens.other)
126
+ break;
127
+ tokens.other = undefined;
128
+ continue;
129
+ }
130
+ if (response) {
131
+ for (const c of response.otherContacts ?? []) {
132
+ for (const e of c.emailAddresses ?? []) {
133
+ if (!e.value)
134
+ continue;
135
+ const { name, avatar } = parseContact(c);
136
+ contacts[e.value] = {
137
+ ...contacts[e.value],
138
+ email: e.value,
139
+ ...(name ? { name } : {}),
140
+ ...(avatar ? { avatar } : {}),
141
+ };
142
+ }
143
+ }
144
+ more = !!response.nextPageToken;
145
+ tokens = {
146
+ ...tokens,
147
+ other: {
148
+ nextPageToken: response.nextPageToken ?? undefined,
149
+ nextSyncToken: response.nextSyncToken ?? undefined,
150
+ },
151
+ };
152
+ }
153
+ }
154
+ else {
155
+ more = false;
156
+ tokens = {
157
+ ...tokens,
158
+ other: {},
159
+ };
160
+ }
161
+ }
162
+ return {
163
+ contacts: Object.values(contacts),
164
+ state: {
165
+ more,
166
+ state: JSON.stringify(tokens),
167
+ },
168
+ };
169
+ }
170
+ export default class default_1 extends Tool {
171
+ tools;
172
+ static id = "google-contacts";
173
+ auth;
174
+ store;
175
+ run;
176
+ callback;
177
+ constructor(tools) {
178
+ super();
179
+ this.tools = tools;
180
+ this.auth = tools.get(Auth);
181
+ this.store = tools.get(Store);
182
+ this.run = tools.get(Run);
183
+ this.callback = tools.get(CallbackTool);
184
+ }
185
+ async requestAuth(callbackFunctionName, callbackContext) {
186
+ const contactsScopes = [
187
+ "https://www.googleapis.com/auth/contacts.readonly",
188
+ "https://www.googleapis.com/auth/contacts.other.readonly",
189
+ ];
190
+ // Generate opaque token for this authorization
191
+ const opaqueToken = crypto.randomUUID();
192
+ // Register the callback for auth completion with opaque token
193
+ const callbackToken = await this.callback.create(callbackFunctionName, callbackContext);
194
+ await this.store.set(`auth_callback_token:${opaqueToken}`, callbackToken);
195
+ // Create callback for auth completion
196
+ const authCallback = await this.callback.create("onAuthSuccess", {
197
+ toolName: "google-contacts",
198
+ opaqueToken,
199
+ });
200
+ // Request auth and return the activity link
201
+ return await this.auth.request({
202
+ provider: AuthProvider.Google,
203
+ level: AuthLevel.User,
204
+ scopes: contactsScopes,
205
+ }, authCallback);
206
+ }
207
+ async getContacts(authToken) {
208
+ const storedAuthToken = await this.store.get(`auth_token:${authToken}`);
209
+ if (!storedAuthToken) {
210
+ throw new Error("No Google authentication token available for the provided authToken");
211
+ }
212
+ const api = new GoogleApi(storedAuthToken.token);
213
+ const result = await getGoogleContacts(api, storedAuthToken.scopes, {
214
+ more: false,
215
+ });
216
+ return result.contacts;
217
+ }
218
+ async startSync(authToken, callbackFunctionName, options) {
219
+ const storedAuthToken = await this.store.get(`auth_token:${authToken}`);
220
+ if (!storedAuthToken) {
221
+ throw new Error("No Google authentication token available for the provided authToken");
222
+ }
223
+ // Register the callback
224
+ const callbackToken = await this.callback.create(callbackFunctionName, options?.context);
225
+ await this.store.set(`contacts_callback_token:${authToken}`, callbackToken);
226
+ // Start initial sync
227
+ const initialState = {
228
+ more: false,
229
+ };
230
+ await this.store.set(`sync_state:${authToken}`, initialState);
231
+ // Start sync batch using run tool for long-running operation
232
+ await this.run.now("syncBatch", {
233
+ batchNumber: 1,
234
+ authToken,
235
+ });
236
+ }
237
+ async stopSync(authToken) {
238
+ // Clear sync state for this specific auth token
239
+ await this.store.clear(`sync_state:${authToken}`);
240
+ await this.store.clear(`contacts_callback_token:${authToken}`);
241
+ }
242
+ async syncBatch(context) {
243
+ const { batchNumber, authToken } = context;
244
+ console.log(`Starting Google Contacts sync batch ${batchNumber}`);
245
+ try {
246
+ const storedAuthToken = await this.store.get(`auth_token:${authToken}`);
247
+ if (!storedAuthToken) {
248
+ throw new Error("No authentication token available for the provided authToken");
249
+ }
250
+ const state = await this.store.get(`sync_state:${authToken}`);
251
+ if (!state) {
252
+ throw new Error("No sync state found");
253
+ }
254
+ const api = new GoogleApi(storedAuthToken.token);
255
+ const result = await getGoogleContacts(api, storedAuthToken.scopes, state);
256
+ if (result.contacts.length > 0) {
257
+ await this.processContacts(result.contacts, authToken);
258
+ console.log(`Synced ${result.contacts.length} contacts in batch ${batchNumber}`);
259
+ }
260
+ await this.store.set(`sync_state:${authToken}`, result.state);
261
+ if (result.state.more) {
262
+ await this.run.now("syncBatch", {
263
+ batchNumber: batchNumber + 1,
264
+ authToken,
265
+ });
266
+ }
267
+ else {
268
+ console.log(`Google Contacts sync completed after ${batchNumber} batches`);
269
+ await this.store.clear(`sync_state:${authToken}`);
270
+ }
271
+ }
272
+ catch (error) {
273
+ console.error(`Error in sync batch ${batchNumber}:`, error);
274
+ throw error;
275
+ }
276
+ }
277
+ async processContacts(contacts, authToken) {
278
+ const callbackToken = await this.store.get(`contacts_callback_token:${authToken}`);
279
+ if (callbackToken) {
280
+ await this.callback.call(callbackToken, contacts);
281
+ }
282
+ }
283
+ async onAuthSuccess(authResult, context) {
284
+ console.log("Google Contacts authentication successful", authResult);
285
+ // Extract opaque token from context
286
+ const opaqueToken = context?.opaqueToken;
287
+ if (!opaqueToken) {
288
+ console.error("No opaque token found in auth context");
289
+ return;
290
+ }
291
+ // Store the actual auth token using opaque token as key
292
+ await this.store.set(`auth_token:${opaqueToken}`, authResult);
293
+ // Retrieve and call the stored callback
294
+ const callbackToken = await this.store.get(`auth_callback_token:${opaqueToken}`);
295
+ if (callbackToken) {
296
+ const authSuccessResult = {
297
+ authToken: opaqueToken,
298
+ };
299
+ await this.callback.call(callbackToken, authSuccessResult);
300
+ // Clean up the callback token
301
+ await this.store.clear(`auth_callback_token:${opaqueToken}`);
302
+ }
303
+ }
304
+ }
305
+ //# sourceMappingURL=google-contacts.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"google-contacts.js","sourceRoot":"","sources":["../src/google-contacts.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ export * from "./types";
2
+ export { default } from "./google-contacts";
3
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,SAAS,CAAC;AACxB,OAAO,EAAE,OAAO,EAAE,MAAM,mBAAmB,CAAC"}
package/dist/index.js ADDED
@@ -0,0 +1,3 @@
1
+ export * from "./types";
2
+ export { default } from "./google-contacts";
3
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,SAAS,CAAC;AACxB,OAAO,EAAE,OAAO,EAAE,MAAM,mBAAmB,CAAC"}
@@ -0,0 +1,18 @@
1
+ import type { ActivityLink, Tool } from "@plotday/sdk";
2
+ export type Contact = {
3
+ email: string;
4
+ name?: string;
5
+ avatar?: string;
6
+ };
7
+ export type ContactAuth = {
8
+ authToken: string;
9
+ };
10
+ export interface GoogleContacts extends Tool {
11
+ requestAuth(callbackFunctionName: string, callbackContext?: any): Promise<ActivityLink>;
12
+ getContacts(authToken: string): Promise<Contact[]>;
13
+ startSync(authToken: string, callbackFunctionName: string, options?: {
14
+ context?: any;
15
+ }): Promise<void>;
16
+ stopSync(authToken: string): Promise<void>;
17
+ }
18
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,IAAI,EAAE,MAAM,cAAc,CAAC;AAEvD,MAAM,MAAM,OAAO,GAAG;IACpB,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB,CAAC;AAEF,MAAM,MAAM,WAAW,GAAG;IACxB,SAAS,EAAE,MAAM,CAAC;CACnB,CAAC;AAEF,MAAM,WAAW,cAAe,SAAQ,IAAI;IAC1C,WAAW,CACT,oBAAoB,EAAE,MAAM,EAC5B,eAAe,CAAC,EAAE,GAAG,GACpB,OAAO,CAAC,YAAY,CAAC,CAAC;IAEzB,WAAW,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,EAAE,CAAC,CAAC;IAEnD,SAAS,CACP,SAAS,EAAE,MAAM,EACjB,oBAAoB,EAAE,MAAM,EAC5B,OAAO,CAAC,EAAE;QACR,OAAO,CAAC,EAAE,GAAG,CAAC;KACf,GACA,OAAO,CAAC,IAAI,CAAC,CAAC;IAEjB,QAAQ,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CAC5C"}
package/dist/types.js ADDED
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":""}
package/package.json ADDED
@@ -0,0 +1,52 @@
1
+ {
2
+ "name": "@plotday/tool-google-contacts",
3
+ "displayName": "Google Contacts",
4
+ "description": "Sync with Google Contacts",
5
+ "author": "Plot <team@plot.day> (https://plot.day)",
6
+ "license": "MIT",
7
+ "version": "0.1.0-alpha.0",
8
+ "type": "module",
9
+ "main": "./dist/index.js",
10
+ "types": "./dist/index.d.ts",
11
+ "exports": {
12
+ ".": {
13
+ "types": "./dist/index.d.ts",
14
+ "default": "./dist/index.js"
15
+ }
16
+ },
17
+ "files": [
18
+ "dist",
19
+ "README.md",
20
+ "LICENSE"
21
+ ],
22
+ "dependencies": {
23
+ "@plotday/sdk": "^0.1.0-alpha.2"
24
+ },
25
+ "devDependencies": {
26
+ "@cloudflare/workers-types": "^4.0.0",
27
+ "typescript": "^5.9.3"
28
+ },
29
+ "repository": {
30
+ "type": "git",
31
+ "url": "https://github.com/plotday/plot.git",
32
+ "directory": "tools/google-contacts"
33
+ },
34
+ "homepage": "https://plot.day",
35
+ "bugs": {
36
+ "url": "https://github.com/plotday/plot/issues"
37
+ },
38
+ "keywords": [
39
+ "plot",
40
+ "agent",
41
+ "tool",
42
+ "google-contacts",
43
+ "contacts"
44
+ ],
45
+ "publishConfig": {
46
+ "access": "public"
47
+ },
48
+ "scripts": {
49
+ "build": "tsc --project tsconfig.build.json",
50
+ "clean": "rm -rf dist"
51
+ }
52
+ }