@mustafaaksoy41/sharepoint-kit 0.1.2

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.
Files changed (42) hide show
  1. package/README.md +293 -0
  2. package/dist/bin/sp-generate-types.js +784 -0
  3. package/dist/bin/sp-generate-types.js.map +1 -0
  4. package/dist/chunk-2FU6XS6S.cjs +142 -0
  5. package/dist/chunk-2FU6XS6S.cjs.map +1 -0
  6. package/dist/chunk-MLY32NZB.js +131 -0
  7. package/dist/chunk-MLY32NZB.js.map +1 -0
  8. package/dist/chunk-V6K5IFVV.cjs +253 -0
  9. package/dist/chunk-V6K5IFVV.cjs.map +1 -0
  10. package/dist/chunk-VOGWZXJY.js +246 -0
  11. package/dist/chunk-VOGWZXJY.js.map +1 -0
  12. package/dist/cli/index.cjs +516 -0
  13. package/dist/cli/index.cjs.map +1 -0
  14. package/dist/cli/index.d.cts +117 -0
  15. package/dist/cli/index.d.ts +117 -0
  16. package/dist/cli/index.js +505 -0
  17. package/dist/cli/index.js.map +1 -0
  18. package/dist/components/index.cjs +509 -0
  19. package/dist/components/index.cjs.map +1 -0
  20. package/dist/components/index.d.cts +118 -0
  21. package/dist/components/index.d.ts +118 -0
  22. package/dist/components/index.js +494 -0
  23. package/dist/components/index.js.map +1 -0
  24. package/dist/config-loader-Nbidwviq.d.cts +33 -0
  25. package/dist/config-loader-Nbidwviq.d.ts +33 -0
  26. package/dist/hooks/index.cjs +45 -0
  27. package/dist/hooks/index.cjs.map +1 -0
  28. package/dist/hooks/index.d.cts +51 -0
  29. package/dist/hooks/index.d.ts +51 -0
  30. package/dist/hooks/index.js +24 -0
  31. package/dist/hooks/index.js.map +1 -0
  32. package/dist/index.cjs +32 -0
  33. package/dist/index.cjs.map +1 -0
  34. package/dist/index.d.cts +32 -0
  35. package/dist/index.d.ts +32 -0
  36. package/dist/index.js +3 -0
  37. package/dist/index.js.map +1 -0
  38. package/dist/sp-client-A9dM9oYp.d.ts +31 -0
  39. package/dist/sp-client-DTChApOB.d.cts +31 -0
  40. package/dist/types-Dk0jbejG.d.cts +108 -0
  41. package/dist/types-Dk0jbejG.d.ts +108 -0
  42. package/package.json +123 -0
@@ -0,0 +1,505 @@
1
+ import { createSpClient } from '../chunk-VOGWZXJY.js';
2
+ import { existsSync, readFileSync, writeFileSync, mkdirSync } from 'fs';
3
+ import { resolve, extname, join, dirname } from 'path';
4
+ import { ConfidentialClientApplication } from '@azure/msal-node';
5
+ import prompts from 'prompts';
6
+
7
+ async function loadConfig(configPath) {
8
+ const absolutePath = resolve(process.cwd(), configPath);
9
+ if (!existsSync(absolutePath)) {
10
+ throw new Error(`Config file not found: ${absolutePath}`);
11
+ }
12
+ const ext = extname(absolutePath);
13
+ let config;
14
+ if (ext === ".json") {
15
+ const content = readFileSync(absolutePath, "utf-8");
16
+ config = JSON.parse(content);
17
+ } else if (ext === ".ts" || ext === ".js" || ext === ".mjs") {
18
+ const module = await import(absolutePath);
19
+ config = module.default ?? module;
20
+ } else {
21
+ throw new Error(`Unsupported config file format: ${ext}. Use .json, .ts, .js, or .mjs`);
22
+ }
23
+ validateConfig(config);
24
+ return config;
25
+ }
26
+ function validateConfig(config) {
27
+ if (!config || typeof config !== "object") {
28
+ throw new Error("Config must be an object");
29
+ }
30
+ const c = config;
31
+ if (!c.siteId || typeof c.siteId !== "string") {
32
+ throw new Error('Config must have a "siteId" string property');
33
+ }
34
+ if (!Array.isArray(c.contentTypes) || c.contentTypes.length === 0) {
35
+ throw new Error('Config must have a non-empty "contentTypes" array');
36
+ }
37
+ for (const [index, ct] of c.contentTypes.entries()) {
38
+ if (!ct || typeof ct !== "object") {
39
+ throw new Error(`contentTypes[${index}] must be an object`);
40
+ }
41
+ const ctObj = ct;
42
+ if (!ctObj.contentTypeName || typeof ctObj.contentTypeName !== "string") {
43
+ throw new Error(`contentTypes[${index}] must have a "contentTypeName" string property`);
44
+ }
45
+ if (!ctObj.outputType || typeof ctObj.outputType !== "string") {
46
+ throw new Error(`contentTypes[${index}] must have an "outputType" string property`);
47
+ }
48
+ if (ctObj.listId !== void 0 && typeof ctObj.listId !== "string") {
49
+ throw new Error(`contentTypes[${index}].listId must be a string`);
50
+ }
51
+ if (ctObj.listName !== void 0 && typeof ctObj.listName !== "string") {
52
+ throw new Error(`contentTypes[${index}].listName must be a string`);
53
+ }
54
+ const validStrategies = ["interactive", "first", "error", "all"];
55
+ if (ctObj.strategy !== void 0 && !validStrategies.includes(ctObj.strategy)) {
56
+ throw new Error(`contentTypes[${index}].strategy must be one of: ${validStrategies.join(", ")}`);
57
+ }
58
+ }
59
+ if (c.defaultStrategy !== void 0) {
60
+ const validStrategies = ["interactive", "first", "error", "all"];
61
+ if (!validStrategies.includes(c.defaultStrategy)) {
62
+ throw new Error(`defaultStrategy must be one of: ${validStrategies.join(", ")}`);
63
+ }
64
+ }
65
+ }
66
+ var CACHE_FILE = ".sharepoint-cache.json";
67
+ var CacheManager = class {
68
+ constructor(outputDir = "./") {
69
+ this.cachePath = join(outputDir, CACHE_FILE);
70
+ }
71
+ load() {
72
+ if (!existsSync(this.cachePath)) {
73
+ return null;
74
+ }
75
+ try {
76
+ const content = readFileSync(this.cachePath, "utf-8");
77
+ const data = JSON.parse(content);
78
+ if (!data || typeof data !== "object") return null;
79
+ return data;
80
+ } catch {
81
+ return null;
82
+ }
83
+ }
84
+ save(data) {
85
+ writeFileSync(this.cachePath, JSON.stringify(data, null, 2), "utf-8");
86
+ }
87
+ getResolution(contentTypeName) {
88
+ const cache = this.load();
89
+ if (!cache) return null;
90
+ return cache.resolutions[contentTypeName] ?? null;
91
+ }
92
+ saveResolution(siteId, contentTypeName, listId, listName) {
93
+ const cache = this.load() ?? {
94
+ siteId,
95
+ lastUpdated: (/* @__PURE__ */ new Date()).toISOString(),
96
+ lists: [],
97
+ resolutions: {}
98
+ };
99
+ cache.lastUpdated = (/* @__PURE__ */ new Date()).toISOString();
100
+ cache.siteId = siteId;
101
+ cache.resolutions[contentTypeName] = {
102
+ listId,
103
+ listName,
104
+ resolvedAt: (/* @__PURE__ */ new Date()).toISOString()
105
+ };
106
+ this.save(cache);
107
+ }
108
+ saveLists(siteId, lists) {
109
+ const cache = this.load() ?? {
110
+ siteId,
111
+ lastUpdated: (/* @__PURE__ */ new Date()).toISOString(),
112
+ lists: [],
113
+ resolutions: {}
114
+ };
115
+ cache.siteId = siteId;
116
+ cache.lastUpdated = (/* @__PURE__ */ new Date()).toISOString();
117
+ cache.lists = lists;
118
+ this.save(cache);
119
+ }
120
+ clear() {
121
+ if (existsSync(this.cachePath)) {
122
+ writeFileSync(this.cachePath, "{}", "utf-8");
123
+ console.log("Cache cleared.");
124
+ }
125
+ }
126
+ getCachePath() {
127
+ return this.cachePath;
128
+ }
129
+ };
130
+ async function promptListSelection(contentTypeName, lists, strategy = "interactive") {
131
+ if (strategy === "first") {
132
+ console.log(` Using first match: "${lists[0].displayName}" (${lists[0].id})`);
133
+ return [{ listId: lists[0].id, listName: lists[0].displayName }];
134
+ }
135
+ if (strategy === "error") {
136
+ throw new Error(
137
+ `Content type "${contentTypeName}" found in ${lists.length} lists. Please specify listId or listName in config, or use --strategy=all`
138
+ );
139
+ }
140
+ if (strategy === "all") {
141
+ console.log(` Generating types for ALL ${lists.length} lists`);
142
+ return lists.map((list) => ({
143
+ listId: list.id,
144
+ listName: list.displayName
145
+ }));
146
+ }
147
+ console.log(`
148
+ Content type "${contentTypeName}" found in ${lists.length} lists:
149
+ `);
150
+ const choices = [
151
+ ...lists.map((list, index) => ({
152
+ title: `${index + 1}. ${list.displayName} (${list.id})`,
153
+ value: list.id,
154
+ description: `List ID: ${list.id}`
155
+ })),
156
+ {
157
+ title: `Generate types for ALL ${lists.length} lists`,
158
+ value: "__all__",
159
+ description: lists.map((l) => l.displayName).join(", ")
160
+ },
161
+ {
162
+ title: "Skip this content type",
163
+ value: "__skip__",
164
+ description: "Do not generate types for this content type"
165
+ }
166
+ ];
167
+ const response = await prompts({
168
+ type: "select",
169
+ name: "selection",
170
+ message: `Which list(s) should be used for "${contentTypeName}"?`,
171
+ choices,
172
+ initial: 0
173
+ });
174
+ if (!response.selection || response.selection === "__skip__") {
175
+ console.log(` Skipped "${contentTypeName}"
176
+ `);
177
+ return [];
178
+ }
179
+ if (response.selection === "__all__") {
180
+ console.log(` Generating types for all lists
181
+ `);
182
+ return lists.map((list) => ({
183
+ listId: list.id,
184
+ listName: list.displayName
185
+ }));
186
+ }
187
+ const selectedList = lists.find((l) => l.id === response.selection);
188
+ if (!selectedList) {
189
+ throw new Error("Invalid selection");
190
+ }
191
+ console.log(` Selected: ${selectedList.displayName}
192
+ `);
193
+ return [{ listId: response.selection, listName: selectedList.displayName }];
194
+ }
195
+
196
+ // src/cli/list-resolver.ts
197
+ async function resolveContentType(config, siteId, graphClient, cacheManager, globalStrategy, nonInteractive) {
198
+ const strategy = config.strategy ?? globalStrategy;
199
+ if (config.listId) {
200
+ const list = await graphClient.getList({ listId: config.listId });
201
+ console.log(` Found list "${list.displayName}" (${list.id})`);
202
+ return [{
203
+ contentTypeName: config.contentTypeName,
204
+ outputType: config.outputType,
205
+ listId: config.listId,
206
+ listName: list.displayName
207
+ }];
208
+ }
209
+ const cached = cacheManager.getResolution(config.contentTypeName);
210
+ if (cached) {
211
+ console.log(` Using cached resolution for "${config.contentTypeName}": ${cached.listName}`);
212
+ return [{
213
+ contentTypeName: config.contentTypeName,
214
+ outputType: config.outputType,
215
+ listId: cached.listId,
216
+ listName: cached.listName
217
+ }];
218
+ }
219
+ const lists = await graphClient.getLists();
220
+ if (config.listName) {
221
+ const list = lists.find(
222
+ (l) => l.displayName === config.listName || l.name === config.listName
223
+ );
224
+ if (!list) {
225
+ throw new Error(`List "${config.listName}" not found in site "${siteId}"`);
226
+ }
227
+ console.log(` Found list "${list.displayName}" (${list.id})`);
228
+ cacheManager.saveResolution(siteId, config.contentTypeName, list.id, list.displayName);
229
+ return [{
230
+ contentTypeName: config.contentTypeName,
231
+ outputType: config.outputType,
232
+ listId: list.id,
233
+ listName: list.displayName
234
+ }];
235
+ }
236
+ console.log(` Scanning lists for content type "${config.contentTypeName}"...`);
237
+ const matchingLists = [];
238
+ for (const list of lists) {
239
+ try {
240
+ const contentTypes = await graphClient.getListContentTypes({ listId: list.id });
241
+ if (contentTypes.some((ct) => ct.name === config.contentTypeName)) {
242
+ matchingLists.push({
243
+ id: list.id,
244
+ displayName: list.displayName,
245
+ name: list.name
246
+ });
247
+ }
248
+ } catch {
249
+ }
250
+ }
251
+ if (matchingLists.length === 0) {
252
+ throw new Error(
253
+ `Content type "${config.contentTypeName}" not found in any list of site "${siteId}"`
254
+ );
255
+ }
256
+ if (matchingLists.length === 1) {
257
+ const list = matchingLists[0];
258
+ console.log(` Found content type "${config.contentTypeName}" in list "${list.displayName}"`);
259
+ cacheManager.saveResolution(siteId, config.contentTypeName, list.id, list.displayName);
260
+ return [{
261
+ contentTypeName: config.contentTypeName,
262
+ outputType: config.outputType,
263
+ listId: list.id,
264
+ listName: list.displayName
265
+ }];
266
+ }
267
+ const effectiveStrategy = nonInteractive && strategy === "interactive" ? "first" : strategy;
268
+ const selectedLists = await promptListSelection(
269
+ config.contentTypeName,
270
+ matchingLists,
271
+ effectiveStrategy
272
+ );
273
+ if (selectedLists.length === 0) {
274
+ return [];
275
+ }
276
+ if (selectedLists.length === 1) {
277
+ cacheManager.saveResolution(
278
+ siteId,
279
+ config.contentTypeName,
280
+ selectedLists[0].listId,
281
+ selectedLists[0].listName
282
+ );
283
+ }
284
+ if (selectedLists.length > 1) {
285
+ return selectedLists.map((list) => ({
286
+ contentTypeName: config.contentTypeName,
287
+ outputType: `${config.outputType}_${list.listName.replace(/\s+/g, "")}`,
288
+ listId: list.listId,
289
+ listName: list.listName
290
+ }));
291
+ }
292
+ return selectedLists.map((list) => ({
293
+ contentTypeName: config.contentTypeName,
294
+ outputType: config.outputType,
295
+ listId: list.listId,
296
+ listName: list.listName
297
+ }));
298
+ }
299
+
300
+ // src/cli/templates.ts
301
+ function generateFileHeader() {
302
+ return [
303
+ "// Auto-generated by @mustafaaksoy41/sharepoint-kit CLI",
304
+ "// Do not edit manually. Run: npx sp-generate-types --config sharepoint.config.ts",
305
+ ""
306
+ ].join("\n");
307
+ }
308
+ function generateInterface(name, fields) {
309
+ const lines = [];
310
+ lines.push(`export interface ${name} {`);
311
+ for (const field of fields) {
312
+ if (field.description) {
313
+ lines.push(` /** ${field.description} */`);
314
+ }
315
+ const optional = field.required ? "" : "?";
316
+ lines.push(` ${field.name}${optional}: ${field.tsType};`);
317
+ }
318
+ lines.push("}");
319
+ return lines.join("\n");
320
+ }
321
+ function mapSharePointTypeToTs(spType) {
322
+ switch (spType) {
323
+ case "Text":
324
+ case "Note":
325
+ case "Choice":
326
+ return "string";
327
+ case "MultiChoice":
328
+ return "string[]";
329
+ case "Number":
330
+ case "Currency":
331
+ return "number";
332
+ case "Boolean":
333
+ return "boolean";
334
+ case "DateTime":
335
+ return "string";
336
+ case "Lookup":
337
+ return "{ id: number; value: string }";
338
+ case "User":
339
+ return "{ id: number; email: string; displayName: string }";
340
+ case "URL":
341
+ return "{ url: string; description: string }";
342
+ case "Taxonomy":
343
+ return "{ termGuid: string; label: string }";
344
+ case "Calculated":
345
+ return "string | number";
346
+ default:
347
+ return "unknown";
348
+ }
349
+ }
350
+ function sanitizeInterfaceName(name) {
351
+ return name.replace(/[^a-zA-Z0-9_]/g, "").replace(/^(\d)/, "_$1");
352
+ }
353
+
354
+ // src/cli/type-generator.ts
355
+ async function generateTypeScript(inputs, graphClient, options = {}) {
356
+ const { fieldNameMapping = {} } = options;
357
+ const interfaces = [generateFileHeader()];
358
+ for (const input of inputs) {
359
+ console.log(` Generating interface "${input.outputType}" from list "${input.listName}"...`);
360
+ const contentTypes = await graphClient.getListContentTypes({ listId: input.listId });
361
+ const contentType = contentTypes.find((ct) => ct.name === input.contentTypeName);
362
+ let columns;
363
+ if (contentType) {
364
+ columns = await graphClient.getColumns({ contentTypeId: contentType.id });
365
+ } else {
366
+ console.log(` Content type not found by ID, falling back to list columns`);
367
+ columns = await graphClient.getListColumns({ listId: input.listId });
368
+ }
369
+ const writableColumns = columns.filter((col) => !col.readOnly && !isSystemColumn(col.name));
370
+ const fields = writableColumns.map((col) => {
371
+ const mappedName = fieldNameMapping[col.name] ?? col.name;
372
+ const tsType = mapSharePointTypeToTs(col.type);
373
+ return {
374
+ name: mappedName,
375
+ tsType,
376
+ required: col.required,
377
+ description: col.displayName !== col.name ? col.displayName : void 0
378
+ };
379
+ });
380
+ const interfaceName = sanitizeInterfaceName(input.outputType);
381
+ interfaces.push(generateInterface(interfaceName, fields));
382
+ }
383
+ return interfaces.join("\n\n") + "\n";
384
+ }
385
+ function isSystemColumn(name) {
386
+ const systemColumns = /* @__PURE__ */ new Set([
387
+ "ContentType",
388
+ "Modified",
389
+ "Created",
390
+ "Author",
391
+ "Editor",
392
+ "_ModerationComments",
393
+ "_ModerationStatus",
394
+ "FileSystemObjectType",
395
+ "ServerRedirectedEmbedUri",
396
+ "ServerRedirectedEmbedUrl",
397
+ "ID",
398
+ "ContentTypeId",
399
+ "Attachments",
400
+ "GUID",
401
+ "OData__UIVersionString",
402
+ "ComplianceAssetId"
403
+ ]);
404
+ return systemColumns.has(name);
405
+ }
406
+
407
+ // src/cli/generate-types.ts
408
+ async function generateTypes(options) {
409
+ const { configPath, nonInteractive = false, strategy, clearCache = false } = options;
410
+ console.log("\nSharePoint Kit - Type Generator\n");
411
+ const config = await loadConfig(configPath);
412
+ const outputDir = config.options?.outputDir ?? "./generated";
413
+ const outputFile = config.options?.outputFile ?? "sp-types.ts";
414
+ const cacheManager = new CacheManager(outputDir);
415
+ if (clearCache) {
416
+ cacheManager.clear();
417
+ console.log("Cache cleared.\n");
418
+ return;
419
+ }
420
+ const globalStrategy = strategy ?? config.defaultStrategy ?? "interactive";
421
+ console.log(`Site: ${config.siteId}`);
422
+ console.log(`Strategy: ${globalStrategy}`);
423
+ console.log(`Output: ${outputDir}/${outputFile}
424
+ `);
425
+ const getAccessToken = await createTokenProvider(config);
426
+ const client = createSpClient({
427
+ siteId: config.siteId,
428
+ getAccessToken
429
+ });
430
+ console.log("Scanning SharePoint site...\n");
431
+ const allResolved = [];
432
+ for (const ctConfig of config.contentTypes) {
433
+ console.log(`Processing: "${ctConfig.contentTypeName}" -> ${ctConfig.outputType}`);
434
+ try {
435
+ const resolved = await resolveContentType(
436
+ ctConfig,
437
+ config.siteId,
438
+ client,
439
+ cacheManager,
440
+ globalStrategy,
441
+ nonInteractive
442
+ );
443
+ allResolved.push(...resolved);
444
+ } catch (error) {
445
+ const message = error instanceof Error ? error.message : String(error);
446
+ console.error(` Error: ${message}`);
447
+ if (nonInteractive) {
448
+ throw error;
449
+ }
450
+ }
451
+ }
452
+ if (allResolved.length === 0) {
453
+ console.log("\nNo content types resolved. Nothing to generate.\n");
454
+ return;
455
+ }
456
+ console.log(`
457
+ Generating TypeScript interfaces...
458
+ `);
459
+ const tsContent = await generateTypeScript(
460
+ allResolved,
461
+ client,
462
+ { fieldNameMapping: config.options?.fieldNameMapping }
463
+ );
464
+ const outputPath = resolve(process.cwd(), outputDir, outputFile);
465
+ mkdirSync(dirname(outputPath), { recursive: true });
466
+ writeFileSync(outputPath, tsContent, "utf-8");
467
+ console.log(`
468
+ Done! Generated ${allResolved.length} interface(s).`);
469
+ console.log(`Output: ${outputPath}
470
+ `);
471
+ }
472
+ async function createTokenProvider(config) {
473
+ if (!config.tenantId || !config.clientId) {
474
+ throw new Error(
475
+ "tenantId and clientId are required in config for authentication. You can set them via environment variables: SHAREPOINT_TENANT_ID, SHAREPOINT_CLIENT_ID"
476
+ );
477
+ }
478
+ const clientSecret = config.clientSecret ?? process.env.SHAREPOINT_CLIENT_SECRET;
479
+ if (!clientSecret) {
480
+ throw new Error(
481
+ "clientSecret is required for authentication. Set it in config or via SHAREPOINT_CLIENT_SECRET environment variable"
482
+ );
483
+ }
484
+ const msalConfig = {
485
+ auth: {
486
+ clientId: config.clientId,
487
+ authority: `https://login.microsoftonline.com/${config.tenantId}`,
488
+ clientSecret
489
+ }
490
+ };
491
+ const cca = new ConfidentialClientApplication(msalConfig);
492
+ return async () => {
493
+ const result = await cca.acquireTokenByClientCredential({
494
+ scopes: ["https://graph.microsoft.com/.default"]
495
+ });
496
+ if (!result?.accessToken) {
497
+ throw new Error("Failed to acquire access token");
498
+ }
499
+ return result.accessToken;
500
+ };
501
+ }
502
+
503
+ export { CacheManager, generateTypeScript, generateTypes, loadConfig, promptListSelection, resolveContentType };
504
+ //# sourceMappingURL=index.js.map
505
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/cli/config-loader.ts","../../src/cli/cache-manager.ts","../../src/cli/interactive-prompt.ts","../../src/cli/list-resolver.ts","../../src/cli/templates.ts","../../src/cli/type-generator.ts","../../src/cli/generate-types.ts"],"names":["existsSync","readFileSync","resolve","writeFileSync"],"mappings":"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","file":"index.js","sourcesContent":["import { readFileSync, existsSync } from 'fs';\nimport { resolve, extname } from 'path';\n\nexport type ListSelectionStrategy = 'interactive' | 'first' | 'error' | 'all';\n\n/** Microsoft login (MSAL) config for browser/SPA. Use for \"Sign in with Microsoft\". */\nexport interface SpLoginConfig {\n tenantId: string;\n clientId: string;\n redirectUri: string;\n scopes?: string[];\n}\n\nexport interface ContentTypeConfig {\n listId?: string;\n listName?: string;\n contentTypeName: string;\n outputType: string;\n strategy?: ListSelectionStrategy;\n}\n\nexport interface SpKitConfig {\n siteId: string;\n tenantId?: string;\n clientId?: string;\n clientSecret?: string;\n /** Microsoft login config for browser (SPA). Optional; when set, enables \"Sign in with Microsoft\". */\n login?: SpLoginConfig;\n defaultStrategy?: ListSelectionStrategy;\n contentTypes: ContentTypeConfig[];\n options?: {\n outputDir?: string;\n outputFile?: string;\n fieldNameMapping?: Record<string, string>;\n };\n}\n\nexport async function loadConfig(configPath: string): Promise<SpKitConfig> {\n const absolutePath = resolve(process.cwd(), configPath);\n\n if (!existsSync(absolutePath)) {\n throw new Error(`Config file not found: ${absolutePath}`);\n }\n\n const ext = extname(absolutePath);\n let config: SpKitConfig;\n\n if (ext === '.json') {\n const content = readFileSync(absolutePath, 'utf-8');\n config = JSON.parse(content) as SpKitConfig;\n } else if (ext === '.ts' || ext === '.js' || ext === '.mjs') {\n const module = await import(absolutePath);\n config = module.default ?? module;\n } else {\n throw new Error(`Unsupported config file format: ${ext}. Use .json, .ts, .js, or .mjs`);\n }\n\n validateConfig(config);\n return config;\n}\n\nfunction validateConfig(config: unknown): asserts config is SpKitConfig {\n if (!config || typeof config !== 'object') {\n throw new Error('Config must be an object');\n }\n\n const c = config as Record<string, unknown>;\n\n if (!c.siteId || typeof c.siteId !== 'string') {\n throw new Error('Config must have a \"siteId\" string property');\n }\n\n if (!Array.isArray(c.contentTypes) || c.contentTypes.length === 0) {\n throw new Error('Config must have a non-empty \"contentTypes\" array');\n }\n\n for (const [index, ct] of (c.contentTypes as unknown[]).entries()) {\n if (!ct || typeof ct !== 'object') {\n throw new Error(`contentTypes[${index}] must be an object`);\n }\n\n const ctObj = ct as Record<string, unknown>;\n\n if (!ctObj.contentTypeName || typeof ctObj.contentTypeName !== 'string') {\n throw new Error(`contentTypes[${index}] must have a \"contentTypeName\" string property`);\n }\n\n if (!ctObj.outputType || typeof ctObj.outputType !== 'string') {\n throw new Error(`contentTypes[${index}] must have an \"outputType\" string property`);\n }\n\n if (ctObj.listId !== undefined && typeof ctObj.listId !== 'string') {\n throw new Error(`contentTypes[${index}].listId must be a string`);\n }\n\n if (ctObj.listName !== undefined && typeof ctObj.listName !== 'string') {\n throw new Error(`contentTypes[${index}].listName must be a string`);\n }\n\n const validStrategies: ListSelectionStrategy[] = ['interactive', 'first', 'error', 'all'];\n if (ctObj.strategy !== undefined && !validStrategies.includes(ctObj.strategy as ListSelectionStrategy)) {\n throw new Error(`contentTypes[${index}].strategy must be one of: ${validStrategies.join(', ')}`);\n }\n }\n\n if (c.defaultStrategy !== undefined) {\n const validStrategies: ListSelectionStrategy[] = ['interactive', 'first', 'error', 'all'];\n if (!validStrategies.includes(c.defaultStrategy as ListSelectionStrategy)) {\n throw new Error(`defaultStrategy must be one of: ${validStrategies.join(', ')}`);\n }\n }\n}\n","import { readFileSync, writeFileSync, existsSync } from 'fs';\nimport { join } from 'path';\n\nexport interface CacheResolution {\n listId: string;\n listName: string;\n resolvedAt: string;\n}\n\nexport interface CacheData {\n siteId: string;\n lastUpdated: string;\n lists: Array<{\n id: string;\n displayName: string;\n name: string;\n contentTypes: string[];\n }>;\n resolutions: Record<string, CacheResolution>;\n}\n\nconst CACHE_FILE = '.sharepoint-cache.json';\n\nexport class CacheManager {\n private cachePath: string;\n\n constructor(outputDir: string = './') {\n this.cachePath = join(outputDir, CACHE_FILE);\n }\n\n load(): CacheData | null {\n if (!existsSync(this.cachePath)) {\n return null;\n }\n\n try {\n const content = readFileSync(this.cachePath, 'utf-8');\n const data = JSON.parse(content);\n if (!data || typeof data !== 'object') return null;\n return data as CacheData;\n } catch {\n return null;\n }\n }\n\n save(data: CacheData): void {\n writeFileSync(this.cachePath, JSON.stringify(data, null, 2), 'utf-8');\n }\n\n getResolution(contentTypeName: string): CacheResolution | null {\n const cache = this.load();\n if (!cache) return null;\n return cache.resolutions[contentTypeName] ?? null;\n }\n\n saveResolution(\n siteId: string,\n contentTypeName: string,\n listId: string,\n listName: string,\n ): void {\n const cache = this.load() ?? {\n siteId,\n lastUpdated: new Date().toISOString(),\n lists: [],\n resolutions: {},\n };\n\n cache.lastUpdated = new Date().toISOString();\n cache.siteId = siteId;\n cache.resolutions[contentTypeName] = {\n listId,\n listName,\n resolvedAt: new Date().toISOString(),\n };\n\n this.save(cache);\n }\n\n saveLists(\n siteId: string,\n lists: Array<{ id: string; displayName: string; name: string; contentTypes: string[] }>,\n ): void {\n const cache = this.load() ?? {\n siteId,\n lastUpdated: new Date().toISOString(),\n lists: [],\n resolutions: {},\n };\n\n cache.siteId = siteId;\n cache.lastUpdated = new Date().toISOString();\n cache.lists = lists;\n\n this.save(cache);\n }\n\n clear(): void {\n if (existsSync(this.cachePath)) {\n writeFileSync(this.cachePath, '{}', 'utf-8');\n console.log('Cache cleared.');\n }\n }\n\n getCachePath(): string {\n return this.cachePath;\n }\n}\n","import prompts from 'prompts';\nimport type { ListSelectionStrategy } from './config-loader.js';\n\nexport interface ListInfo {\n id: string;\n displayName: string;\n name: string;\n}\n\nexport interface ListSelection {\n listId: string;\n listName: string;\n}\n\nexport async function promptListSelection(\n contentTypeName: string,\n lists: ListInfo[],\n strategy: ListSelectionStrategy = 'interactive',\n): Promise<ListSelection[]> {\n if (strategy === 'first') {\n console.log(` Using first match: \"${lists[0].displayName}\" (${lists[0].id})`);\n return [{ listId: lists[0].id, listName: lists[0].displayName }];\n }\n\n if (strategy === 'error') {\n throw new Error(\n `Content type \"${contentTypeName}\" found in ${lists.length} lists. ` +\n `Please specify listId or listName in config, or use --strategy=all`,\n );\n }\n\n if (strategy === 'all') {\n console.log(` Generating types for ALL ${lists.length} lists`);\n return lists.map((list) => ({\n listId: list.id,\n listName: list.displayName,\n }));\n }\n\n console.log(`\\n Content type \"${contentTypeName}\" found in ${lists.length} lists:\\n`);\n\n const choices = [\n ...lists.map((list, index) => ({\n title: `${index + 1}. ${list.displayName} (${list.id})`,\n value: list.id,\n description: `List ID: ${list.id}`,\n })),\n {\n title: `Generate types for ALL ${lists.length} lists`,\n value: '__all__',\n description: lists.map((l) => l.displayName).join(', '),\n },\n {\n title: 'Skip this content type',\n value: '__skip__',\n description: 'Do not generate types for this content type',\n },\n ];\n\n const response = await prompts({\n type: 'select',\n name: 'selection',\n message: `Which list(s) should be used for \"${contentTypeName}\"?`,\n choices,\n initial: 0,\n });\n\n if (!response.selection || response.selection === '__skip__') {\n console.log(` Skipped \"${contentTypeName}\"\\n`);\n return [];\n }\n\n if (response.selection === '__all__') {\n console.log(` Generating types for all lists\\n`);\n return lists.map((list) => ({\n listId: list.id,\n listName: list.displayName,\n }));\n }\n\n const selectedList = lists.find((l) => l.id === response.selection);\n if (!selectedList) {\n throw new Error('Invalid selection');\n }\n\n console.log(` Selected: ${selectedList.displayName}\\n`);\n return [{ listId: response.selection, listName: selectedList.displayName }];\n}\n","import type { ContentTypeConfig, ListSelectionStrategy } from './config-loader.js';\nimport type { CacheManager } from './cache-manager.js';\nimport { promptListSelection, type ListInfo } from './interactive-prompt.js';\n\nexport interface ResolvedContentType {\n contentTypeName: string;\n outputType: string;\n listId: string;\n listName: string;\n}\n\ninterface GraphClient {\n getLists(): Promise<Array<{ id: string; displayName: string; name: string }>>;\n getList(options: { listId: string }): Promise<{ id: string; displayName: string; name: string }>;\n getListContentTypes(options: { listId: string }): Promise<Array<{ id: string; name: string }>>;\n}\n\nexport async function resolveContentType(\n config: ContentTypeConfig,\n siteId: string,\n graphClient: GraphClient,\n cacheManager: CacheManager,\n globalStrategy: ListSelectionStrategy,\n nonInteractive: boolean,\n): Promise<ResolvedContentType[]> {\n const strategy = config.strategy ?? globalStrategy;\n\n if (config.listId) {\n const list = await graphClient.getList({ listId: config.listId });\n console.log(` Found list \"${list.displayName}\" (${list.id})`);\n return [{\n contentTypeName: config.contentTypeName,\n outputType: config.outputType,\n listId: config.listId,\n listName: list.displayName,\n }];\n }\n\n const cached = cacheManager.getResolution(config.contentTypeName);\n if (cached) {\n console.log(` Using cached resolution for \"${config.contentTypeName}\": ${cached.listName}`);\n return [{\n contentTypeName: config.contentTypeName,\n outputType: config.outputType,\n listId: cached.listId,\n listName: cached.listName,\n }];\n }\n\n const lists = await graphClient.getLists();\n\n if (config.listName) {\n const list = lists.find(\n (l) => l.displayName === config.listName || l.name === config.listName,\n );\n\n if (!list) {\n throw new Error(`List \"${config.listName}\" not found in site \"${siteId}\"`);\n }\n\n console.log(` Found list \"${list.displayName}\" (${list.id})`);\n cacheManager.saveResolution(siteId, config.contentTypeName, list.id, list.displayName);\n\n return [{\n contentTypeName: config.contentTypeName,\n outputType: config.outputType,\n listId: list.id,\n listName: list.displayName,\n }];\n }\n\n console.log(` Scanning lists for content type \"${config.contentTypeName}\"...`);\n const matchingLists: ListInfo[] = [];\n\n for (const list of lists) {\n try {\n const contentTypes = await graphClient.getListContentTypes({ listId: list.id });\n if (contentTypes.some((ct) => ct.name === config.contentTypeName)) {\n matchingLists.push({\n id: list.id,\n displayName: list.displayName,\n name: list.name,\n });\n }\n } catch {\n // Skip lists with access errors\n }\n }\n\n if (matchingLists.length === 0) {\n throw new Error(\n `Content type \"${config.contentTypeName}\" not found in any list of site \"${siteId}\"`,\n );\n }\n\n if (matchingLists.length === 1) {\n const list = matchingLists[0];\n console.log(` Found content type \"${config.contentTypeName}\" in list \"${list.displayName}\"`);\n cacheManager.saveResolution(siteId, config.contentTypeName, list.id, list.displayName);\n\n return [{\n contentTypeName: config.contentTypeName,\n outputType: config.outputType,\n listId: list.id,\n listName: list.displayName,\n }];\n }\n\n const effectiveStrategy = nonInteractive && strategy === 'interactive' ? 'first' : strategy;\n\n const selectedLists = await promptListSelection(\n config.contentTypeName,\n matchingLists,\n effectiveStrategy,\n );\n\n if (selectedLists.length === 0) {\n return [];\n }\n\n if (selectedLists.length === 1) {\n cacheManager.saveResolution(\n siteId,\n config.contentTypeName,\n selectedLists[0].listId,\n selectedLists[0].listName,\n );\n }\n\n if (selectedLists.length > 1) {\n return selectedLists.map((list) => ({\n contentTypeName: config.contentTypeName,\n outputType: `${config.outputType}_${list.listName.replace(/\\s+/g, '')}`,\n listId: list.listId,\n listName: list.listName,\n }));\n }\n\n return selectedLists.map((list) => ({\n contentTypeName: config.contentTypeName,\n outputType: config.outputType,\n listId: list.listId,\n listName: list.listName,\n }));\n}\n","export function generateFileHeader(): string {\n return [\n '// Auto-generated by @mustafaaksoy41/sharepoint-kit CLI',\n '// Do not edit manually. Run: npx sp-generate-types --config sharepoint.config.ts',\n '',\n ].join('\\n');\n}\n\nexport function generateInterface(\n name: string,\n fields: Array<{ name: string; tsType: string; required: boolean; description?: string }>,\n): string {\n const lines: string[] = [];\n lines.push(`export interface ${name} {`);\n\n for (const field of fields) {\n if (field.description) {\n lines.push(` /** ${field.description} */`);\n }\n const optional = field.required ? '' : '?';\n lines.push(` ${field.name}${optional}: ${field.tsType};`);\n }\n\n lines.push('}');\n return lines.join('\\n');\n}\n\nexport function mapSharePointTypeToTs(spType: string): string {\n switch (spType) {\n case 'Text':\n case 'Note':\n case 'Choice':\n return 'string';\n case 'MultiChoice':\n return 'string[]';\n case 'Number':\n case 'Currency':\n return 'number';\n case 'Boolean':\n return 'boolean';\n case 'DateTime':\n return 'string';\n case 'Lookup':\n return '{ id: number; value: string }';\n case 'User':\n return '{ id: number; email: string; displayName: string }';\n case 'URL':\n return '{ url: string; description: string }';\n case 'Taxonomy':\n return '{ termGuid: string; label: string }';\n case 'Calculated':\n return 'string | number';\n default:\n return 'unknown';\n }\n}\n\nexport function sanitizeInterfaceName(name: string): string {\n return name\n .replace(/[^a-zA-Z0-9_]/g, '')\n .replace(/^(\\d)/, '_$1');\n}\n","import type { SpColumn } from '../client/types.js';\nimport { generateFileHeader, generateInterface, mapSharePointTypeToTs, sanitizeInterfaceName } from './templates.js';\n\ninterface GraphClient {\n getColumns(options: { contentTypeId: string }): Promise<SpColumn[]>;\n getListColumns(options: { listId: string }): Promise<SpColumn[]>;\n getContentTypes(options?: { listId?: string }): Promise<Array<{ id: string; name: string }>>;\n getListContentTypes(options: { listId: string }): Promise<Array<{ id: string; name: string }>>;\n}\n\nexport interface TypeGenerationInput {\n contentTypeName: string;\n outputType: string;\n listId: string;\n listName: string;\n}\n\nexport interface TypeGenerationOptions {\n fieldNameMapping?: Record<string, string>;\n}\n\nexport async function generateTypeScript(\n inputs: TypeGenerationInput[],\n graphClient: GraphClient,\n options: TypeGenerationOptions = {},\n): Promise<string> {\n const { fieldNameMapping = {} } = options;\n const interfaces: string[] = [generateFileHeader()];\n\n for (const input of inputs) {\n console.log(` Generating interface \"${input.outputType}\" from list \"${input.listName}\"...`);\n\n const contentTypes = await graphClient.getListContentTypes({ listId: input.listId });\n const contentType = contentTypes.find((ct) => ct.name === input.contentTypeName);\n\n let columns: SpColumn[];\n\n if (contentType) {\n columns = await graphClient.getColumns({ contentTypeId: contentType.id });\n } else {\n console.log(` Content type not found by ID, falling back to list columns`);\n columns = await graphClient.getListColumns({ listId: input.listId });\n }\n\n const writableColumns = columns.filter((col) => !col.readOnly && !isSystemColumn(col.name));\n\n const fields = writableColumns.map((col) => {\n const mappedName = fieldNameMapping[col.name] ?? col.name;\n const tsType = mapSharePointTypeToTs(col.type);\n\n return {\n name: mappedName,\n tsType,\n required: col.required,\n description: col.displayName !== col.name ? col.displayName : undefined,\n };\n });\n\n const interfaceName = sanitizeInterfaceName(input.outputType);\n interfaces.push(generateInterface(interfaceName, fields));\n }\n\n return interfaces.join('\\n\\n') + '\\n';\n}\n\nfunction isSystemColumn(name: string): boolean {\n const systemColumns = new Set([\n 'ContentType',\n 'Modified',\n 'Created',\n 'Author',\n 'Editor',\n '_ModerationComments',\n '_ModerationStatus',\n 'FileSystemObjectType',\n 'ServerRedirectedEmbedUri',\n 'ServerRedirectedEmbedUrl',\n 'ID',\n 'ContentTypeId',\n 'Attachments',\n 'GUID',\n 'OData__UIVersionString',\n 'ComplianceAssetId',\n ]);\n\n return systemColumns.has(name);\n}\n","import { writeFileSync, mkdirSync } from 'fs';\nimport { dirname, resolve } from 'path';\nimport { ConfidentialClientApplication } from '@azure/msal-node';\nimport { loadConfig, type SpKitConfig, type ListSelectionStrategy } from './config-loader.js';\nimport { CacheManager } from './cache-manager.js';\nimport { resolveContentType, type ResolvedContentType } from './list-resolver.js';\nimport { generateTypeScript } from './type-generator.js';\nimport { createSpClient } from '../client/sp-client.js';\n\nexport interface GenerateTypesOptions {\n configPath: string;\n nonInteractive?: boolean;\n strategy?: ListSelectionStrategy;\n clearCache?: boolean;\n updateCache?: boolean;\n}\n\nexport async function generateTypes(options: GenerateTypesOptions): Promise<void> {\n const { configPath, nonInteractive = false, strategy, clearCache = false } = options;\n\n console.log('\\nSharePoint Kit - Type Generator\\n');\n\n const config = await loadConfig(configPath);\n const outputDir = config.options?.outputDir ?? './generated';\n const outputFile = config.options?.outputFile ?? 'sp-types.ts';\n const cacheManager = new CacheManager(outputDir);\n\n if (clearCache) {\n cacheManager.clear();\n console.log('Cache cleared.\\n');\n return;\n }\n\n const globalStrategy = strategy ?? config.defaultStrategy ?? 'interactive';\n\n console.log(`Site: ${config.siteId}`);\n console.log(`Strategy: ${globalStrategy}`);\n console.log(`Output: ${outputDir}/${outputFile}\\n`);\n\n const getAccessToken = await createTokenProvider(config);\n\n const client = createSpClient({\n siteId: config.siteId,\n getAccessToken,\n });\n\n console.log('Scanning SharePoint site...\\n');\n\n const allResolved: ResolvedContentType[] = [];\n\n for (const ctConfig of config.contentTypes) {\n console.log(`Processing: \"${ctConfig.contentTypeName}\" -> ${ctConfig.outputType}`);\n\n try {\n const resolved = await resolveContentType(\n ctConfig,\n config.siteId,\n client,\n cacheManager,\n globalStrategy,\n nonInteractive,\n );\n allResolved.push(...resolved);\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error);\n console.error(` Error: ${message}`);\n\n if (nonInteractive) {\n throw error;\n }\n }\n }\n\n if (allResolved.length === 0) {\n console.log('\\nNo content types resolved. Nothing to generate.\\n');\n return;\n }\n\n console.log(`\\nGenerating TypeScript interfaces...\\n`);\n\n const tsContent = await generateTypeScript(\n allResolved,\n client,\n { fieldNameMapping: config.options?.fieldNameMapping },\n );\n\n const outputPath = resolve(process.cwd(), outputDir, outputFile);\n mkdirSync(dirname(outputPath), { recursive: true });\n writeFileSync(outputPath, tsContent, 'utf-8');\n\n console.log(`\\nDone! Generated ${allResolved.length} interface(s).`);\n console.log(`Output: ${outputPath}\\n`);\n}\n\nasync function createTokenProvider(config: SpKitConfig): Promise<() => Promise<string>> {\n if (!config.tenantId || !config.clientId) {\n throw new Error(\n 'tenantId and clientId are required in config for authentication. ' +\n 'You can set them via environment variables: SHAREPOINT_TENANT_ID, SHAREPOINT_CLIENT_ID',\n );\n }\n\n const clientSecret = config.clientSecret ?? process.env.SHAREPOINT_CLIENT_SECRET;\n\n if (!clientSecret) {\n throw new Error(\n 'clientSecret is required for authentication. ' +\n 'Set it in config or via SHAREPOINT_CLIENT_SECRET environment variable',\n );\n }\n\n const msalConfig = {\n auth: {\n clientId: config.clientId,\n authority: `https://login.microsoftonline.com/${config.tenantId}`,\n clientSecret,\n },\n };\n\n const cca = new ConfidentialClientApplication(msalConfig);\n\n return async () => {\n const result = await cca.acquireTokenByClientCredential({\n scopes: ['https://graph.microsoft.com/.default'],\n });\n\n if (!result?.accessToken) {\n throw new Error('Failed to acquire access token');\n }\n\n return result.accessToken;\n };\n}\n"]}