@bobfrankston/gcards 0.1.2 → 0.1.5

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.
@@ -1,305 +1,305 @@
1
- /**
2
- * Google People API Type Definitions
3
- * Reference: https://developers.google.com/people/api/rest/v1/people
4
- */
5
-
6
- // ============================================================
7
- // Google People API Response Types (from API)
8
- // ============================================================
9
-
10
- export interface GooglePersonMetadata {
11
- sources?: Array<{
12
- type: string; // "CONTACT", "PROFILE", "DOMAIN_PROFILE"
13
- id: string;
14
- etag?: string;
15
- updateTime?: string;
16
- }>;
17
- previousResourceNames?: string[];
18
- linkedPeopleResourceNames?: string[];
19
- deleted?: boolean;
20
- }
21
-
22
- export interface GoogleName {
23
- metadata?: FieldMetadata;
24
- displayName?: string;
25
- displayNameLastFirst?: string;
26
- familyName?: string;
27
- givenName?: string;
28
- middleName?: string;
29
- honorificPrefix?: string;
30
- honorificSuffix?: string;
31
- phoneticFullName?: string;
32
- phoneticFamilyName?: string;
33
- phoneticGivenName?: string;
34
- phoneticMiddleName?: string;
35
- phoneticHonorificPrefix?: string;
36
- phoneticHonorificSuffix?: string;
37
- unstructuredName?: string;
38
- }
39
-
40
- export interface GoogleNickname {
41
- metadata?: FieldMetadata;
42
- value?: string;
43
- type?: string; // "DEFAULT", "MAIDEN_NAME", "INITIALS", etc.
44
- }
45
-
46
- export interface GoogleEmailAddress {
47
- metadata?: FieldMetadata;
48
- value?: string;
49
- type?: string; // "home", "work", "other"
50
- formattedType?: string;
51
- displayName?: string;
52
- }
53
-
54
- export interface GooglePhoneNumber {
55
- metadata?: FieldMetadata;
56
- value?: string;
57
- canonicalForm?: string; // E.164 format
58
- type?: string; // "home", "work", "mobile", etc.
59
- formattedType?: string;
60
- }
61
-
62
- export interface GoogleAddress {
63
- metadata?: FieldMetadata;
64
- formattedValue?: string;
65
- type?: string;
66
- formattedType?: string;
67
- poBox?: string;
68
- streetAddress?: string;
69
- extendedAddress?: string;
70
- city?: string;
71
- region?: string;
72
- postalCode?: string;
73
- country?: string;
74
- countryCode?: string;
75
- }
76
-
77
- export interface GoogleOrganization {
78
- metadata?: FieldMetadata;
79
- type?: string;
80
- formattedType?: string;
81
- name?: string;
82
- department?: string;
83
- title?: string;
84
- jobDescription?: string;
85
- symbol?: string;
86
- phoneticName?: string;
87
- location?: string;
88
- startDate?: GoogleDate;
89
- endDate?: GoogleDate;
90
- current?: boolean;
91
- }
92
-
93
- export interface GoogleBiography {
94
- metadata?: FieldMetadata;
95
- value?: string;
96
- contentType?: string; // "TEXT_PLAIN", "TEXT_HTML"
97
- }
98
-
99
- export interface GoogleUrl {
100
- metadata?: FieldMetadata;
101
- value?: string;
102
- type?: string;
103
- formattedType?: string;
104
- }
105
-
106
- export interface GooglePhoto {
107
- metadata?: FieldMetadata;
108
- url?: string;
109
- default?: boolean;
110
- }
111
-
112
- export interface GoogleBirthday {
113
- metadata?: FieldMetadata;
114
- date?: GoogleDate;
115
- text?: string;
116
- }
117
-
118
- export interface GoogleDate {
119
- year?: number;
120
- month?: number;
121
- day?: number;
122
- }
123
-
124
- export interface GoogleEvent {
125
- metadata?: FieldMetadata;
126
- date?: GoogleDate;
127
- type?: string;
128
- formattedType?: string;
129
- }
130
-
131
- export interface GoogleRelation {
132
- metadata?: FieldMetadata;
133
- person?: string;
134
- type?: string;
135
- formattedType?: string;
136
- }
137
-
138
- export interface GoogleMembership {
139
- metadata?: FieldMetadata;
140
- contactGroupMembership?: {
141
- contactGroupId?: string;
142
- contactGroupResourceName?: string;
143
- };
144
- domainMembership?: {
145
- inViewerDomain?: boolean;
146
- };
147
- }
148
-
149
- export interface GoogleUserDefined {
150
- metadata?: FieldMetadata;
151
- key?: string;
152
- value?: string;
153
- }
154
-
155
- export interface FieldMetadata {
156
- primary?: boolean;
157
- verified?: boolean;
158
- source?: {
159
- type: string;
160
- id: string;
161
- };
162
- sourcePrimary?: boolean;
163
- }
164
-
165
- /**
166
- * Full Google Person resource as returned by People API
167
- */
168
- export interface GooglePerson {
169
- resourceName: string; // e.g., "people/c1234567890"
170
- etag?: string;
171
- metadata?: GooglePersonMetadata;
172
- names?: GoogleName[];
173
- nicknames?: GoogleNickname[];
174
- photos?: GooglePhoto[];
175
- birthdays?: GoogleBirthday[];
176
- addresses?: GoogleAddress[];
177
- emailAddresses?: GoogleEmailAddress[];
178
- phoneNumbers?: GooglePhoneNumber[];
179
- organizations?: GoogleOrganization[];
180
- biographies?: GoogleBiography[];
181
- urls?: GoogleUrl[];
182
- events?: GoogleEvent[];
183
- relations?: GoogleRelation[];
184
- memberships?: GoogleMembership[];
185
- userDefined?: GoogleUserDefined[];
186
- imClients?: Array<{
187
- metadata?: FieldMetadata;
188
- username?: string;
189
- type?: string;
190
- formattedType?: string;
191
- protocol?: string;
192
- formattedProtocol?: string;
193
- }>;
194
- sipAddresses?: Array<{
195
- metadata?: FieldMetadata;
196
- value?: string;
197
- type?: string;
198
- formattedType?: string;
199
- }>;
200
- fileAses?: Array<{
201
- metadata?: FieldMetadata;
202
- value?: string;
203
- }>;
204
- }
205
-
206
- export interface GoogleConnectionsResponse {
207
- connections?: GooglePerson[];
208
- nextPageToken?: string;
209
- nextSyncToken?: string;
210
- totalPeople?: number;
211
- totalItems?: number;
212
- }
213
-
214
- // ============================================================
215
- // Local Simplified Format (for analysis/cleanup)
216
- // ============================================================
217
-
218
- export interface LocalContact {
219
- // Identity & reconciliation
220
- resourceName: string; // From Google - used for updates
221
- etag?: string; // For conflict detection
222
-
223
- // Core identity
224
- displayName: string;
225
- givenName?: string;
226
- familyName?: string;
227
- nickname?: string;
228
-
229
- // Contact info (flattened, typed arrays)
230
- emails: Array<{ value: string; type?: string; primary?: boolean }>;
231
- phones: Array<{ value: string; type?: string; primary?: boolean }>;
232
- addresses: Array<{
233
- formatted?: string;
234
- street?: string;
235
- city?: string;
236
- region?: string;
237
- postalCode?: string;
238
- country?: string;
239
- type?: string;
240
- }>;
241
-
242
- // Professional
243
- organizations: Array<{
244
- name?: string;
245
- title?: string;
246
- department?: string;
247
- }>;
248
-
249
- // Social/web
250
- urls: Array<{ value: string; type?: string }>;
251
-
252
- // Dates
253
- birthday?: { year?: number; month?: number; day?: number };
254
-
255
- // Notes
256
- notes?: string;
257
-
258
- // Groups
259
- groups: string[]; // contactGroupResourceNames
260
-
261
- // Metadata for cleanup
262
- _meta: {
263
- sourceType: string; // "CONTACT", "PROFILE", etc.
264
- updateTime?: string;
265
- isTestEntry?: boolean; // Flagged as test (m-XXXX@bob.ma pattern)
266
- duplicateOf?: string[]; // resourceNames of potential duplicates
267
- mergeConfidence?: number; // 0-1 confidence for merge candidates
268
- };
269
- }
270
-
271
- // ============================================================
272
- // Cleanup Analysis Types
273
- // ============================================================
274
-
275
- export interface DuplicateGroup {
276
- primary: string; // resourceName of "best" contact
277
- duplicates: string[]; // resourceNames to merge into primary
278
- confidence: number; // 0-1 merge confidence
279
- matchReasons: string[]; // Why these are considered duplicates
280
- }
281
-
282
- export interface CleanupReport {
283
- totalContacts: number;
284
- testEntries: LocalContact[]; // To be deleted
285
- duplicateGroups: DuplicateGroup[];
286
- emptyContacts: LocalContact[]; // No useful info
287
- suggestions: string[]; // Human-readable recommendations
288
- }
289
-
290
- // ============================================================
291
- // Deletion Logging (for tracking cleanup history)
292
- // ============================================================
293
-
294
- export interface DeletionRecord {
295
- resourceName: string;
296
- displayName: string;
297
- reason: string; // "test_entry", "duplicate_of:people/cXXX", "empty", etc.
298
- deletedAt: string; // ISO timestamp
299
- originalData: LocalContact; // Snapshot before deletion
300
- }
301
-
302
- export interface DeletionLog {
303
- deletions: DeletionRecord[];
304
- lastUpdated: string; // ISO timestamp
305
- }
1
+ /**
2
+ * Google People API Type Definitions
3
+ * Reference: https://developers.google.com/people/api/rest/v1/people
4
+ */
5
+
6
+ // ============================================================
7
+ // Google People API Response Types (from API)
8
+ // ============================================================
9
+
10
+ export interface GooglePersonMetadata {
11
+ sources?: Array<{
12
+ type: string; // "CONTACT", "PROFILE", "DOMAIN_PROFILE"
13
+ id: string;
14
+ etag?: string;
15
+ updateTime?: string;
16
+ }>;
17
+ previousResourceNames?: string[];
18
+ linkedPeopleResourceNames?: string[];
19
+ deleted?: boolean;
20
+ }
21
+
22
+ export interface GoogleName {
23
+ metadata?: FieldMetadata;
24
+ displayName?: string;
25
+ displayNameLastFirst?: string;
26
+ familyName?: string;
27
+ givenName?: string;
28
+ middleName?: string;
29
+ honorificPrefix?: string;
30
+ honorificSuffix?: string;
31
+ phoneticFullName?: string;
32
+ phoneticFamilyName?: string;
33
+ phoneticGivenName?: string;
34
+ phoneticMiddleName?: string;
35
+ phoneticHonorificPrefix?: string;
36
+ phoneticHonorificSuffix?: string;
37
+ unstructuredName?: string;
38
+ }
39
+
40
+ export interface GoogleNickname {
41
+ metadata?: FieldMetadata;
42
+ value?: string;
43
+ type?: string; // "DEFAULT", "MAIDEN_NAME", "INITIALS", etc.
44
+ }
45
+
46
+ export interface GoogleEmailAddress {
47
+ metadata?: FieldMetadata;
48
+ value?: string;
49
+ type?: string; // "home", "work", "other"
50
+ formattedType?: string;
51
+ displayName?: string;
52
+ }
53
+
54
+ export interface GooglePhoneNumber {
55
+ metadata?: FieldMetadata;
56
+ value?: string;
57
+ canonicalForm?: string; // E.164 format
58
+ type?: string; // "home", "work", "mobile", etc.
59
+ formattedType?: string;
60
+ }
61
+
62
+ export interface GoogleAddress {
63
+ metadata?: FieldMetadata;
64
+ formattedValue?: string;
65
+ type?: string;
66
+ formattedType?: string;
67
+ poBox?: string;
68
+ streetAddress?: string;
69
+ extendedAddress?: string;
70
+ city?: string;
71
+ region?: string;
72
+ postalCode?: string;
73
+ country?: string;
74
+ countryCode?: string;
75
+ }
76
+
77
+ export interface GoogleOrganization {
78
+ metadata?: FieldMetadata;
79
+ type?: string;
80
+ formattedType?: string;
81
+ name?: string;
82
+ department?: string;
83
+ title?: string;
84
+ jobDescription?: string;
85
+ symbol?: string;
86
+ phoneticName?: string;
87
+ location?: string;
88
+ startDate?: GoogleDate;
89
+ endDate?: GoogleDate;
90
+ current?: boolean;
91
+ }
92
+
93
+ export interface GoogleBiography {
94
+ metadata?: FieldMetadata;
95
+ value?: string;
96
+ contentType?: string; // "TEXT_PLAIN", "TEXT_HTML"
97
+ }
98
+
99
+ export interface GoogleUrl {
100
+ metadata?: FieldMetadata;
101
+ value?: string;
102
+ type?: string;
103
+ formattedType?: string;
104
+ }
105
+
106
+ export interface GooglePhoto {
107
+ metadata?: FieldMetadata;
108
+ url?: string;
109
+ default?: boolean;
110
+ }
111
+
112
+ export interface GoogleBirthday {
113
+ metadata?: FieldMetadata;
114
+ date?: GoogleDate;
115
+ text?: string;
116
+ }
117
+
118
+ export interface GoogleDate {
119
+ year?: number;
120
+ month?: number;
121
+ day?: number;
122
+ }
123
+
124
+ export interface GoogleEvent {
125
+ metadata?: FieldMetadata;
126
+ date?: GoogleDate;
127
+ type?: string;
128
+ formattedType?: string;
129
+ }
130
+
131
+ export interface GoogleRelation {
132
+ metadata?: FieldMetadata;
133
+ person?: string;
134
+ type?: string;
135
+ formattedType?: string;
136
+ }
137
+
138
+ export interface GoogleMembership {
139
+ metadata?: FieldMetadata;
140
+ contactGroupMembership?: {
141
+ contactGroupId?: string;
142
+ contactGroupResourceName?: string;
143
+ };
144
+ domainMembership?: {
145
+ inViewerDomain?: boolean;
146
+ };
147
+ }
148
+
149
+ export interface GoogleUserDefined {
150
+ metadata?: FieldMetadata;
151
+ key?: string;
152
+ value?: string;
153
+ }
154
+
155
+ export interface FieldMetadata {
156
+ primary?: boolean;
157
+ verified?: boolean;
158
+ source?: {
159
+ type: string;
160
+ id: string;
161
+ };
162
+ sourcePrimary?: boolean;
163
+ }
164
+
165
+ /**
166
+ * Full Google Person resource as returned by People API
167
+ */
168
+ export interface GooglePerson {
169
+ resourceName: string; // e.g., "people/c1234567890"
170
+ etag?: string;
171
+ metadata?: GooglePersonMetadata;
172
+ names?: GoogleName[];
173
+ nicknames?: GoogleNickname[];
174
+ photos?: GooglePhoto[];
175
+ birthdays?: GoogleBirthday[];
176
+ addresses?: GoogleAddress[];
177
+ emailAddresses?: GoogleEmailAddress[];
178
+ phoneNumbers?: GooglePhoneNumber[];
179
+ organizations?: GoogleOrganization[];
180
+ biographies?: GoogleBiography[];
181
+ urls?: GoogleUrl[];
182
+ events?: GoogleEvent[];
183
+ relations?: GoogleRelation[];
184
+ memberships?: GoogleMembership[];
185
+ userDefined?: GoogleUserDefined[];
186
+ imClients?: Array<{
187
+ metadata?: FieldMetadata;
188
+ username?: string;
189
+ type?: string;
190
+ formattedType?: string;
191
+ protocol?: string;
192
+ formattedProtocol?: string;
193
+ }>;
194
+ sipAddresses?: Array<{
195
+ metadata?: FieldMetadata;
196
+ value?: string;
197
+ type?: string;
198
+ formattedType?: string;
199
+ }>;
200
+ fileAses?: Array<{
201
+ metadata?: FieldMetadata;
202
+ value?: string;
203
+ }>;
204
+ }
205
+
206
+ export interface GoogleConnectionsResponse {
207
+ connections?: GooglePerson[];
208
+ nextPageToken?: string;
209
+ nextSyncToken?: string;
210
+ totalPeople?: number;
211
+ totalItems?: number;
212
+ }
213
+
214
+ // ============================================================
215
+ // Local Simplified Format (for analysis/cleanup)
216
+ // ============================================================
217
+
218
+ export interface LocalContact {
219
+ // Identity & reconciliation
220
+ resourceName: string; // From Google - used for updates
221
+ etag?: string; // For conflict detection
222
+
223
+ // Core identity
224
+ displayName: string;
225
+ givenName?: string;
226
+ familyName?: string;
227
+ nickname?: string;
228
+
229
+ // Contact info (flattened, typed arrays)
230
+ emails: Array<{ value: string; type?: string; primary?: boolean }>;
231
+ phones: Array<{ value: string; type?: string; primary?: boolean }>;
232
+ addresses: Array<{
233
+ formatted?: string;
234
+ street?: string;
235
+ city?: string;
236
+ region?: string;
237
+ postalCode?: string;
238
+ country?: string;
239
+ type?: string;
240
+ }>;
241
+
242
+ // Professional
243
+ organizations: Array<{
244
+ name?: string;
245
+ title?: string;
246
+ department?: string;
247
+ }>;
248
+
249
+ // Social/web
250
+ urls: Array<{ value: string; type?: string }>;
251
+
252
+ // Dates
253
+ birthday?: { year?: number; month?: number; day?: number };
254
+
255
+ // Notes
256
+ notes?: string;
257
+
258
+ // Groups
259
+ groups: string[]; // contactGroupResourceNames
260
+
261
+ // Metadata for cleanup
262
+ _meta: {
263
+ sourceType: string; // "CONTACT", "PROFILE", etc.
264
+ updateTime?: string;
265
+ isTestEntry?: boolean; // Flagged as test (m-XXXX@bob.ma pattern)
266
+ duplicateOf?: string[]; // resourceNames of potential duplicates
267
+ mergeConfidence?: number; // 0-1 confidence for merge candidates
268
+ };
269
+ }
270
+
271
+ // ============================================================
272
+ // Cleanup Analysis Types
273
+ // ============================================================
274
+
275
+ export interface DuplicateGroup {
276
+ primary: string; // resourceName of "best" contact
277
+ duplicates: string[]; // resourceNames to merge into primary
278
+ confidence: number; // 0-1 merge confidence
279
+ matchReasons: string[]; // Why these are considered duplicates
280
+ }
281
+
282
+ export interface CleanupReport {
283
+ totalContacts: number;
284
+ testEntries: LocalContact[]; // To be deleted
285
+ duplicateGroups: DuplicateGroup[];
286
+ emptyContacts: LocalContact[]; // No useful info
287
+ suggestions: string[]; // Human-readable recommendations
288
+ }
289
+
290
+ // ============================================================
291
+ // Deletion Logging (for tracking cleanup history)
292
+ // ============================================================
293
+
294
+ export interface DeletionRecord {
295
+ resourceName: string;
296
+ displayName: string;
297
+ reason: string; // "test_entry", "duplicate_of:people/cXXX", "empty", etc.
298
+ deletedAt: string; // ISO timestamp
299
+ originalData: LocalContact; // Snapshot before deletion
300
+ }
301
+
302
+ export interface DeletionLog {
303
+ deletions: DeletionRecord[];
304
+ lastUpdated: string; // ISO timestamp
305
+ }
package/package.json CHANGED
@@ -1,11 +1,12 @@
1
1
  {
2
2
  "name": "@bobfrankston/gcards",
3
- "version": "0.1.2",
3
+ "version": "0.1.5",
4
4
  "description": "Google Contacts cleanup and management tool",
5
5
  "type": "module",
6
6
  "main": "gcards.ts",
7
7
  "bin": {
8
- "gcards": "gcards.ts"
8
+ "gcards": "gcards.ts",
9
+ "gfix": "gfix.ts"
9
10
  },
10
11
  "repository": {
11
12
  "type": "git",
@@ -16,7 +17,7 @@
16
17
  "prerelease:local": "git add -A && (git diff-index --quiet HEAD || git commit -m \"Pre-release commit\")",
17
18
  "preversion": "npm run check && git add -A",
18
19
  "postversion": "git push && git push --tags",
19
- "release": "npm run prerelease:local && npm version patch && npm publish --access public"
20
+ "release": "npm whoami && npm run prerelease:local && npm version patch && npm publish --access public"
20
21
  },
21
22
  "keywords": [
22
23
  "google",
@@ -27,7 +28,8 @@
27
28
  "author": "Bob Frankston",
28
29
  "license": "MIT",
29
30
  "devDependencies": {
30
- "@types/node": "^22.10.1"
31
+ "@types/node": "^22.10.1",
32
+ "tsx": "^4.21.0"
31
33
  },
32
34
  "dependencies": {
33
35
  "@bobfrankston/miscassists": "file:../../../projects/NodeJS/miscassists"