@lindle/sharepoint_requests 0.1.18 → 0.1.20
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/README.md +121 -116
- package/dist/index.d.mts +469 -0
- package/dist/index.d.ts +460 -8
- package/dist/index.js +892 -5
- package/dist/index.js.map +1 -0
- package/dist/index.mjs +863 -0
- package/dist/index.mjs.map +1 -0
- package/package.json +5 -5
- package/src/index.ts +3 -5
- package/src/root/index.ts +281 -146
- package/src/root/instance.ts +7 -0
- package/src/root/internal/context.ts +2 -3
- package/src/root/internal/digest.ts +18 -11
- package/src/root/internal/emailRequests.ts +5 -11
- package/src/root/internal/listRequests/createAttachment.ts +16 -5
- package/src/root/internal/listRequests/createListItem.ts +18 -27
- package/src/root/internal/listRequests/deleteFile.ts +5 -5
- package/src/root/internal/listRequests/deleteItem.ts +17 -3
- package/src/root/internal/listRequests/getFiles.ts +4 -10
- package/src/root/internal/listRequests/getListItems.ts +43 -9
- package/src/root/internal/listRequests/getOnly.ts +10 -7
- package/src/root/internal/listRequests/normalizePayload.ts +1 -1
- package/src/root/internal/listRequests/resolveMetadataType.ts +14 -0
- package/src/root/internal/listRequests/updateListItem.ts +24 -30
- package/src/root/internal/listRequests/uploadFile.ts +13 -21
- package/src/root/internal/listRequests/utils.ts +1 -1
- package/src/root/internal/odata.ts +2 -4
- package/src/root/internal/sharepointUrl.ts +7 -0
- package/src/root/internal/userRequests.ts +93 -37
- package/src/types.ts +154 -149
- package/dist/root/index.d.ts +0 -88
- package/dist/root/instance.d.ts +0 -3
- package/dist/root/internal/context.d.ts +0 -11
- package/dist/root/internal/digest.d.ts +0 -2
- package/dist/root/internal/emailRequests.d.ts +0 -10
- package/dist/root/internal/listRequests/createAttachment.d.ts +0 -3
- package/dist/root/internal/listRequests/createListItem.d.ts +0 -3
- package/dist/root/internal/listRequests/deleteFile.d.ts +0 -3
- package/dist/root/internal/listRequests/deleteItem.d.ts +0 -3
- package/dist/root/internal/listRequests/getFiles.d.ts +0 -8
- package/dist/root/internal/listRequests/getListItems.d.ts +0 -8
- package/dist/root/internal/listRequests/getOnly.d.ts +0 -3
- package/dist/root/internal/listRequests/index.d.ts +0 -9
- package/dist/root/internal/listRequests/normalizePayload.d.ts +0 -4
- package/dist/root/internal/listRequests/updateListItem.d.ts +0 -3
- package/dist/root/internal/listRequests/uploadFile.d.ts +0 -6
- package/dist/root/internal/listRequests/utils.d.ts +0 -2
- package/dist/root/internal/odata.d.ts +0 -5
- package/dist/root/internal/userRequests.d.ts +0 -15
- package/dist/sharepoint_requests.cjs.development.js +0 -1325
- package/dist/sharepoint_requests.cjs.development.js.map +0 -1
- package/dist/sharepoint_requests.cjs.production.min.js +0 -2
- package/dist/sharepoint_requests.cjs.production.min.js.map +0 -1
- package/dist/sharepoint_requests.esm.js +0 -1318
- package/dist/sharepoint_requests.esm.js.map +0 -1
- package/dist/types.d.ts +0 -256
|
@@ -1,44 +1,35 @@
|
|
|
1
|
-
import
|
|
1
|
+
import { ListData, SHAREPOINT_VER } from '../../../types';
|
|
2
2
|
import { fetchDigest } from '../digest';
|
|
3
|
-
import
|
|
3
|
+
import { RequestContext } from '../context';
|
|
4
4
|
import { normalizeListPayload } from './normalizePayload';
|
|
5
|
-
|
|
6
|
-
async function resolveMetadataType<V extends SHAREPOINT_VER>(
|
|
7
|
-
context: RequestContext<V>
|
|
8
|
-
) {
|
|
9
|
-
if (context.resolveListItemEntityType) {
|
|
10
|
-
return context.resolveListItemEntityType();
|
|
11
|
-
}
|
|
12
|
-
|
|
13
|
-
if (context.listItemEntityTypeFullName) {
|
|
14
|
-
return context.listItemEntityTypeFullName;
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
return `SP.Data.${context.listName}ListItem`;
|
|
18
|
-
}
|
|
5
|
+
import { resolveMetadataType } from './resolveMetadataType';
|
|
19
6
|
|
|
20
7
|
export async function createListItem<
|
|
21
8
|
D = Record<string, unknown>,
|
|
22
9
|
V extends SHAREPOINT_VER = '2013'
|
|
23
10
|
>(context: RequestContext<V>, listData: ListData<D>) {
|
|
24
|
-
const metadataType = await resolveMetadataType(context);
|
|
25
11
|
const normalizedData = normalizeListPayload(listData);
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
__metadata
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
12
|
+
let payload: Record<string, unknown> = normalizedData;
|
|
13
|
+
|
|
14
|
+
if (context.sharepointVersion === '2013') {
|
|
15
|
+
const metadataType = await resolveMetadataType(context);
|
|
16
|
+
const userMetadata = (listData as { __metadata?: Record<string, unknown> })
|
|
17
|
+
.__metadata;
|
|
18
|
+
payload = {
|
|
19
|
+
...normalizedData,
|
|
20
|
+
__metadata: {
|
|
21
|
+
...(userMetadata && typeof userMetadata === 'object' ? userMetadata : {}),
|
|
22
|
+
type: metadataType,
|
|
23
|
+
},
|
|
24
|
+
};
|
|
25
|
+
}
|
|
35
26
|
|
|
36
27
|
const response = await context.instance({
|
|
37
28
|
url: context.endpoint,
|
|
38
29
|
method: 'POST',
|
|
39
30
|
data: JSON.stringify(payload),
|
|
40
31
|
headers: {
|
|
41
|
-
'X-RequestDigest': await fetchDigest(context.instance
|
|
32
|
+
'X-RequestDigest': await fetchDigest(context.instance),
|
|
42
33
|
},
|
|
43
34
|
});
|
|
44
35
|
|
|
@@ -1,7 +1,8 @@
|
|
|
1
|
-
import
|
|
1
|
+
import { SHAREPOINT_VER, DeleteFileProps } from '../../../types';
|
|
2
2
|
import { fetchDigest } from '../digest';
|
|
3
|
-
import
|
|
3
|
+
import { RequestContext } from '../context';
|
|
4
4
|
import { buildLibraryPath, encodeFileName } from './utils';
|
|
5
|
+
import { buildListByTitleEndpoint } from '../sharepointUrl';
|
|
5
6
|
|
|
6
7
|
const SUPPORTED_VERSION: SHAREPOINT_VER = '2013';
|
|
7
8
|
|
|
@@ -16,11 +17,11 @@ export async function deleteFile<V extends SHAREPOINT_VER = '2013'>(
|
|
|
16
17
|
}
|
|
17
18
|
|
|
18
19
|
const encodedFileName = encodeFileName(fileName);
|
|
19
|
-
let requestUrl =
|
|
20
|
+
let requestUrl = `${buildListByTitleEndpoint(context.listName)}/RootFolder`;
|
|
20
21
|
requestUrl += buildLibraryPath(folderPath);
|
|
21
22
|
requestUrl += `/Files('${encodedFileName}')`;
|
|
22
23
|
|
|
23
|
-
const digest = await fetchDigest(context.instance
|
|
24
|
+
const digest = await fetchDigest(context.instance);
|
|
24
25
|
|
|
25
26
|
const response = await context.instance.post(requestUrl, undefined, {
|
|
26
27
|
headers: {
|
|
@@ -28,7 +29,6 @@ export async function deleteFile<V extends SHAREPOINT_VER = '2013'>(
|
|
|
28
29
|
'IF-MATCH': '*',
|
|
29
30
|
'X-RequestDigest': digest,
|
|
30
31
|
},
|
|
31
|
-
withCredentials: true,
|
|
32
32
|
});
|
|
33
33
|
|
|
34
34
|
return response;
|
|
@@ -1,10 +1,24 @@
|
|
|
1
|
-
import
|
|
2
|
-
import
|
|
1
|
+
import { SHAREPOINT_VER } from '../../../types';
|
|
2
|
+
import { RequestContext } from '../context';
|
|
3
|
+
import { fetchDigest } from '../digest';
|
|
4
|
+
import { buildListByTitleEndpoint } from '../sharepointUrl';
|
|
3
5
|
|
|
4
6
|
export async function deleteItem<V extends SHAREPOINT_VER = '2013'>(
|
|
5
7
|
context: RequestContext<V>,
|
|
6
8
|
id: number | string
|
|
7
9
|
) {
|
|
8
|
-
const
|
|
10
|
+
const requestDigest = await fetchDigest(context.instance);
|
|
11
|
+
const url =
|
|
12
|
+
context.sharepointVersion === '2013'
|
|
13
|
+
? `${buildListByTitleEndpoint(context.listName)}/items(${id})`
|
|
14
|
+
: `${context.endpoint}(${id})`;
|
|
15
|
+
|
|
16
|
+
const response = await context.instance.post(url, undefined, {
|
|
17
|
+
headers: {
|
|
18
|
+
'X-RequestDigest': requestDigest,
|
|
19
|
+
'IF-MATCH': '*',
|
|
20
|
+
'X-HTTP-Method': 'DELETE',
|
|
21
|
+
},
|
|
22
|
+
});
|
|
9
23
|
return response;
|
|
10
24
|
}
|
|
@@ -1,11 +1,8 @@
|
|
|
1
|
-
import
|
|
1
|
+
import { Folder_Options, SHAREPOINT_VER } from '../../../types';
|
|
2
2
|
import { appendParamsToUrl, buildODataParams } from '../odata';
|
|
3
|
-
import
|
|
3
|
+
import { RequestContext } from '../context';
|
|
4
4
|
|
|
5
|
-
export async function getFiles<
|
|
6
|
-
T,
|
|
7
|
-
V extends SHAREPOINT_VER = '2013'
|
|
8
|
-
>(
|
|
5
|
+
export async function getFiles<T, V extends SHAREPOINT_VER = '2013'>(
|
|
9
6
|
context: RequestContext<V>,
|
|
10
7
|
options?: Folder_Options<T>
|
|
11
8
|
) {
|
|
@@ -20,10 +17,7 @@ export async function getFiles<
|
|
|
20
17
|
params,
|
|
21
18
|
});
|
|
22
19
|
|
|
23
|
-
const data =
|
|
24
|
-
options?.limit || !response.data.d.results
|
|
25
|
-
? response.data.d
|
|
26
|
-
: response.data.d.results;
|
|
20
|
+
const data = response.data?.d?.results ?? response.data?.d ?? response.data;
|
|
27
21
|
|
|
28
22
|
const meta = { url };
|
|
29
23
|
|
|
@@ -1,14 +1,38 @@
|
|
|
1
|
-
import
|
|
1
|
+
import { Options, SPItem, SHAREPOINT_VER } from '../../../types';
|
|
2
2
|
import { appendParamsToUrl, buildODataParams } from '../odata';
|
|
3
|
-
import
|
|
3
|
+
import { RequestContext } from '../context';
|
|
4
|
+
|
|
5
|
+
type ListItemShape<K, V extends SHAREPOINT_VER> = K & Partial<SPItem<V>>;
|
|
6
|
+
|
|
7
|
+
type SelectedColumns<
|
|
8
|
+
K,
|
|
9
|
+
V extends SHAREPOINT_VER,
|
|
10
|
+
O extends Options<K, V> | undefined
|
|
11
|
+
> = O extends { cols?: infer C }
|
|
12
|
+
? C extends readonly (infer Key)[]
|
|
13
|
+
? Extract<Key, keyof ListItemShape<K, V>>
|
|
14
|
+
: Extract<C, keyof ListItemShape<K, V>>
|
|
15
|
+
: never;
|
|
16
|
+
|
|
17
|
+
type ListItemResponseData<
|
|
18
|
+
K,
|
|
19
|
+
V extends SHAREPOINT_VER,
|
|
20
|
+
O extends Options<K, V> | undefined
|
|
21
|
+
> = [SelectedColumns<K, V, O>] extends [never]
|
|
22
|
+
? ListItemShape<K, V>
|
|
23
|
+
: Pick<ListItemShape<K, V>, SelectedColumns<K, V, O>>;
|
|
4
24
|
|
|
5
25
|
export async function getListItems<
|
|
6
26
|
K,
|
|
7
|
-
V extends SHAREPOINT_VER = '2013'
|
|
27
|
+
V extends SHAREPOINT_VER = '2013',
|
|
28
|
+
O extends Options<K, V> | undefined = Options<K, V> | undefined
|
|
8
29
|
>(
|
|
9
30
|
context: RequestContext<V>,
|
|
10
|
-
options?:
|
|
11
|
-
): Promise<{
|
|
31
|
+
options?: O
|
|
32
|
+
): Promise<{
|
|
33
|
+
data: ListItemResponseData<K, V, O> | ListItemResponseData<K, V, O>[] | undefined;
|
|
34
|
+
meta: { url: URL };
|
|
35
|
+
}> {
|
|
12
36
|
const params = buildODataParams(options, ' ');
|
|
13
37
|
|
|
14
38
|
const url = new URL(context.endpoint, context.instance.defaults.baseURL);
|
|
@@ -20,10 +44,14 @@ export async function getListItems<
|
|
|
20
44
|
params,
|
|
21
45
|
});
|
|
22
46
|
|
|
23
|
-
const rawData =
|
|
24
|
-
|
|
47
|
+
const rawData =
|
|
48
|
+
response.data?.d?.results ?? response.data?.d ?? response.data;
|
|
49
|
+
const cols = options?.cols as Options<K, V>['cols'] | undefined;
|
|
25
50
|
const keys = cols
|
|
26
|
-
? (Array.isArray(cols) ? cols : [cols]).filter(
|
|
51
|
+
? (Array.isArray(cols) ? cols : [cols]).filter(
|
|
52
|
+
(key): key is Extract<keyof ListItemShape<K, V>, string> =>
|
|
53
|
+
typeof key === 'string'
|
|
54
|
+
)
|
|
27
55
|
: undefined;
|
|
28
56
|
|
|
29
57
|
const filterItem = (item: unknown) => {
|
|
@@ -46,5 +74,11 @@ export async function getListItems<
|
|
|
46
74
|
|
|
47
75
|
const meta = { url };
|
|
48
76
|
|
|
49
|
-
return {
|
|
77
|
+
return {
|
|
78
|
+
data: data as
|
|
79
|
+
| ListItemResponseData<K, V, O>
|
|
80
|
+
| ListItemResponseData<K, V, O>[]
|
|
81
|
+
| undefined,
|
|
82
|
+
meta,
|
|
83
|
+
};
|
|
50
84
|
}
|
|
@@ -1,18 +1,21 @@
|
|
|
1
|
-
import
|
|
2
|
-
import
|
|
1
|
+
import { AxiosInstance } from 'axios';
|
|
2
|
+
import { Options, SHAREPOINT_VER } from '../../../types';
|
|
3
3
|
import { buildODataParams } from '../odata';
|
|
4
4
|
|
|
5
|
-
export async function getOnly<
|
|
6
|
-
T,
|
|
7
|
-
V extends SHAREPOINT_VER = '2013'
|
|
8
|
-
>(
|
|
5
|
+
export async function getOnly<T, V extends SHAREPOINT_VER = '2013'>(
|
|
9
6
|
instance: AxiosInstance,
|
|
10
7
|
endpoint: string,
|
|
11
8
|
options?: Options<T, V>
|
|
12
9
|
) {
|
|
13
10
|
const params = buildODataParams(options, ',');
|
|
14
11
|
const { data } = await instance.get(endpoint, { params });
|
|
15
|
-
if (data) {
|
|
12
|
+
if (!data) {
|
|
13
|
+
return undefined;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
if (data.d) {
|
|
16
17
|
return data.d.results ? data.d.results : data.d;
|
|
17
18
|
}
|
|
19
|
+
|
|
20
|
+
return data;
|
|
18
21
|
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { SHAREPOINT_VER } from '../../../types';
|
|
2
|
+
import { RequestContext } from '../context';
|
|
3
|
+
|
|
4
|
+
export async function resolveMetadataType<V extends SHAREPOINT_VER>(
|
|
5
|
+
context: RequestContext<V>
|
|
6
|
+
): Promise<string> {
|
|
7
|
+
if (context.resolveListItemEntityType) {
|
|
8
|
+
return context.resolveListItemEntityType();
|
|
9
|
+
}
|
|
10
|
+
if (context.listItemEntityTypeFullName) {
|
|
11
|
+
return context.listItemEntityTypeFullName;
|
|
12
|
+
}
|
|
13
|
+
return `SP.Data.${context.listName}ListItem`;
|
|
14
|
+
}
|
|
@@ -1,21 +1,9 @@
|
|
|
1
|
-
import
|
|
1
|
+
import { ListData, SHAREPOINT_VER } from '../../../types';
|
|
2
2
|
import { fetchDigest } from '../digest';
|
|
3
|
-
import
|
|
3
|
+
import { RequestContext } from '../context';
|
|
4
4
|
import { normalizeListPayload } from './normalizePayload';
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
context: RequestContext<V>
|
|
8
|
-
) {
|
|
9
|
-
if (context.resolveListItemEntityType) {
|
|
10
|
-
return context.resolveListItemEntityType();
|
|
11
|
-
}
|
|
12
|
-
|
|
13
|
-
if (context.listItemEntityTypeFullName) {
|
|
14
|
-
return context.listItemEntityTypeFullName;
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
return `SP.Data.${context.listName}ListItem`;
|
|
18
|
-
}
|
|
5
|
+
import { buildListByTitleEndpoint } from '../sharepointUrl';
|
|
6
|
+
import { resolveMetadataType } from './resolveMetadataType';
|
|
19
7
|
|
|
20
8
|
export async function updateListItem<
|
|
21
9
|
D = Record<string, unknown>,
|
|
@@ -26,22 +14,28 @@ export async function updateListItem<
|
|
|
26
14
|
data: ListData<D>,
|
|
27
15
|
digest?: string
|
|
28
16
|
) {
|
|
29
|
-
const formDigestValue =
|
|
30
|
-
digest || (await fetchDigest(context.instance, context.baseURL));
|
|
17
|
+
const formDigestValue = digest ?? (await fetchDigest(context.instance));
|
|
31
18
|
|
|
32
|
-
const metadataType = await resolveMetadataType(context);
|
|
33
19
|
const normalizedData = normalizeListPayload(data);
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
__metadata
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
20
|
+
let payload: Record<string, unknown> = normalizedData;
|
|
21
|
+
|
|
22
|
+
if (context.sharepointVersion === '2013') {
|
|
23
|
+
const metadataType = await resolveMetadataType(context);
|
|
24
|
+
const userMetadata = (data as { __metadata?: Record<string, unknown> })
|
|
25
|
+
.__metadata;
|
|
26
|
+
payload = {
|
|
27
|
+
...normalizedData,
|
|
28
|
+
__metadata: {
|
|
29
|
+
...(userMetadata && typeof userMetadata === 'object' ? userMetadata : {}),
|
|
30
|
+
type: metadataType,
|
|
31
|
+
},
|
|
32
|
+
};
|
|
33
|
+
}
|
|
43
34
|
|
|
44
|
-
const url =
|
|
35
|
+
const url =
|
|
36
|
+
context.sharepointVersion === '2013'
|
|
37
|
+
? `${buildListByTitleEndpoint(context.listName)}/items(${id})`
|
|
38
|
+
: `${context.endpoint}(${id})`;
|
|
45
39
|
|
|
46
40
|
const response = await context.instance({
|
|
47
41
|
url,
|
|
@@ -50,7 +44,7 @@ export async function updateListItem<
|
|
|
50
44
|
headers: {
|
|
51
45
|
'X-RequestDigest': formDigestValue,
|
|
52
46
|
'IF-MATCH': '*',
|
|
53
|
-
'X-
|
|
47
|
+
'X-HTTP-Method': 'MERGE',
|
|
54
48
|
},
|
|
55
49
|
});
|
|
56
50
|
|
|
@@ -1,19 +1,16 @@
|
|
|
1
|
-
import
|
|
2
|
-
import
|
|
3
|
-
ItemID,
|
|
4
|
-
SHAREPOINT_VER,
|
|
5
|
-
UploadFileProps,
|
|
6
|
-
} from '../../../types';
|
|
1
|
+
import { AxiosResponse } from 'axios';
|
|
2
|
+
import { ItemID, SHAREPOINT_VER, UploadFileProps } from '../../../types';
|
|
7
3
|
import { fetchDigest } from '../digest';
|
|
8
|
-
import
|
|
4
|
+
import { RequestContext } from '../context';
|
|
9
5
|
import { buildLibraryPath, encodeFileName } from './utils';
|
|
6
|
+
import { buildListByTitleEndpoint } from '../sharepointUrl';
|
|
10
7
|
|
|
11
8
|
const SUPPORTED_VERSION: SHAREPOINT_VER = '2013';
|
|
12
9
|
|
|
13
10
|
export async function uploadFile<V extends SHAREPOINT_VER = '2013'>(
|
|
14
11
|
context: RequestContext<V>,
|
|
15
12
|
{ file, folderPath, overwrite = true }: UploadFileProps
|
|
16
|
-
): Promise<
|
|
13
|
+
): Promise<{ response: AxiosResponse; itemId?: ItemID }> {
|
|
17
14
|
if (context.sharepointVersion !== SUPPORTED_VERSION) {
|
|
18
15
|
throw new Error(
|
|
19
16
|
'uploadFile is only supported for SharePoint 2013 REST endpoints.'
|
|
@@ -24,8 +21,7 @@ export async function uploadFile<V extends SHAREPOINT_VER = '2013'>(
|
|
|
24
21
|
throw new Error('A file with a valid name must be provided.');
|
|
25
22
|
}
|
|
26
23
|
|
|
27
|
-
let requestUrl =
|
|
28
|
-
|
|
24
|
+
let requestUrl = `${buildListByTitleEndpoint(context.listName)}/RootFolder`;
|
|
29
25
|
requestUrl += buildLibraryPath(folderPath);
|
|
30
26
|
|
|
31
27
|
const encodedFileName = encodeFileName(file.name);
|
|
@@ -33,37 +29,33 @@ export async function uploadFile<V extends SHAREPOINT_VER = '2013'>(
|
|
|
33
29
|
overwrite ? 'true' : 'false'
|
|
34
30
|
})?$expand=ListItemAllFields&$select=ListItemAllFields/Id`;
|
|
35
31
|
|
|
36
|
-
const digest = await fetchDigest(context.instance
|
|
32
|
+
const digest = await fetchDigest(context.instance);
|
|
37
33
|
|
|
38
|
-
const response =
|
|
34
|
+
const response = await context.instance.post(requestUrl, file, {
|
|
39
35
|
headers: {
|
|
40
36
|
'Content-Type': file.type || 'application/octet-stream',
|
|
41
37
|
'X-RequestDigest': digest,
|
|
42
38
|
},
|
|
43
|
-
|
|
44
|
-
})) as AxiosResponse & { itemId?: ItemID };
|
|
39
|
+
});
|
|
45
40
|
|
|
46
41
|
const responseData = response.data?.d ?? response.data;
|
|
47
42
|
const listItemFields = responseData?.ListItemAllFields;
|
|
48
|
-
|
|
43
|
+
let itemId: ItemID | undefined =
|
|
49
44
|
listItemFields?.Id ??
|
|
50
45
|
listItemFields?.ID ??
|
|
51
46
|
responseData?.Id ??
|
|
52
47
|
responseData?.ID;
|
|
53
48
|
|
|
54
|
-
if (typeof itemId
|
|
55
|
-
response.itemId = itemId;
|
|
56
|
-
} else if (listItemFields?.__deferred?.uri) {
|
|
49
|
+
if (typeof itemId === 'undefined' && listItemFields?.__deferred?.uri) {
|
|
57
50
|
const listItemResponse = await context.instance.get(
|
|
58
51
|
listItemFields.__deferred.uri
|
|
59
52
|
);
|
|
60
53
|
const deferredId =
|
|
61
54
|
listItemResponse.data?.d?.Id ?? listItemResponse.data?.Id;
|
|
62
|
-
|
|
63
55
|
if (typeof deferredId !== 'undefined') {
|
|
64
|
-
|
|
56
|
+
itemId = deferredId;
|
|
65
57
|
}
|
|
66
58
|
}
|
|
67
59
|
|
|
68
|
-
return response;
|
|
60
|
+
return { response, itemId };
|
|
69
61
|
}
|
|
@@ -11,7 +11,7 @@ export function buildLibraryPath(folderPath?: string | string[]) {
|
|
|
11
11
|
return '';
|
|
12
12
|
}
|
|
13
13
|
|
|
14
|
-
const escapedSegments = segments.map(
|
|
14
|
+
const escapedSegments = segments.map(segment => {
|
|
15
15
|
if (!segment.trim()) {
|
|
16
16
|
throw new Error('Folder path segments cannot be empty.');
|
|
17
17
|
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import
|
|
1
|
+
import { Folder_Options, Options, SHAREPOINT_VER } from '../../types';
|
|
2
2
|
|
|
3
3
|
type QueryableOptions<T, V extends SHAREPOINT_VER = '2013'> =
|
|
4
4
|
| Options<T, V>
|
|
@@ -16,9 +16,7 @@ export function buildODataParams<T, V extends SHAREPOINT_VER = '2013'>(
|
|
|
16
16
|
$skip: skip,
|
|
17
17
|
$select: Array.isArray(cols) ? cols.join(',') : cols,
|
|
18
18
|
$filter: filter,
|
|
19
|
-
$orderby: Array.isArray(orderBy)
|
|
20
|
-
? orderBy.join(orderBySeparator)
|
|
21
|
-
: orderBy,
|
|
19
|
+
$orderby: Array.isArray(orderBy) ? orderBy.join(orderBySeparator) : orderBy,
|
|
22
20
|
};
|
|
23
21
|
|
|
24
22
|
return params;
|
|
@@ -1,17 +1,28 @@
|
|
|
1
|
-
import
|
|
2
|
-
import
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
UserProfile,
|
|
6
|
-
} from '../../types';
|
|
7
|
-
import type { RequestContext } from './context';
|
|
1
|
+
import { AxiosInstance } from 'axios';
|
|
2
|
+
import { PermissionLabel, PersonField, UserPermision, UserProfile } from '../../types';
|
|
3
|
+
import { RequestContext } from './context';
|
|
4
|
+
import { escapeODataStringLiteral } from './sharepointUrl';
|
|
8
5
|
|
|
9
6
|
type RoleDefinition = {
|
|
7
|
+
Name: string;
|
|
8
|
+
Description: string;
|
|
9
|
+
Hidden: boolean;
|
|
10
|
+
Id: number;
|
|
11
|
+
Order: number;
|
|
12
|
+
RoleTypeKind: number;
|
|
10
13
|
BasePermissions: {
|
|
11
14
|
High: string;
|
|
15
|
+
Low: string;
|
|
12
16
|
};
|
|
13
17
|
};
|
|
14
18
|
|
|
19
|
+
const PERMISSION_PRIORITY: PermissionLabel[] = [
|
|
20
|
+
'Full Control',
|
|
21
|
+
'Edit',
|
|
22
|
+
'Contribute',
|
|
23
|
+
'Read',
|
|
24
|
+
];
|
|
25
|
+
|
|
15
26
|
export async function typeAhead(
|
|
16
27
|
instance: AxiosInstance,
|
|
17
28
|
input: string,
|
|
@@ -46,64 +57,109 @@ export async function typeAhead(
|
|
|
46
57
|
},
|
|
47
58
|
});
|
|
48
59
|
|
|
49
|
-
|
|
60
|
+
const searchResults =
|
|
61
|
+
response.data?.d?.ClientPeoplePickerSearchUser ??
|
|
62
|
+
response.data?.ClientPeoplePickerSearchUser;
|
|
63
|
+
|
|
64
|
+
if (typeof searchResults === 'string') {
|
|
65
|
+
const parsed = JSON.parse(searchResults);
|
|
66
|
+
if (Array.isArray(parsed) && parsed.length > 0) {
|
|
67
|
+
return parsed[0] as PersonField;
|
|
68
|
+
}
|
|
69
|
+
throw new Error('People picker returned no results.');
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
if (Array.isArray(searchResults) && searchResults.length > 0) {
|
|
73
|
+
return searchResults[0] as PersonField;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
if (searchResults && typeof searchResults === 'object') {
|
|
77
|
+
return searchResults as PersonField;
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
throw new Error('Invalid people picker response.');
|
|
50
81
|
}
|
|
51
82
|
|
|
52
83
|
export async function currentUserProperties(
|
|
53
84
|
instance: AxiosInstance
|
|
54
85
|
): Promise<UserProfile> {
|
|
55
86
|
const requestUrl = '_api/sp.userprofiles.peoplemanager/getmyproperties';
|
|
56
|
-
|
|
87
|
+
const response = await instance.get(requestUrl);
|
|
57
88
|
|
|
58
|
-
profile =
|
|
89
|
+
const profile = (response.data?.d ?? response.data) as UserProfile | undefined;
|
|
90
|
+
if (!profile) {
|
|
91
|
+
throw new Error('Unable to retrieve user profile.');
|
|
92
|
+
}
|
|
59
93
|
|
|
60
|
-
profile.UserProfileProperties
|
|
94
|
+
profile.UserProfileProperties?.results?.forEach(
|
|
61
95
|
(prop: { Key: string; Value: string }) => {
|
|
62
|
-
if (prop.Key === 'FirstName')
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
if (prop.Key === '
|
|
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
|
-
}
|
|
96
|
+
if (prop.Key === 'FirstName') profile.FirstName = prop.Value;
|
|
97
|
+
else if (prop.Key === 'LastName') profile.LastName = prop.Value;
|
|
98
|
+
else if (prop.Key === 'Country') profile.Country = prop.Value;
|
|
99
|
+
else if (prop.Key === 'UserName') profile.UserName = prop.Value;
|
|
74
100
|
}
|
|
75
101
|
);
|
|
76
102
|
|
|
77
103
|
return profile;
|
|
78
104
|
}
|
|
79
105
|
|
|
80
|
-
export async function getSiteUser(
|
|
81
|
-
|
|
82
|
-
|
|
106
|
+
export async function getSiteUser(
|
|
107
|
+
instance: AxiosInstance,
|
|
108
|
+
searchValue: string
|
|
109
|
+
) {
|
|
110
|
+
const safeSearchValue = escapeODataStringLiteral(searchValue);
|
|
111
|
+
const response = await instance.get('_api/web/siteusers', {
|
|
112
|
+
params: {
|
|
113
|
+
$filter: `substringof('${safeSearchValue}', Title) or substringof('${safeSearchValue}', LoginName) or substringof('${safeSearchValue}', Email)`,
|
|
114
|
+
$top: 50,
|
|
115
|
+
$expand: 'Groups',
|
|
116
|
+
},
|
|
117
|
+
});
|
|
83
118
|
return response.data.d;
|
|
84
119
|
}
|
|
85
120
|
|
|
86
|
-
|
|
87
|
-
const
|
|
88
|
-
const response = await instance.get(requestUrl);
|
|
121
|
+
async function roleDefinitions(instance: AxiosInstance): Promise<RoleDefinition[]> {
|
|
122
|
+
const response = await instance.get('_api/Web/RoleDefinitions');
|
|
89
123
|
return response.data.d.results as RoleDefinition[];
|
|
90
124
|
}
|
|
91
125
|
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
126
|
+
async function getEffectiveBasePermissions(
|
|
127
|
+
instance: AxiosInstance
|
|
128
|
+
): Promise<{ High: string; Low: string }> {
|
|
129
|
+
const response = await instance.get('_api/Web/effectiveBasePermissions');
|
|
95
130
|
return response.data.d.EffectiveBasePermissions;
|
|
96
131
|
}
|
|
97
132
|
|
|
98
133
|
export async function currentUserPermissions(
|
|
99
134
|
context: RequestContext
|
|
100
135
|
): Promise<UserPermision> {
|
|
101
|
-
const { High } = await getEffectiveBasePermissions(
|
|
136
|
+
const { High: userHigh, Low: userLow } = await getEffectiveBasePermissions(
|
|
137
|
+
context.instance
|
|
138
|
+
);
|
|
102
139
|
const definitions = await roleDefinitions(context.instance);
|
|
103
140
|
|
|
104
|
-
const
|
|
105
|
-
|
|
106
|
-
|
|
141
|
+
const userHighInt = parseInt(userHigh, 10);
|
|
142
|
+
const userLowInt = parseInt(userLow, 10);
|
|
143
|
+
|
|
144
|
+
const matching = definitions
|
|
145
|
+
.filter((def): def is RoleDefinition =>
|
|
146
|
+
PERMISSION_PRIORITY.includes(def.Name as PermissionLabel) &&
|
|
147
|
+
(userHighInt & parseInt(def.BasePermissions.High, 10)) === parseInt(def.BasePermissions.High, 10) &&
|
|
148
|
+
(userLowInt & parseInt(def.BasePermissions.Low, 10)) === parseInt(def.BasePermissions.Low, 10)
|
|
149
|
+
)
|
|
150
|
+
.sort(
|
|
151
|
+
(a, b) =>
|
|
152
|
+
PERMISSION_PRIORITY.indexOf(a.Name as PermissionLabel) -
|
|
153
|
+
PERMISSION_PRIORITY.indexOf(b.Name as PermissionLabel)
|
|
154
|
+
);
|
|
155
|
+
|
|
156
|
+
const result = matching[0];
|
|
157
|
+
|
|
158
|
+
if (!result) {
|
|
159
|
+
throw new Error(
|
|
160
|
+
`Unable to resolve current user permission. Effective: High="${userHigh}", Low="${userLow}"`
|
|
161
|
+
);
|
|
162
|
+
}
|
|
107
163
|
|
|
108
|
-
return result as UserPermision;
|
|
164
|
+
return result as unknown as UserPermision;
|
|
109
165
|
}
|