@lindle/sharepoint_requests 0.1.11 → 0.1.13

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 (41) hide show
  1. package/dist/index.d.ts +4 -2
  2. package/dist/root/index.d.ts +17 -217
  3. package/dist/root/instance.d.ts +2 -2
  4. package/dist/root/internal/context.d.ts +9 -0
  5. package/dist/root/internal/digest.d.ts +2 -0
  6. package/dist/root/internal/emailRequests.d.ts +10 -0
  7. package/dist/root/internal/listRequests/createAttachment.d.ts +3 -0
  8. package/dist/root/internal/listRequests/createListItem.d.ts +3 -0
  9. package/dist/root/internal/listRequests/deleteItem.d.ts +3 -0
  10. package/dist/root/internal/listRequests/getFiles.d.ts +8 -0
  11. package/dist/root/internal/listRequests/getListItems.d.ts +8 -0
  12. package/dist/root/internal/listRequests/getOnly.d.ts +3 -0
  13. package/dist/root/internal/listRequests/index.d.ts +7 -0
  14. package/dist/root/internal/listRequests/updateListItem.d.ts +3 -0
  15. package/dist/root/internal/odata.d.ts +5 -0
  16. package/dist/root/internal/userRequests.d.ts +15 -0
  17. package/dist/sharepoint_requests.cjs.development.js +621 -775
  18. package/dist/sharepoint_requests.cjs.development.js.map +1 -1
  19. package/dist/sharepoint_requests.cjs.production.min.js +1 -1
  20. package/dist/sharepoint_requests.cjs.production.min.js.map +1 -1
  21. package/dist/sharepoint_requests.esm.js +620 -775
  22. package/dist/sharepoint_requests.esm.js.map +1 -1
  23. package/dist/types.d.ts +38 -7
  24. package/package.json +1 -1
  25. package/src/index.ts +37 -28
  26. package/src/root/index.ts +201 -600
  27. package/src/root/instance.ts +22 -13
  28. package/src/root/internal/context.ts +10 -0
  29. package/src/root/internal/digest.ts +22 -0
  30. package/src/root/internal/emailRequests.ts +45 -0
  31. package/src/root/internal/listRequests/createAttachment.ts +18 -0
  32. package/src/root/internal/listRequests/createListItem.ts +36 -0
  33. package/src/root/internal/listRequests/deleteItem.ts +10 -0
  34. package/src/root/internal/listRequests/getFiles.ts +31 -0
  35. package/src/root/internal/listRequests/getListItems.ts +50 -0
  36. package/src/root/internal/listRequests/getOnly.ts +18 -0
  37. package/src/root/internal/listRequests/index.ts +7 -0
  38. package/src/root/internal/listRequests/updateListItem.ts +32 -0
  39. package/src/root/internal/odata.ts +36 -0
  40. package/src/root/internal/userRequests.ts +109 -0
  41. package/src/types.ts +76 -36
@@ -1,19 +1,28 @@
1
- import axios, { CreateAxiosDefaults } from 'axios';
1
+ import axios, { AxiosHeaders, CreateAxiosDefaults as AxiosConfig } from 'axios';
2
+
3
+ const defaultConfig: AxiosConfig = {
4
+ headers: {
5
+ Accept: 'application/json; odata=verbose',
6
+ 'Content-Type': 'application/json; odata=verbose',
7
+ },
8
+ timeout: 15000,
9
+ withCredentials: true,
10
+ };
11
+
12
+ export const instance = (baseURL: string, config?: AxiosConfig) => {
13
+ const userHeaders =
14
+ config?.headers instanceof AxiosHeaders
15
+ ? config.headers.toJSON()
16
+ : config?.headers ?? {};
2
17
 
3
- export const instance = (
4
- baseURL: string,
5
- config: CreateAxiosDefaults = {
6
- headers: {
7
- Accept: 'application/json; odata=verbose',
8
- 'Content-Type': 'application/json; odata=verbose',
9
- },
10
- timeout: 15000,
11
- withCredentials: true,
12
- }
13
- ) => {
14
18
  return axios.create({
15
- baseURL: baseURL,
19
+ ...defaultConfig,
16
20
  ...config,
21
+ baseURL,
22
+ headers: {
23
+ ...defaultConfig.headers,
24
+ ...userHeaders,
25
+ },
17
26
  });
18
27
  };
19
28
 
@@ -0,0 +1,10 @@
1
+ import type { AxiosInstance } from 'axios';
2
+ import type { SHAREPOINT_VER } from '../../types';
3
+
4
+ export interface RequestContext<V extends SHAREPOINT_VER = '2013'> {
5
+ instance: AxiosInstance;
6
+ baseURL: string;
7
+ endpoint: string;
8
+ listName: string;
9
+ sharepointVersion: V;
10
+ }
@@ -0,0 +1,22 @@
1
+ import type { AxiosInstance } from 'axios';
2
+
3
+ export async function fetchDigest(
4
+ instance: AxiosInstance,
5
+ baseURL: string
6
+ ): Promise<string> {
7
+ try {
8
+ const response = await instance.post(`${baseURL}_api/contextinfo`);
9
+
10
+ const formDigestValue =
11
+ response.data?.d?.GetContextWebInformation?.FormDigestValue;
12
+
13
+ if (!formDigestValue) {
14
+ throw new Error('Invalid response structure: Missing FormDigestValue');
15
+ }
16
+
17
+ return formDigestValue;
18
+ } catch (error) {
19
+ console.error('Failed to retrieve the Form Digest Value:', error);
20
+ throw new Error(`Error retrieving Form Digest Value`);
21
+ }
22
+ }
@@ -0,0 +1,45 @@
1
+ import type { AxiosResponse } from 'axios';
2
+ import type { EmailProps } from '../../types';
3
+ import { fetchDigest } from './digest';
4
+ import type { RequestContext } from './context';
5
+
6
+ type SendEmailResponse = AxiosResponse<{
7
+ d: {
8
+ SendEmail: null;
9
+ };
10
+ }>;
11
+
12
+ export async function sendEmail(
13
+ context: RequestContext,
14
+ { From, To, Subject, Body }: EmailProps
15
+ ): Promise<SendEmailResponse> {
16
+ const httpRequest = '_api/SP.Utilities.Utility.SendEmail';
17
+
18
+ const response = await context.instance({
19
+ url: httpRequest,
20
+ method: 'POST',
21
+ headers: {
22
+ 'X-RequestDigest': await fetchDigest(
23
+ context.instance,
24
+ context.baseURL
25
+ ),
26
+ 'X-Http-Method': 'POST',
27
+ 'Content-Type': 'application/json;odata=verbose',
28
+ },
29
+ data: JSON.stringify({
30
+ properties: {
31
+ __metadata: {
32
+ type: 'SP.Utilities.EmailProperties',
33
+ },
34
+ From,
35
+ To: {
36
+ results: Array.isArray(To) ? To : [To],
37
+ },
38
+ Body,
39
+ Subject,
40
+ },
41
+ }),
42
+ });
43
+
44
+ return response;
45
+ }
@@ -0,0 +1,18 @@
1
+ import type { CreateFileProps, SHAREPOINT_VER } from '../../../types';
2
+ import { fetchDigest } from '../digest';
3
+ import type { RequestContext } from '../context';
4
+
5
+ export async function createAttachment<V extends SHAREPOINT_VER = '2013'>(
6
+ context: RequestContext<V>,
7
+ { file, itemId }: CreateFileProps
8
+ ) {
9
+ const requestUrl = `_api/lists/getbytitle('${context.listName}')/items(${itemId})/AttachmentFiles/add(FileName='${file.name}')`;
10
+ const response = await context.instance.post(requestUrl, file, {
11
+ headers: {
12
+ 'X-RequestDigest': await fetchDigest(context.instance, context.baseURL),
13
+ },
14
+ withCredentials: true,
15
+ });
16
+
17
+ return response;
18
+ }
@@ -0,0 +1,36 @@
1
+ import type { ListData, SHAREPOINT_VER } from '../../../types';
2
+ import { fetchDigest } from '../digest';
3
+ import type { RequestContext } from '../context';
4
+
5
+ function transformArraysToEdmStrings(data: ListData) {
6
+ for (const key in data) {
7
+ if (Array.isArray(data[key])) {
8
+ data[key] = {
9
+ __metadata: { type: 'Collection(Edm.String)' },
10
+ results: data[key],
11
+ };
12
+ }
13
+ }
14
+ }
15
+
16
+ export async function createListItem<V extends SHAREPOINT_VER = '2013'>(
17
+ context: RequestContext<V>,
18
+ listData: ListData
19
+ ) {
20
+ transformArraysToEdmStrings(listData);
21
+ listData.__metadata = {
22
+ type: `SP.Data.${context.listName}ListItem`,
23
+ };
24
+
25
+ const response = await context.instance({
26
+ url: context.endpoint,
27
+ method: 'POST',
28
+ data: JSON.stringify(listData),
29
+ headers: {
30
+ 'X-RequestDigest': await fetchDigest(context.instance, context.baseURL),
31
+ 'IF-MATCH': '*',
32
+ },
33
+ });
34
+
35
+ return response;
36
+ }
@@ -0,0 +1,10 @@
1
+ import type { SHAREPOINT_VER } from '../../../types';
2
+ import type { RequestContext } from '../context';
3
+
4
+ export async function deleteItem<V extends SHAREPOINT_VER = '2013'>(
5
+ context: RequestContext<V>,
6
+ id: number | string
7
+ ) {
8
+ const response = await context.instance.delete(`${context.endpoint}(${id})`);
9
+ return response;
10
+ }
@@ -0,0 +1,31 @@
1
+ import type { Folder_Options, SHAREPOINT_VER } from '../../../types';
2
+ import { appendParamsToUrl, buildODataParams } from '../odata';
3
+ import type { RequestContext } from '../context';
4
+
5
+ export async function getFiles<
6
+ T,
7
+ V extends SHAREPOINT_VER = '2013'
8
+ >(
9
+ context: RequestContext<V>,
10
+ options?: Folder_Options<T>
11
+ ) {
12
+ const params = buildODataParams(options, ',');
13
+ const url = new URL(context.endpoint, context.instance.defaults.baseURL);
14
+
15
+ appendParamsToUrl(url, params);
16
+
17
+ const response = await context.instance.request({
18
+ url: context.endpoint,
19
+ method: 'GET',
20
+ params,
21
+ });
22
+
23
+ const data =
24
+ options?.limit || !response.data.d.results
25
+ ? response.data.d
26
+ : response.data.d.results;
27
+
28
+ const meta = { url };
29
+
30
+ return { data, meta };
31
+ }
@@ -0,0 +1,50 @@
1
+ import type { Options, SPItem, SHAREPOINT_VER } from '../../../types';
2
+ import { appendParamsToUrl, buildODataParams } from '../odata';
3
+ import type { RequestContext } from '../context';
4
+
5
+ export async function getListItems<
6
+ K,
7
+ V extends SHAREPOINT_VER = '2013'
8
+ >(
9
+ context: RequestContext<V>,
10
+ options?: Options<K, V>
11
+ ): Promise<{ data: (K & Partial<SPItem<V>>)[]; meta: { url: URL } }> {
12
+ const params = buildODataParams(options, ' ');
13
+
14
+ const url = new URL(context.endpoint, context.instance.defaults.baseURL);
15
+ appendParamsToUrl(url, params);
16
+
17
+ const response = await context.instance.request({
18
+ url: context.endpoint,
19
+ method: 'GET',
20
+ params,
21
+ });
22
+
23
+ const rawData = response.data?.d?.results ?? response.data?.d ?? response.data;
24
+ const cols = options?.cols;
25
+ const keys = cols
26
+ ? (Array.isArray(cols) ? cols : [cols]).filter(Boolean)
27
+ : undefined;
28
+
29
+ const filterItem = (item: unknown) => {
30
+ if (!keys || !item || typeof item !== 'object') {
31
+ return item;
32
+ }
33
+
34
+ return keys.reduce<Record<string, unknown>>((acc, key) => {
35
+ if (key in item) {
36
+ acc[key] = (item as Record<string, unknown>)[key];
37
+ }
38
+
39
+ return acc;
40
+ }, {});
41
+ };
42
+
43
+ const data = Array.isArray(rawData)
44
+ ? rawData.map(filterItem)
45
+ : filterItem(rawData);
46
+
47
+ const meta = { url };
48
+
49
+ return { data: data as (K & Partial<SPItem<V>>)[], meta };
50
+ }
@@ -0,0 +1,18 @@
1
+ import type { AxiosInstance } from 'axios';
2
+ import type { Options, SHAREPOINT_VER } from '../../../types';
3
+ import { buildODataParams } from '../odata';
4
+
5
+ export async function getOnly<
6
+ T,
7
+ V extends SHAREPOINT_VER = '2013'
8
+ >(
9
+ instance: AxiosInstance,
10
+ endpoint: string,
11
+ options?: Options<T, V>
12
+ ) {
13
+ const params = buildODataParams(options, ',');
14
+ const { data } = await instance.get(endpoint, { params });
15
+ if (data) {
16
+ return data.d.results ? data.d.results : data.d;
17
+ }
18
+ }
@@ -0,0 +1,7 @@
1
+ export { createListItem } from './createListItem';
2
+ export { createAttachment } from './createAttachment';
3
+ export { deleteItem } from './deleteItem';
4
+ export { getFiles } from './getFiles';
5
+ export { getListItems } from './getListItems';
6
+ export { getOnly } from './getOnly';
7
+ export { updateListItem } from './updateListItem';
@@ -0,0 +1,32 @@
1
+ import type { ListData, SHAREPOINT_VER } from '../../../types';
2
+ import { fetchDigest } from '../digest';
3
+ import type { RequestContext } from '../context';
4
+
5
+ export async function updateListItem<V extends SHAREPOINT_VER = '2013'>(
6
+ context: RequestContext<V>,
7
+ id: number | string,
8
+ data: ListData,
9
+ digest?: string
10
+ ) {
11
+ const formDigestValue =
12
+ digest || (await fetchDigest(context.instance, context.baseURL));
13
+
14
+ data.__metadata = {
15
+ type: `SP.Data.${context.listName}ListItem`,
16
+ };
17
+
18
+ const url = `_api/lists/getbytitle('${context.listName}')/getItemById('${id}')`;
19
+
20
+ const response = await context.instance({
21
+ url,
22
+ method: 'POST',
23
+ data: JSON.stringify(data),
24
+ headers: {
25
+ 'X-RequestDigest': formDigestValue,
26
+ 'IF-MATCH': '*',
27
+ 'X-Http-Method': 'PATCH',
28
+ },
29
+ });
30
+
31
+ return response;
32
+ }
@@ -0,0 +1,36 @@
1
+ import type { Folder_Options, Options, SHAREPOINT_VER } from '../../types';
2
+
3
+ type QueryableOptions<T, V extends SHAREPOINT_VER = '2013'> =
4
+ | Options<T, V>
5
+ | Folder_Options<T>;
6
+
7
+ export function buildODataParams<T, V extends SHAREPOINT_VER = '2013'>(
8
+ options: QueryableOptions<T, V> | undefined,
9
+ orderBySeparator: ',' | ' ' = ','
10
+ ) {
11
+ const { expand, orderBy, limit, filter, cols, skip } = options || {};
12
+
13
+ const params: Record<string, string | number | undefined> = {
14
+ $expand: Array.isArray(expand) ? expand.join(',') : expand,
15
+ $top: limit,
16
+ $skip: skip,
17
+ $select: Array.isArray(cols) ? cols.join(',') : cols,
18
+ $filter: filter,
19
+ $orderby: Array.isArray(orderBy)
20
+ ? orderBy.join(orderBySeparator)
21
+ : orderBy,
22
+ };
23
+
24
+ return params;
25
+ }
26
+
27
+ export function appendParamsToUrl(
28
+ baseUrl: URL,
29
+ params: Record<string, string | number | undefined | null>
30
+ ) {
31
+ Object.entries(params).forEach(([key, value]) => {
32
+ if (value !== undefined && value !== null) {
33
+ baseUrl.searchParams.append(key, String(value));
34
+ }
35
+ });
36
+ }
@@ -0,0 +1,109 @@
1
+ import type { AxiosInstance } from 'axios';
2
+ import type {
3
+ PersonField,
4
+ UserPermision,
5
+ UserProfile,
6
+ } from '../../types';
7
+ import type { RequestContext } from './context';
8
+
9
+ type RoleDefinition = {
10
+ BasePermissions: {
11
+ High: string;
12
+ };
13
+ };
14
+
15
+ export async function typeAhead(
16
+ instance: AxiosInstance,
17
+ input: string,
18
+ filter?: string
19
+ ): Promise<PersonField> {
20
+ const requestUrl = `_api/SP.UI.ApplicationPages.ClientPeoplePickerWebServiceInterface.clientPeoplePickerSearchUser`;
21
+
22
+ const data = {
23
+ queryParams: {
24
+ __metadata: {
25
+ type: 'SP.UI.ApplicationPages.ClientPeoplePickerQueryParameters',
26
+ },
27
+ AllowEmailAddresses: true,
28
+ AllowMultipleEntities: false,
29
+ AllUrlZones: false,
30
+ MaximumEntitySuggestions: 10,
31
+ PrincipalSource: 15,
32
+ PrincipalType: 1,
33
+ QueryString: input,
34
+ },
35
+ };
36
+
37
+ if (filter) {
38
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
39
+ (data.queryParams as any).RequiredProperties = [filter];
40
+ }
41
+
42
+ const response = await instance.post(requestUrl, JSON.stringify(data), {
43
+ headers: {
44
+ Accept: 'application/json; odata=verbose',
45
+ 'Content-Type': 'application/json;odata=verbose',
46
+ },
47
+ });
48
+
49
+ return response.data.d.ClientPeoplePickerSearchUser;
50
+ }
51
+
52
+ export async function currentUserProperties(
53
+ instance: AxiosInstance
54
+ ): Promise<UserProfile> {
55
+ const requestUrl = '_api/sp.userprofiles.peoplemanager/getmyproperties';
56
+ let profile: any = await instance.get(requestUrl);
57
+
58
+ profile = profile.data.d;
59
+
60
+ profile.UserProfileProperties.results.forEach(
61
+ (prop: { Key: string; Value: string }) => {
62
+ if (prop.Key === 'FirstName') {
63
+ profile.FirstName = prop.Value;
64
+ }
65
+ if (prop.Key === 'LastName') {
66
+ profile.LastName = prop.Value;
67
+ }
68
+ if (prop.Key === 'Country') {
69
+ profile.Country = prop.Value;
70
+ }
71
+ if (prop.Key === 'UserName') {
72
+ profile.UserName = prop.Value;
73
+ }
74
+ }
75
+ );
76
+
77
+ return profile;
78
+ }
79
+
80
+ export async function getSiteUser(instance: AxiosInstance, searchValue: string) {
81
+ const requestUrl = `_api/web/siteusers?&$filter=substringof('${searchValue}', Title) or substringof('${searchValue}', LoginName) or substringof('${searchValue}', Email)&$top=50&$expand=Groups`;
82
+ const response = await instance.get(requestUrl);
83
+ return response.data.d;
84
+ }
85
+
86
+ export async function roleDefinitions(instance: AxiosInstance) {
87
+ const requestUrl = `_api/Web/RoleDefinitions`;
88
+ const response = await instance.get(requestUrl);
89
+ return response.data.d.results as RoleDefinition[];
90
+ }
91
+
92
+ export async function getEffectiveBasePermissions(instance: AxiosInstance) {
93
+ const requestUrl = `_api/Web/effectiveBasePermissions`;
94
+ const response = await instance.get(requestUrl);
95
+ return response.data.d.EffectiveBasePermissions;
96
+ }
97
+
98
+ export async function currentUserPermissions(
99
+ context: RequestContext
100
+ ): Promise<UserPermision> {
101
+ const { High } = await getEffectiveBasePermissions(context.instance);
102
+ const definitions = await roleDefinitions(context.instance);
103
+
104
+ const result = definitions.find(
105
+ ({ BasePermissions }: RoleDefinition) => BasePermissions.High === High
106
+ );
107
+
108
+ return result as UserPermision;
109
+ }
package/src/types.ts CHANGED
@@ -1,36 +1,73 @@
1
- export type Metadata = {
2
- id?: string;
3
- type?: string;
4
- uri?: string;
5
- etag?: string;
6
- };
7
-
8
- export type SPItem = {
9
- Attachments: string;
10
- ContentType: string;
11
- ContentTypeID: string;
12
- Created: string;
13
- CreatedBy: PersonField & _Deferred;
14
- CreatedById: string;
15
- Modified: string;
16
- ModifiedBy: PersonField & _Deferred;
17
- ModifiedById: string;
18
- Id: number;
19
- Title: string;
20
- Path: string;
21
- Version: string;
22
- Owshiddenversion: number;
23
- __metadata: Metadata;
24
- };
25
-
26
- type ListFields<K> = Extract<keyof K, string> | keyof SPItem;
27
-
28
- export interface Options<K = any> {
29
- expand?: ListFields<K>[] | ListFields<K>;
30
- orderBy?: ListFields<K> | [ListFields<K>, 'asc' | 'desc'];
31
- limit?: number;
32
- filter?: string;
33
- cols?: ListFields<K>[] | ListFields<K>;
1
+ export type Metadata = {
2
+ id?: string;
3
+ type?: string;
4
+ uri?: string;
5
+ etag?: string;
6
+ };
7
+
8
+ export type SPItem2010 = {
9
+ Attachments: string;
10
+ ContentType: string;
11
+ ContentTypeID: string;
12
+ Created: string;
13
+ CreatedBy: PersonField & _Deferred;
14
+ CreatedById: string;
15
+ Modified: string;
16
+ ModifiedBy: PersonField & _Deferred;
17
+ ModifiedById: string;
18
+ Id: number;
19
+ Title: string;
20
+ Path: string;
21
+ Version: string;
22
+ Owshiddenversion: number;
23
+ __metadata: Metadata;
24
+ };
25
+
26
+ export type SPItem2013 = {
27
+ __metadata: Metadata;
28
+ FirstUniqueAncestorSecurableObject: _Deferred;
29
+ RoleAssignments: _Deferred;
30
+ AttachmentFiles: _Deferred;
31
+ ContentType: _Deferred;
32
+ GetDlpPolicyTip: _Deferred;
33
+ FieldValuesAsHtml: _Deferred;
34
+ FieldValuesAsText: _Deferred;
35
+ FieldValuesForEdit: _Deferred;
36
+ File: _Deferred;
37
+ Folder: _Deferred;
38
+ ParentList: _Deferred;
39
+ FileSystemObjectType: number;
40
+ Id: number;
41
+ ContentTypeId: string;
42
+ Title: string;
43
+ PhotoRefId?: number;
44
+ ID: number;
45
+ Modified: string;
46
+ Created: string;
47
+ AuthorId: number;
48
+ EditorId: number;
49
+ OData__UIVersionString?: string;
50
+ Attachments: boolean;
51
+ GUID: string;
52
+ Author?: PersonField & _Deferred;
53
+ Editor?: PersonField & _Deferred;
54
+ [key: string]: unknown;
55
+ };
56
+
57
+ export type SPItem<V extends SHAREPOINT_VER = '2013'> = V extends '2010'
58
+ ? SPItem2010
59
+ : SPItem2013;
60
+
61
+ type ListFields<K, V extends SHAREPOINT_VER = '2013'> =
62
+ | Extract<keyof K, string>
63
+ | Extract<keyof SPItem<V>, string>;
64
+
65
+ export interface Options<K = any, V extends SHAREPOINT_VER = '2013'> {
66
+ expand?: ListFields<K, V>[] | ListFields<K, V>;
67
+ orderBy?: ListFields<K, V> | [ListFields<K, V>, 'asc' | 'desc'];
68
+ limit?: number;
69
+ filter?: string;
70
+ cols?: ListFields<K, V>[] | ListFields<K, V>;
34
71
  skip?: number;
35
72
  }
36
73
  export interface Folder_Options<K = any> {
@@ -45,9 +82,12 @@ export interface Folder_Options<K = any> {
45
82
  skip?: number;
46
83
  }
47
84
 
48
- export interface Field_Options<K> extends Omit<Options<K>, 'filter'> {
49
- fieldName?: Extract<keyof K, string>;
50
- }
85
+ export interface Field_Options<
86
+ K,
87
+ V extends SHAREPOINT_VER = '2013'
88
+ > extends Omit<Options<K, V>, 'filter'> {
89
+ fieldName?: Extract<keyof K, string>;
90
+ }
51
91
 
52
92
  export type SHAREPOINT_VER = '2010' | '2013';
53
93