@planningcenter/chat-react-native 1.5.0-rc.2 → 1.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (57) hide show
  1. package/build/contexts/api_provider.d.ts.map +1 -1
  2. package/build/contexts/api_provider.js +3 -1
  3. package/build/contexts/api_provider.js.map +1 -1
  4. package/build/utils/client/client.d.ts +23 -0
  5. package/build/utils/client/client.d.ts.map +1 -0
  6. package/build/utils/client/client.js +75 -0
  7. package/build/utils/client/client.js.map +1 -0
  8. package/build/utils/client/index.d.ts +2 -0
  9. package/build/utils/client/index.d.ts.map +1 -0
  10. package/build/utils/client/index.js +2 -0
  11. package/build/utils/client/index.js.map +1 -0
  12. package/build/utils/client/request_helpers.d.ts +20 -0
  13. package/build/utils/client/request_helpers.d.ts.map +1 -0
  14. package/build/utils/client/request_helpers.js +83 -0
  15. package/build/utils/client/request_helpers.js.map +1 -0
  16. package/build/utils/client/transform_request_data.d.ts +8 -0
  17. package/build/utils/client/transform_request_data.d.ts.map +1 -0
  18. package/build/utils/client/transform_request_data.js +33 -0
  19. package/build/utils/client/transform_request_data.js.map +1 -0
  20. package/build/utils/client/transform_response.d.ts +3 -0
  21. package/build/utils/client/transform_response.d.ts.map +1 -0
  22. package/build/utils/client/transform_response.js +84 -0
  23. package/build/utils/client/transform_response.js.map +1 -0
  24. package/build/utils/client/utils.d.ts +5 -0
  25. package/build/utils/client/utils.d.ts.map +1 -0
  26. package/build/utils/client/utils.js +36 -0
  27. package/build/utils/client/utils.js.map +1 -0
  28. package/build/utils/index.d.ts +2 -0
  29. package/build/utils/index.d.ts.map +1 -1
  30. package/build/utils/index.js +2 -0
  31. package/build/utils/index.js.map +1 -1
  32. package/build/utils/session.d.ts +4 -7
  33. package/build/utils/session.d.ts.map +1 -1
  34. package/build/utils/session.js +12 -14
  35. package/build/utils/session.js.map +1 -1
  36. package/build/utils/uri.d.ts +21 -0
  37. package/build/utils/uri.d.ts.map +1 -0
  38. package/build/utils/uri.js +61 -0
  39. package/build/utils/uri.js.map +1 -0
  40. package/package.json +8 -3
  41. package/src/__tests__/client.ts +388 -0
  42. package/src/__tests__/{session.tsx → session.ts} +2 -11
  43. package/src/__utils__/fixtures/defaults/index.ts +17 -0
  44. package/src/__utils__/fixtures/defaults/records.ts +109 -0
  45. package/src/__utils__/handlers.ts +38 -0
  46. package/src/__utils__/server.ts +67 -0
  47. package/src/contexts/api_provider.tsx +3 -1
  48. package/src/utils/client/client.ts +114 -0
  49. package/src/utils/client/index.ts +1 -0
  50. package/src/utils/client/request_helpers.ts +114 -0
  51. package/src/utils/client/transform_request_data.ts +48 -0
  52. package/src/utils/client/transform_response.ts +97 -0
  53. package/src/utils/client/types.d.ts +64 -0
  54. package/src/utils/client/utils.ts +45 -0
  55. package/src/utils/index.ts +2 -0
  56. package/src/utils/session.ts +12 -15
  57. package/src/utils/uri.ts +70 -0
@@ -1 +1 @@
1
- {"version":3,"file":"api_provider.d.ts","sourceRoot":"","sources":["../../src/contexts/api_provider.tsx"],"names":[],"mappings":"AACA,OAAO,EAAE,WAAW,EAAiC,MAAM,uBAAuB,CAAA;AAClF,OAAO,KAAoB,MAAM,OAAO,CAAA;AACxC,OAAO,EAAE,SAAS,EAAE,MAAM,cAAc,CAAA;AACxC,OAAO,EAAE,UAAU,EAAE,MAAM,UAAU,CAAA;AAErC,OAAO,EAAE,GAAG,EAAW,MAAM,kBAAkB,CAAA;AAqB/C,eAAO,MAAM,WAAW,aAMtB,CAAA;AAEF,wBAAgB,WAAW,CAAC,EAC1B,QAAQ,EACR,GAAkB,EAClB,KAAK,EACL,cAAc,GACf,EAAE,SAAS,GAAG;IAAE,GAAG,CAAC,EAAE,GAAG,CAAC;IAAC,KAAK,CAAC,EAAE,UAAU,CAAC;IAAC,cAAc,EAAE,MAAM,IAAI,CAAA;CAAE,qBAU3E"}
1
+ {"version":3,"file":"api_provider.d.ts","sourceRoot":"","sources":["../../src/contexts/api_provider.tsx"],"names":[],"mappings":"AACA,OAAO,EAAE,WAAW,EAAiC,MAAM,uBAAuB,CAAA;AAClF,OAAO,KAAoB,MAAM,OAAO,CAAA;AACxC,OAAO,EAAE,SAAS,EAAE,MAAM,cAAc,CAAA;AACxC,OAAO,EAAE,UAAU,EAAE,MAAM,UAAU,CAAA;AAErC,OAAO,EAAE,GAAG,EAAW,MAAM,kBAAkB,CAAA;AAuB/C,eAAO,MAAM,WAAW,aAMtB,CAAA;AAEF,wBAAgB,WAAW,CAAC,EAC1B,QAAQ,EACR,GAAkB,EAClB,KAAK,EACL,cAAc,GACf,EAAE,SAAS,GAAG;IAAE,GAAG,CAAC,EAAE,GAAG,CAAC;IAAC,KAAK,CAAC,EAAE,UAAU,CAAC;IAAC,cAAc,EAAE,MAAM,IAAI,CAAA;CAAE,qBAU3E"}
@@ -2,12 +2,14 @@ import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
2
2
  import React, { useEffect } from 'react';
3
3
  import apiRequest from '../utils/api';
4
4
  import { session } from '../utils/session';
5
+ import Uri from '../utils/uri';
5
6
  let handleTokenExpired;
6
7
  const defaultQueryFn = ({ queryKey }) => {
7
8
  if (!session.token) {
8
9
  throw new Error('No token present');
9
10
  }
10
- const url = `${session.baseUrl}${queryKey[0]}`;
11
+ const uri = new Uri({ session });
12
+ const url = uri.api(queryKey[0]);
11
13
  return apiRequest(url)
12
14
  .then(r => r.json)
13
15
  .catch(error => {
@@ -1 +1 @@
1
- {"version":3,"file":"api_provider.js","sourceRoot":"","sources":["../../src/contexts/api_provider.tsx"],"names":[],"mappings":"AACA,OAAO,EAAE,WAAW,EAAE,mBAAmB,EAAY,MAAM,uBAAuB,CAAA;AAClF,OAAO,KAAK,EAAE,EAAE,SAAS,EAAE,MAAM,OAAO,CAAA;AAGxC,OAAO,UAAU,MAAM,cAAc,CAAA;AACrC,OAAO,EAAO,OAAO,EAAE,MAAM,kBAAkB,CAAA;AAE/C,IAAI,kBAA8B,CAAA;AAElC,MAAM,cAAc,GAAG,CAAC,EAAE,QAAQ,EAA0B,EAAE,EAAE;IAC9D,IAAI,CAAC,OAAO,CAAC,KAAK,EAAE,CAAC;QACnB,MAAM,IAAI,KAAK,CAAC,kBAAkB,CAAC,CAAA;IACrC,CAAC;IAED,MAAM,GAAG,GAAG,GAAG,OAAO,CAAC,OAAO,GAAG,QAAQ,CAAC,CAAC,CAAC,EAAE,CAAA;IAE9C,OAAO,UAAU,CAAkB,GAAG,CAAC;SACpC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC;SACjB,KAAK,CAAC,KAAK,CAAC,EAAE;QACb,IAAI,KAAK,CAAC,OAAO,KAAK,eAAe,EAAE,CAAC;YACtC,kBAAkB,EAAE,CAAA;QACtB,CAAC;QACD,OAAO,IAAI,CAAA;IACb,CAAC,CAAC,CAAA;AACN,CAAC,CAAA;AAED,MAAM,CAAC,MAAM,WAAW,GAAG,IAAI,WAAW,CAAC;IACzC,cAAc,EAAE;QACd,OAAO,EAAE;YACP,OAAO,EAAE,cAAc;SACxB;KACF;CACF,CAAC,CAAA;AAEF,MAAM,UAAU,WAAW,CAAC,EAC1B,QAAQ,EACR,GAAG,GAAG,YAAY,EAClB,KAAK,EACL,cAAc,GAC4D;IAC1E,OAAO,CAAC,GAAG,GAAG,GAAG,CAAA;IACjB,OAAO,CAAC,KAAK,GAAG,KAAK,CAAA;IACrB,kBAAkB,GAAG,cAAc,CAAA;IAEnC,SAAS,CAAC,GAAG,EAAE;QACb,WAAW,CAAC,iBAAiB,EAAE,CAAA;IACjC,CAAC,EAAE,CAAC,GAAG,EAAE,KAAK,CAAC,CAAC,CAAA;IAEhB,OAAO,CAAC,mBAAmB,CAAC,MAAM,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,QAAQ,CAAC,EAAE,mBAAmB,CAAC,CAAA;AACnF,CAAC","sourcesContent":["import { JSONAPIResponse } from '@planningcenter/chat-core'\nimport { QueryClient, QueryClientProvider, QueryKey } from '@tanstack/react-query'\nimport React, { useEffect } from 'react'\nimport { ViewProps } from 'react-native'\nimport { OAuthToken } from '../types'\nimport apiRequest from '../utils/api'\nimport { ENV, session } from '../utils/session'\n\nlet handleTokenExpired: () => void\n\nconst defaultQueryFn = ({ queryKey }: { queryKey: QueryKey }) => {\n if (!session.token) {\n throw new Error('No token present')\n }\n\n const url = `${session.baseUrl}${queryKey[0]}`\n\n return apiRequest<JSONAPIResponse>(url)\n .then(r => r.json)\n .catch(error => {\n if (error.message === 'Token expired') {\n handleTokenExpired()\n }\n return null\n })\n}\n\nexport const queryClient = new QueryClient({\n defaultOptions: {\n queries: {\n queryFn: defaultQueryFn,\n },\n },\n})\n\nexport function ApiProvider({\n children,\n env = 'production',\n token,\n onTokenExpired,\n}: ViewProps & { env?: ENV; token?: OAuthToken; onTokenExpired: () => void }) {\n session.env = env\n session.token = token\n handleTokenExpired = onTokenExpired\n\n useEffect(() => {\n queryClient.invalidateQueries()\n }, [env, token])\n\n return <QueryClientProvider client={queryClient}>{children}</QueryClientProvider>\n}\n"]}
1
+ {"version":3,"file":"api_provider.js","sourceRoot":"","sources":["../../src/contexts/api_provider.tsx"],"names":[],"mappings":"AACA,OAAO,EAAE,WAAW,EAAE,mBAAmB,EAAY,MAAM,uBAAuB,CAAA;AAClF,OAAO,KAAK,EAAE,EAAE,SAAS,EAAE,MAAM,OAAO,CAAA;AAGxC,OAAO,UAAU,MAAM,cAAc,CAAA;AACrC,OAAO,EAAO,OAAO,EAAE,MAAM,kBAAkB,CAAA;AAC/C,OAAO,GAAG,MAAM,cAAc,CAAA;AAE9B,IAAI,kBAA8B,CAAA;AAElC,MAAM,cAAc,GAAG,CAAC,EAAE,QAAQ,EAA0B,EAAE,EAAE;IAC9D,IAAI,CAAC,OAAO,CAAC,KAAK,EAAE,CAAC;QACnB,MAAM,IAAI,KAAK,CAAC,kBAAkB,CAAC,CAAA;IACrC,CAAC;IAED,MAAM,GAAG,GAAG,IAAI,GAAG,CAAC,EAAE,OAAO,EAAE,CAAC,CAAA;IAChC,MAAM,GAAG,GAAG,GAAG,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAA;IAEhC,OAAO,UAAU,CAAkB,GAAG,CAAC;SACpC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC;SACjB,KAAK,CAAC,KAAK,CAAC,EAAE;QACb,IAAI,KAAK,CAAC,OAAO,KAAK,eAAe,EAAE,CAAC;YACtC,kBAAkB,EAAE,CAAA;QACtB,CAAC;QACD,OAAO,IAAI,CAAA;IACb,CAAC,CAAC,CAAA;AACN,CAAC,CAAA;AAED,MAAM,CAAC,MAAM,WAAW,GAAG,IAAI,WAAW,CAAC;IACzC,cAAc,EAAE;QACd,OAAO,EAAE;YACP,OAAO,EAAE,cAAc;SACxB;KACF;CACF,CAAC,CAAA;AAEF,MAAM,UAAU,WAAW,CAAC,EAC1B,QAAQ,EACR,GAAG,GAAG,YAAY,EAClB,KAAK,EACL,cAAc,GAC4D;IAC1E,OAAO,CAAC,GAAG,GAAG,GAAG,CAAA;IACjB,OAAO,CAAC,KAAK,GAAG,KAAK,CAAA;IACrB,kBAAkB,GAAG,cAAc,CAAA;IAEnC,SAAS,CAAC,GAAG,EAAE;QACb,WAAW,CAAC,iBAAiB,EAAE,CAAA;IACjC,CAAC,EAAE,CAAC,GAAG,EAAE,KAAK,CAAC,CAAC,CAAA;IAEhB,OAAO,CAAC,mBAAmB,CAAC,MAAM,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,QAAQ,CAAC,EAAE,mBAAmB,CAAC,CAAA;AACnF,CAAC","sourcesContent":["import { JSONAPIResponse } from '@planningcenter/chat-core'\nimport { QueryClient, QueryClientProvider, QueryKey } from '@tanstack/react-query'\nimport React, { useEffect } from 'react'\nimport { ViewProps } from 'react-native'\nimport { OAuthToken } from '../types'\nimport apiRequest from '../utils/api'\nimport { ENV, session } from '../utils/session'\nimport Uri from '../utils/uri'\n\nlet handleTokenExpired: () => void\n\nconst defaultQueryFn = ({ queryKey }: { queryKey: QueryKey }) => {\n if (!session.token) {\n throw new Error('No token present')\n }\n\n const uri = new Uri({ session })\n const url = uri.api(queryKey[0])\n\n return apiRequest<JSONAPIResponse>(url)\n .then(r => r.json)\n .catch(error => {\n if (error.message === 'Token expired') {\n handleTokenExpired()\n }\n return null\n })\n}\n\nexport const queryClient = new QueryClient({\n defaultOptions: {\n queries: {\n queryFn: defaultQueryFn,\n },\n },\n})\n\nexport function ApiProvider({\n children,\n env = 'production',\n token,\n onTokenExpired,\n}: ViewProps & { env?: ENV; token?: OAuthToken; onTokenExpired: () => void }) {\n session.env = env\n session.token = token\n handleTokenExpired = onTokenExpired\n\n useEffect(() => {\n queryClient.invalidateQueries()\n }, [env, token])\n\n return <QueryClientProvider client={queryClient}>{children}</QueryClientProvider>\n}\n"]}
@@ -0,0 +1,23 @@
1
+ import { JSONAPIResponse } from '@planningcenter/chat-core';
2
+ import Uri from '../uri';
3
+ import { ApiClient, DeleteRequest, GetRequest, PatchRequest, PostRequest } from './types';
4
+ export declare class Client implements ApiClient {
5
+ version: string;
6
+ defaultHeaders: Record<string, string>;
7
+ uri: Uri;
8
+ constructor({ version, defaultHeaders, session, app }: {
9
+ version: any;
10
+ defaultHeaders?: {} | undefined;
11
+ session: any;
12
+ app: any;
13
+ });
14
+ get(args: GetRequest): Promise<JSONAPIResponse>;
15
+ patch(args: PatchRequest): Promise<any>;
16
+ post(args: PostRequest): Promise<any>;
17
+ delete(args: DeleteRequest): Promise<any>;
18
+ get config(): {
19
+ defaultHeaders: Record<string, string>;
20
+ };
21
+ }
22
+ export default Client;
23
+ //# sourceMappingURL=client.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../../../src/utils/client/client.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,2BAA2B,CAAA;AAC3D,OAAO,GAAG,MAAM,QAAQ,CAAA;AASxB,OAAO,EACL,SAAS,EACT,aAAa,EACb,UAAU,EACV,YAAY,EACZ,WAAW,EAEZ,MAAM,SAAS,CAAA;AAEhB,qBAAa,MAAO,YAAW,SAAS;IACtC,OAAO,EAAE,MAAM,CAAK;IACpB,cAAc,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAK;IAC3C,GAAG,EAAE,GAAG,CAAA;gBAEI,EAAE,OAAO,EAAE,cAAmB,EAAE,OAAO,EAAE,GAAG,EAAE;;;;;KAAA;IAYpD,GAAG,CAAC,IAAI,EAAE,UAAU,GAAG,OAAO,CAAC,eAAe,CAAC;IAwC/C,KAAK,CAAC,IAAI,EAAE,YAAY;IAUxB,IAAI,CAAC,IAAI,EAAE,WAAW;IAUtB,MAAM,CAAC,IAAI,EAAE,aAAa;IAUhC,IAAI,MAAM;;MAIT;CACF;AAED,eAAe,MAAM,CAAA"}
@@ -0,0 +1,75 @@
1
+ import Uri from '../uri';
2
+ import { concatRecords, ensureNoQueryParamsInDev, makeRequest, throwErrorIfFieldsMissing, throwErrorIfQueryParams, } from './request_helpers';
3
+ export class Client {
4
+ version = '';
5
+ defaultHeaders = {};
6
+ uri;
7
+ constructor({ version, defaultHeaders = {}, session, app }) {
8
+ this.version = version;
9
+ this.uri = new Uri({ session, app });
10
+ this.defaultHeaders = {
11
+ Accept: 'application/vnd.api+json',
12
+ 'Content-Type': 'application/json',
13
+ 'X-PCO-API-Version': version,
14
+ ...this.uri.headers,
15
+ ...defaultHeaders,
16
+ };
17
+ }
18
+ async get(args) {
19
+ const { walk, ...data } = args.data;
20
+ const isWalking = Boolean(walk);
21
+ const { defaultHeaders } = this.config;
22
+ const headers = { ...defaultHeaders, ...args.headers };
23
+ const url = this.uri.appUrl(args.url);
24
+ await throwErrorIfQueryParams(url);
25
+ const requestArgs = { data, url, action: 'GET', headers };
26
+ const walkRequest = ({ url: requestUrl, data: d = { fields: {} }, acc = { data: [], included: [], meta: {}, links: {} }, ...options }) => {
27
+ return makeRequest({
28
+ action: 'GET',
29
+ data: d,
30
+ url: requestUrl,
31
+ ...options,
32
+ headers,
33
+ }).then(({ links, ...rest }) => {
34
+ const records = Array.isArray(rest.data) ? concatRecords(acc, rest) : rest;
35
+ // `next` will have our params in the link so we do not want to pass them back in
36
+ if (links?.next) {
37
+ return walkRequest({ ...options, data: d, url: links.next, acc: records });
38
+ }
39
+ else {
40
+ return records;
41
+ }
42
+ });
43
+ };
44
+ const handler = isWalking ? walkRequest : makeRequest;
45
+ return throwErrorIfFieldsMissing(handler, requestArgs);
46
+ }
47
+ async patch(args) {
48
+ const { defaultHeaders } = this.config;
49
+ const headers = { ...defaultHeaders, ...args.headers };
50
+ const url = this.uri.appUrl(args.url);
51
+ const requestArgs = { data: args.data, url, action: 'PATCH', headers };
52
+ return ensureNoQueryParamsInDev(makeRequest, requestArgs);
53
+ }
54
+ async post(args) {
55
+ const { defaultHeaders } = this.config;
56
+ const headers = { ...defaultHeaders, ...args.headers };
57
+ const url = this.uri.appUrl(args.url);
58
+ const requestArgs = { ...args, data: args.data, url, action: 'POST', headers };
59
+ return ensureNoQueryParamsInDev(makeRequest, requestArgs);
60
+ }
61
+ async delete(args) {
62
+ const { defaultHeaders } = this.config;
63
+ const headers = { ...defaultHeaders, ...args.headers };
64
+ const url = this.uri.appUrl(args.url);
65
+ const requestArgs = { url, action: 'DELETE', headers };
66
+ return makeRequest(requestArgs);
67
+ }
68
+ get config() {
69
+ return {
70
+ defaultHeaders: this.defaultHeaders,
71
+ };
72
+ }
73
+ }
74
+ export default Client;
75
+ //# sourceMappingURL=client.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"client.js","sourceRoot":"","sources":["../../../src/utils/client/client.ts"],"names":[],"mappings":"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","sourcesContent":["import { JSONAPIResponse } from '@planningcenter/chat-core'\nimport Uri from '../uri'\nimport {\n concatRecords,\n ensureNoQueryParamsInDev,\n makeRequest,\n MakeRequestArgs,\n throwErrorIfFieldsMissing,\n throwErrorIfQueryParams,\n} from './request_helpers'\nimport {\n ApiClient,\n DeleteRequest,\n GetRequest,\n PatchRequest,\n PostRequest,\n WalkRequest,\n} from './types'\n\nexport class Client implements ApiClient {\n version: string = ''\n defaultHeaders: Record<string, string> = {}\n uri: Uri\n\n constructor({ version, defaultHeaders = {}, session, app }) {\n this.version = version\n this.uri = new Uri({ session, app })\n this.defaultHeaders = {\n Accept: 'application/vnd.api+json',\n 'Content-Type': 'application/json',\n 'X-PCO-API-Version': version,\n ...this.uri.headers,\n ...defaultHeaders,\n }\n }\n\n async get(args: GetRequest): Promise<JSONAPIResponse> {\n const { walk, ...data } = args.data\n const isWalking = Boolean(walk)\n const { defaultHeaders } = this.config\n const headers = { ...defaultHeaders, ...args.headers }\n const url = this.uri.appUrl(args.url)\n\n await throwErrorIfQueryParams(url)\n\n const requestArgs: MakeRequestArgs = { data, url, action: 'GET', headers }\n\n const walkRequest = ({\n url: requestUrl,\n data: d = { fields: {} },\n acc = { data: [], included: [], meta: {}, links: {} },\n ...options\n }: WalkRequest) => {\n return makeRequest({\n action: 'GET',\n data: d,\n url: requestUrl,\n ...options,\n headers,\n }).then(({ links, ...rest }) => {\n const records = Array.isArray(rest.data) ? concatRecords(acc, rest) : rest\n\n // `next` will have our params in the link so we do not want to pass them back in\n if (links?.next) {\n return walkRequest({ ...options, data: d, url: links.next, acc: records })\n } else {\n return records\n }\n })\n }\n\n const handler = isWalking ? walkRequest : makeRequest\n\n return throwErrorIfFieldsMissing(handler, requestArgs)\n }\n\n async patch(args: PatchRequest) {\n const { defaultHeaders } = this.config\n const headers = { ...defaultHeaders, ...args.headers }\n const url = this.uri.appUrl(args.url)\n\n const requestArgs: MakeRequestArgs = { data: args.data, url, action: 'PATCH', headers }\n\n return ensureNoQueryParamsInDev(makeRequest, requestArgs)\n }\n\n async post(args: PostRequest) {\n const { defaultHeaders } = this.config\n const headers = { ...defaultHeaders, ...args.headers }\n const url = this.uri.appUrl(args.url)\n\n const requestArgs: MakeRequestArgs = { ...args, data: args.data, url, action: 'POST', headers }\n\n return ensureNoQueryParamsInDev(makeRequest, requestArgs)\n }\n\n async delete(args: DeleteRequest) {\n const { defaultHeaders } = this.config\n const headers = { ...defaultHeaders, ...args.headers }\n const url = this.uri.appUrl(args.url)\n\n const requestArgs: MakeRequestArgs = { url, action: 'DELETE', headers }\n\n return makeRequest(requestArgs)\n }\n\n get config() {\n return {\n defaultHeaders: this.defaultHeaders,\n }\n }\n}\n\nexport default Client\n"]}
@@ -0,0 +1,2 @@
1
+ export * from './client';
2
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/utils/client/index.ts"],"names":[],"mappings":"AAAA,cAAc,UAAU,CAAA"}
@@ -0,0 +1,2 @@
1
+ export * from './client';
2
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/utils/client/index.ts"],"names":[],"mappings":"AAAA,cAAc,UAAU,CAAA","sourcesContent":["export * from './client'\n"]}
@@ -0,0 +1,20 @@
1
+ import { Accumulator, RequestData } from './types';
2
+ export type MakeRequestArgs = {
3
+ action: 'GET' | 'POST' | 'PATCH' | 'DELETE';
4
+ url: string;
5
+ data?: Partial<RequestData>;
6
+ headers: Record<string, string>;
7
+ };
8
+ export declare const makeRequest: ({ action, url, data, headers }: MakeRequestArgs) => Promise<any>;
9
+ export declare const concatRecords: (records: Accumulator, moreRecords: Accumulator) => {
10
+ data: Record<string, unknown>[];
11
+ included: Record<string, unknown>[];
12
+ meta: any;
13
+ };
14
+ export declare const throwErrorIfFieldsMissing: (walk: any, args: any) => Promise<any>;
15
+ export declare const friendlyErrors: (walk: any, args: any) => Promise<any>;
16
+ export declare const noQueryParamsFriendlyErrors: (request: any, args: any) => Promise<any>;
17
+ export declare const ensureFieldsInDev: (walk: any, args: any) => Promise<any>;
18
+ export declare const ensureNoQueryParamsInDev: (request: any, args: any) => Promise<any>;
19
+ export declare const throwErrorIfQueryParams: (url: any) => Promise<void>;
20
+ //# sourceMappingURL=request_helpers.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"request_helpers.d.ts","sourceRoot":"","sources":["../../../src/utils/client/request_helpers.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,WAAW,EAAE,WAAW,EAAE,MAAM,SAAS,CAAA;AAElD,MAAM,MAAM,eAAe,GAAG;IAC5B,MAAM,EAAE,KAAK,GAAG,MAAM,GAAG,OAAO,GAAG,QAAQ,CAAA;IAC3C,GAAG,EAAE,MAAM,CAAA;IACX,IAAI,CAAC,EAAE,OAAO,CAAC,WAAW,CAAC,CAAA;IAC3B,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;CAChC,CAAA;AAED,eAAO,MAAM,WAAW,mCAAsD,eAAe,iBA+B5F,CAAA;AAcD,eAAO,MAAM,aAAa,YAAa,WAAW,eAAe,WAAW;;;;CAM1E,CAAA;AAEF,eAAO,MAAM,yBAAyB,wCAuBrC,CAAA;AAED,eAAO,MAAM,cAAc,wCAGC,CAAA;AAE5B,eAAO,MAAM,2BAA2B,2CAGZ,CAAA;AAI5B,eAAO,MAAM,iBAAiB,wCAAyC,CAAA;AAEvE,eAAO,MAAM,wBAAwB,2CAAsD,CAAA;AAE3F,eAAO,MAAM,uBAAuB,6BAMnC,CAAA"}
@@ -0,0 +1,83 @@
1
+ import _ from 'lodash';
2
+ import URI from 'urijs';
3
+ import { transformRequestData } from './transform_request_data';
4
+ import transformResponse from './transform_response';
5
+ export const makeRequest = ({ action = 'GET', url, data = {}, headers = {} }) => {
6
+ // break apart url so we can reconstruct the url with the query params
7
+ let uri = new URI(url);
8
+ const query = transformRequestData(data);
9
+ const urlQuery = uri.query(true);
10
+ // This likely doesn't matter but will enforce consistent ordering of query params
11
+ const combinedQuery = Object.entries({ ...query, ...urlQuery })
12
+ .sort()
13
+ .reduce((obj, [key, value]) => {
14
+ obj[key] = value;
15
+ return obj;
16
+ }, {});
17
+ if (action === 'GET') {
18
+ uri = uri.query(combinedQuery);
19
+ }
20
+ const body = ['POST', 'PATCH'].includes(action) ? JSON.stringify(data) : undefined;
21
+ return fetch(decodeURIComponent(uri.toString()), {
22
+ method: action,
23
+ headers,
24
+ body,
25
+ }).then(response => {
26
+ if (response.ok) {
27
+ return response.text().then(t => (t === '' ? '' : JSON.parse(t)));
28
+ }
29
+ else {
30
+ return Promise.reject(response);
31
+ }
32
+ });
33
+ };
34
+ const STANDARD_META_ATTRIBUTES = [
35
+ 'total_count',
36
+ 'count',
37
+ 'prev',
38
+ 'next',
39
+ 'can_order_by',
40
+ 'can_query_by',
41
+ 'can_include',
42
+ 'can_filter',
43
+ 'parent',
44
+ ];
45
+ export const concatRecords = (records, moreRecords) => ({
46
+ data: [...records.data, ...moreRecords.data],
47
+ included: [...records.included, ...moreRecords.included],
48
+ // Because custom meta can be computed on a per-page bases,
49
+ // it is safer to remove all custom meta when concatenating multiple pages of data
50
+ meta: _.pick(moreRecords.meta, STANDARD_META_ATTRIBUTES),
51
+ });
52
+ export const throwErrorIfFieldsMissing = async (walk, args) => {
53
+ const fields = args?.data?.fields;
54
+ if (!fields) {
55
+ throw new Error(`Must pass fields for request: ${args.url}`);
56
+ }
57
+ const fieldTypes = Object.keys(fields);
58
+ const response = await walk(args);
59
+ const dataTypes = _(response.data).castArray().map('type').value();
60
+ const includedTypes = _.map(response.included, 'type');
61
+ const responseTypes = _.uniq(dataTypes.concat(includedTypes));
62
+ const missingFields = _.difference(responseTypes, fieldTypes).filter(t => t);
63
+ if (missingFields.length > 0) {
64
+ throw new Error(`Must include fields for types: ${JSON.stringify(missingFields)} for request ${args.url}`);
65
+ }
66
+ return transformResponse(response);
67
+ };
68
+ export const friendlyErrors = (walk, args) => throwErrorIfQueryParams(args.url)
69
+ .then(() => throwErrorIfFieldsMissing(walk, args))
70
+ .then(transformResponse);
71
+ export const noQueryParamsFriendlyErrors = (request, args) => throwErrorIfQueryParams(args.url)
72
+ .then(() => request(args))
73
+ .then(transformResponse);
74
+ const passthrough = async (walk, args) => Promise.resolve(transformResponse(await walk(args)));
75
+ export const ensureFieldsInDev = __DEV__ ? friendlyErrors : passthrough;
76
+ export const ensureNoQueryParamsInDev = __DEV__ ? noQueryParamsFriendlyErrors : passthrough;
77
+ export const throwErrorIfQueryParams = url => {
78
+ if (new URI(url).search().length) {
79
+ throw new Error('Must pass query params as data arg');
80
+ }
81
+ return Promise.resolve();
82
+ };
83
+ //# sourceMappingURL=request_helpers.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"request_helpers.js","sourceRoot":"","sources":["../../../src/utils/client/request_helpers.ts"],"names":[],"mappings":"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","sourcesContent":["import _ from 'lodash'\nimport URI from 'urijs'\nimport { transformRequestData } from './transform_request_data'\nimport transformResponse from './transform_response'\nimport { Accumulator, RequestData } from './types'\n\nexport type MakeRequestArgs = {\n action: 'GET' | 'POST' | 'PATCH' | 'DELETE'\n url: string\n data?: Partial<RequestData>\n headers: Record<string, string>\n}\n\nexport const makeRequest = ({ action = 'GET', url, data = {}, headers = {} }: MakeRequestArgs) => {\n // break apart url so we can reconstruct the url with the query params\n let uri = new URI(url)\n const query = transformRequestData(data)\n const urlQuery = uri.query(true)\n\n // This likely doesn't matter but will enforce consistent ordering of query params\n const combinedQuery = Object.entries({ ...query, ...urlQuery })\n .sort()\n .reduce((obj, [key, value]) => {\n obj[key] = value\n return obj\n }, {})\n\n if (action === 'GET') {\n uri = uri.query(combinedQuery)\n }\n\n const body = ['POST', 'PATCH'].includes(action) ? JSON.stringify(data) : undefined\n\n return fetch(decodeURIComponent(uri.toString()), {\n method: action,\n headers,\n body,\n }).then(response => {\n if (response.ok) {\n return response.text().then(t => (t === '' ? '' : JSON.parse(t)))\n } else {\n return Promise.reject(response)\n }\n })\n}\n\nconst STANDARD_META_ATTRIBUTES = [\n 'total_count',\n 'count',\n 'prev',\n 'next',\n 'can_order_by',\n 'can_query_by',\n 'can_include',\n 'can_filter',\n 'parent',\n]\n\nexport const concatRecords = (records: Accumulator, moreRecords: Accumulator) => ({\n data: [...records.data, ...moreRecords.data],\n included: [...records.included, ...moreRecords.included],\n // Because custom meta can be computed on a per-page bases,\n // it is safer to remove all custom meta when concatenating multiple pages of data\n meta: _.pick(moreRecords.meta, STANDARD_META_ATTRIBUTES),\n})\n\nexport const throwErrorIfFieldsMissing = async (walk, args) => {\n const fields = args?.data?.fields\n\n if (!fields) {\n throw new Error(`Must pass fields for request: ${args.url}`)\n }\n\n const fieldTypes = Object.keys(fields)\n\n const response = await walk(args)\n\n const dataTypes = _(response.data).castArray().map('type').value()\n const includedTypes = _.map(response.included, 'type')\n const responseTypes = _.uniq(dataTypes.concat(includedTypes))\n const missingFields = _.difference(responseTypes, fieldTypes).filter(t => t)\n\n if (missingFields.length > 0) {\n throw new Error(\n `Must include fields for types: ${JSON.stringify(missingFields)} for request ${args.url}`\n )\n }\n\n return transformResponse(response)\n}\n\nexport const friendlyErrors = (walk, args) =>\n throwErrorIfQueryParams(args.url)\n .then(() => throwErrorIfFieldsMissing(walk, args))\n .then(transformResponse)\n\nexport const noQueryParamsFriendlyErrors = (request, args) =>\n throwErrorIfQueryParams(args.url)\n .then(() => request(args))\n .then(transformResponse)\n\nconst passthrough = async (walk, args) => Promise.resolve(transformResponse(await walk(args)))\n\nexport const ensureFieldsInDev = __DEV__ ? friendlyErrors : passthrough\n\nexport const ensureNoQueryParamsInDev = __DEV__ ? noQueryParamsFriendlyErrors : passthrough\n\nexport const throwErrorIfQueryParams = url => {\n if (new URI(url).search().length) {\n throw new Error('Must pass query params as data arg')\n }\n\n return Promise.resolve()\n}\n"]}
@@ -0,0 +1,8 @@
1
+ import { RequestData } from './types';
2
+ export declare const transformRequestData: ({ fields, where, include, perPage, ...restData }: Partial<RequestData>) => any;
3
+ export declare function flattenAttribute(obj: any, key: any): any;
4
+ export declare function buildQuery({ key, value }: {
5
+ key: any;
6
+ value: any;
7
+ }): any;
8
+ //# sourceMappingURL=transform_request_data.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"transform_request_data.d.ts","sourceRoot":"","sources":["../../../src/utils/client/transform_request_data.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,WAAW,EAAE,MAAM,SAAS,CAAA;AAErC,eAAO,MAAM,oBAAoB,qDAM9B,OAAO,CAAC,WAAW,CAAC,QAOtB,CAAA;AAED,wBAAgB,gBAAgB,CAAC,GAAG,KAAA,EAAE,GAAG,KAAA,OAaxC;AAED,wBAAgB,UAAU,CAAC,EAAE,GAAG,EAAE,KAAK,EAAE;;;CAAA,OAaxC"}
@@ -0,0 +1,33 @@
1
+ import { isObject, reduce, isArray } from 'lodash';
2
+ import { keysToSnakeCase } from './utils';
3
+ export const transformRequestData = ({ fields, where, include, perPage = 100, ...restData }) => {
4
+ return {
5
+ ...flattenAttribute(fields, 'fields'),
6
+ ...flattenAttribute(where, 'where'),
7
+ ...keysToSnakeCase({ perPage, ...restData }),
8
+ include: Array.isArray(include) ? include.join(',') : include,
9
+ };
10
+ };
11
+ export function flattenAttribute(obj, key) {
12
+ if (!isObject(obj))
13
+ return { [key]: obj };
14
+ return reduce(obj, (acc, value, attr) => {
15
+ return {
16
+ ...acc,
17
+ ...buildQuery({ key: `${key}[${attr}]`, value }),
18
+ };
19
+ }, {});
20
+ }
21
+ export function buildQuery({ key, value }) {
22
+ if (isArray(value))
23
+ return { [key]: value.join(',') };
24
+ if (isObject(value)) {
25
+ const keys = Object.keys(value);
26
+ return keys.reduce((acc, subKey) => ({
27
+ ...acc,
28
+ ...buildQuery({ key: `${key}[${subKey}]`, value: value[subKey] }),
29
+ }), {});
30
+ }
31
+ return { [key]: value };
32
+ }
33
+ //# sourceMappingURL=transform_request_data.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"transform_request_data.js","sourceRoot":"","sources":["../../../src/utils/client/transform_request_data.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,QAAQ,CAAA;AAClD,OAAO,EAAE,eAAe,EAAE,MAAM,SAAS,CAAA;AAGzC,MAAM,CAAC,MAAM,oBAAoB,GAAG,CAAC,EACnC,MAAM,EACN,KAAK,EACL,OAAO,EACP,OAAO,GAAG,GAAG,EACb,GAAG,QAAQ,EACU,EAAE,EAAE;IACzB,OAAO;QACL,GAAG,gBAAgB,CAAC,MAAM,EAAE,QAAQ,CAAC;QACrC,GAAG,gBAAgB,CAAC,KAAK,EAAE,OAAO,CAAC;QACnC,GAAG,eAAe,CAAC,EAAE,OAAO,EAAE,GAAG,QAAQ,EAAE,CAAC;QAC5C,OAAO,EAAE,KAAK,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,OAAO;KAC9D,CAAA;AACH,CAAC,CAAA;AAED,MAAM,UAAU,gBAAgB,CAAC,GAAG,EAAE,GAAG;IACvC,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC;QAAE,OAAO,EAAE,CAAC,GAAG,CAAC,EAAE,GAAG,EAAE,CAAA;IAEzC,OAAO,MAAM,CACX,GAAG,EACH,CAAC,GAAG,EAAE,KAAK,EAAE,IAAI,EAAE,EAAE;QACnB,OAAO;YACL,GAAG,GAAG;YACN,GAAG,UAAU,CAAC,EAAE,GAAG,EAAE,GAAG,GAAG,IAAI,IAAI,GAAG,EAAE,KAAK,EAAE,CAAC;SACjD,CAAA;IACH,CAAC,EACD,EAAE,CACH,CAAA;AACH,CAAC;AAED,MAAM,UAAU,UAAU,CAAC,EAAE,GAAG,EAAE,KAAK,EAAE;IACvC,IAAI,OAAO,CAAC,KAAK,CAAC;QAAE,OAAO,EAAE,CAAC,GAAG,CAAC,EAAE,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,CAAA;IACrD,IAAI,QAAQ,CAAC,KAAK,CAAC,EAAE,CAAC;QACpB,MAAM,IAAI,GAAG,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAA;QAC/B,OAAO,IAAI,CAAC,MAAM,CAChB,CAAC,GAAG,EAAE,MAAM,EAAE,EAAE,CAAC,CAAC;YAChB,GAAG,GAAG;YACN,GAAG,UAAU,CAAC,EAAE,GAAG,EAAE,GAAG,GAAG,IAAI,MAAM,GAAG,EAAE,KAAK,EAAE,KAAK,CAAC,MAAM,CAAC,EAAE,CAAC;SAClE,CAAC,EACF,EAAE,CACH,CAAA;IACH,CAAC;IACD,OAAO,EAAE,CAAC,GAAG,CAAC,EAAE,KAAK,EAAE,CAAA;AACzB,CAAC","sourcesContent":["import { isObject, reduce, isArray } from 'lodash'\nimport { keysToSnakeCase } from './utils'\nimport { RequestData } from './types'\n\nexport const transformRequestData = ({\n fields,\n where,\n include,\n perPage = 100,\n ...restData\n}: Partial<RequestData>) => {\n return {\n ...flattenAttribute(fields, 'fields'),\n ...flattenAttribute(where, 'where'),\n ...keysToSnakeCase({ perPage, ...restData }),\n include: Array.isArray(include) ? include.join(',') : include,\n }\n}\n\nexport function flattenAttribute(obj, key) {\n if (!isObject(obj)) return { [key]: obj }\n\n return reduce(\n obj,\n (acc, value, attr) => {\n return {\n ...acc,\n ...buildQuery({ key: `${key}[${attr}]`, value }),\n }\n },\n {}\n )\n}\n\nexport function buildQuery({ key, value }) {\n if (isArray(value)) return { [key]: value.join(',') }\n if (isObject(value)) {\n const keys = Object.keys(value)\n return keys.reduce(\n (acc, subKey) => ({\n ...acc,\n ...buildQuery({ key: `${key}[${subKey}]`, value: value[subKey] }),\n }),\n {}\n )\n }\n return { [key]: value }\n}\n"]}
@@ -0,0 +1,3 @@
1
+ declare const transformResponse: any;
2
+ export default transformResponse;
3
+ //# sourceMappingURL=transform_response.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"transform_response.d.ts","sourceRoot":"","sources":["../../../src/utils/client/transform_response.ts"],"names":[],"mappings":"AA8FA,QAAA,MAAM,iBAAiB,KAAyD,CAAA;AAEhF,eAAe,iBAAiB,CAAA"}
@@ -0,0 +1,84 @@
1
+ import _ from 'lodash';
2
+ import inflection from 'lodash-inflection/lib/lodash-inflection';
3
+ import { keysToCamelCase } from './utils';
4
+ _.mixin({ ...inflection });
5
+ // Teach some bad grammar
6
+ _.singular(/^(media)$/i, '$1');
7
+ _.plural(/^(media)$/i, '$1');
8
+ // eslint-disable-next-line eqeqeq
9
+ const transformId = id => _.thru(parseInt(id, 10), int => (int == id ? int : id));
10
+ const transformRelationships = relationships => {
11
+ return Object.keys(relationships || {}).reduce((acc, key) => {
12
+ const relationship = relationships[key];
13
+ if (_.isArray(relationship.data)) {
14
+ const ids = _.map(relationship.data, ({ id }) => transformId(id));
15
+ return { ...acc, [`${_.singularize(key)}_ids`]: ids };
16
+ }
17
+ else {
18
+ const id = _.get(relationship, 'data.id');
19
+ const type = _.get(relationship, 'data.type', null);
20
+ return {
21
+ ...acc,
22
+ [`${key}_id`]: id ? transformId(id) : null,
23
+ [`${key}_type`]: type,
24
+ };
25
+ }
26
+ }, {});
27
+ };
28
+ const addIncludedRecords = (relationships, included, seen, parent) => {
29
+ return Object.keys(relationships || {}).reduce((acc, key) => {
30
+ const relationship = relationships[key];
31
+ if (_.isArray(relationship.data)) {
32
+ const records = _(relationship.data)
33
+ .map(elem => _.find(included, elem))
34
+ .compact() // account for orphans
35
+ .value();
36
+ return _.set(acc, _.pluralize(key), _.map(records, record => transformRecord(record, included, seen)));
37
+ }
38
+ else {
39
+ const [id, type] = _.at(relationship, ['data.id', 'data.type']);
40
+ if (id && type) {
41
+ const record = _.find(included, { id, type });
42
+ return _.set(acc, key, record ? transformRecord(record, included, seen) : null);
43
+ }
44
+ else {
45
+ return acc;
46
+ }
47
+ }
48
+ }, parent);
49
+ };
50
+ const transformRecord = (record, included, seen) => {
51
+ if (!record)
52
+ return record;
53
+ const { id, attributes, links, relationships, type } = record;
54
+ if (seen.has(record)) {
55
+ return seen.get(record);
56
+ }
57
+ else {
58
+ const transformed = {
59
+ id: transformId(id),
60
+ type,
61
+ links,
62
+ ...transformRelationships(relationships),
63
+ ..._.mapKeys(attributes, (v, k) => (k === 'length' ? `${type.charAt(0).toLowerCase()}${type.slice(1)}Length` : k), {}),
64
+ };
65
+ seen.set(record, transformed);
66
+ return addIncludedRecords(relationships, included, seen, transformed);
67
+ }
68
+ };
69
+ const defaultTransformResponse = response => {
70
+ if (_.isEmpty(response))
71
+ return response;
72
+ const { data, included, meta, links } = response;
73
+ const seen = new WeakMap();
74
+ if (_.isArray(data)) {
75
+ const result = data.map(d => transformRecord(d, included, seen));
76
+ return { data: result, meta, links, ...data };
77
+ }
78
+ else {
79
+ return { data: { ...transformRecord(data, included, seen) }, meta, links };
80
+ }
81
+ };
82
+ const transformResponse = _.flowRight(keysToCamelCase, defaultTransformResponse);
83
+ export default transformResponse;
84
+ //# sourceMappingURL=transform_response.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"transform_response.js","sourceRoot":"","sources":["../../../src/utils/client/transform_response.ts"],"names":[],"mappings":"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","sourcesContent":["import _ from 'lodash'\nimport inflection from 'lodash-inflection/lib/lodash-inflection'\nimport { keysToCamelCase } from './utils'\n\n_.mixin({ ...inflection })\n\n// Teach some bad grammar\n_.singular(/^(media)$/i, '$1')\n_.plural(/^(media)$/i, '$1')\n\n// eslint-disable-next-line eqeqeq\nconst transformId = id => _.thru(parseInt(id, 10), int => (int == id ? int : id))\n\nconst transformRelationships = relationships => {\n return Object.keys(relationships || {}).reduce((acc, key) => {\n const relationship = relationships[key]\n if (_.isArray(relationship.data)) {\n const ids = _.map(relationship.data, ({ id }) => transformId(id))\n return { ...acc, [`${_.singularize(key)}_ids`]: ids }\n } else {\n const id = _.get(relationship, 'data.id')\n const type = _.get(relationship, 'data.type', null)\n return {\n ...acc,\n [`${key}_id`]: id ? transformId(id) : null,\n [`${key}_type`]: type,\n }\n }\n }, {})\n}\n\nconst addIncludedRecords = (relationships, included, seen, parent) => {\n return Object.keys(relationships || {}).reduce((acc, key) => {\n const relationship = relationships[key]\n if (_.isArray(relationship.data)) {\n const records = _(relationship.data)\n .map(elem => _.find(included, elem))\n .compact() // account for orphans\n .value()\n return _.set(\n acc,\n _.pluralize(key),\n _.map(records, record => transformRecord(record, included, seen))\n )\n } else {\n const [id, type] = _.at(relationship, ['data.id', 'data.type'])\n if (id && type) {\n const record = _.find(included, { id, type })\n return _.set(acc, key, record ? transformRecord(record, included, seen) : null)\n } else {\n return acc\n }\n }\n }, parent)\n}\n\nconst transformRecord = (record, included, seen) => {\n if (!record) return record\n const { id, attributes, links, relationships, type } = record\n\n if (seen.has(record)) {\n return seen.get(record)\n } else {\n const transformed = {\n id: transformId(id),\n type,\n links,\n ...transformRelationships(relationships),\n ..._.mapKeys(\n attributes,\n (v, k) => (k === 'length' ? `${type.charAt(0).toLowerCase()}${type.slice(1)}Length` : k),\n {}\n ),\n }\n\n seen.set(record, transformed)\n\n return addIncludedRecords(relationships, included, seen, transformed)\n }\n}\n\nconst defaultTransformResponse = response => {\n if (_.isEmpty(response)) return response\n const { data, included, meta, links } = response\n const seen = new WeakMap()\n\n if (_.isArray(data)) {\n const result = data.map(d => transformRecord(d, included, seen))\n return { data: result, meta, links, ...data }\n } else {\n return { data: { ...transformRecord(data, included, seen) }, meta, links }\n }\n}\n\nconst transformResponse = _.flowRight(keysToCamelCase, defaultTransformResponse)\n\nexport default transformResponse\n"]}
@@ -0,0 +1,5 @@
1
+ declare const toSentence: (words: any, lastWordConnector?: string) => any;
2
+ declare const keysToCamelCase: (elem: any) => any;
3
+ declare const keysToSnakeCase: (elem: any) => any;
4
+ export { keysToCamelCase, keysToSnakeCase, toSentence };
5
+ //# sourceMappingURL=utils.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../../../src/utils/client/utils.ts"],"names":[],"mappings":"AAEA,QAAA,MAAM,UAAU,iDAGf,CAAA;AAoCD,QAAA,MAAM,eAAe,oBAAkB,CAAA;AACvC,QAAA,MAAM,eAAe,oBAAwC,CAAA;AAE7D,OAAO,EAAE,eAAe,EAAE,eAAe,EAAE,UAAU,EAAE,CAAA"}
@@ -0,0 +1,36 @@
1
+ import _ from 'lodash';
2
+ const toSentence = (words, lastWordConnector = 'and') => {
3
+ lastWordConnector = `${words.length > 2 ? ',' : ''} ${lastWordConnector}`;
4
+ return words.join(', ').replace(/,\s([^,]+$)/, `${lastWordConnector} $1`);
5
+ };
6
+ const toCamel = s => s.replace(/(_[a-z])/g, m => m.toUpperCase().replace('_', ''));
7
+ const toSnake = s => (s.startsWith('_') ? `_${_.snakeCase(s)}` : _.snakeCase(s));
8
+ const actualObject = elem => {
9
+ return !((_.isObject(elem) && (_.isArray(elem) || _.isFunction(elem))) || !_.isObject(elem));
10
+ };
11
+ // map over tree (object) and apply f to each key
12
+ const walker = f => {
13
+ const seen = new WeakMap();
14
+ const convert = elem => {
15
+ if (actualObject(elem)) {
16
+ return _.reduce(elem, (memo, obj, key) => {
17
+ if (!seen.has(elem)) {
18
+ seen.set(elem, memo);
19
+ }
20
+ memo[f(key)] = seen.get(obj) || convert(obj);
21
+ return memo;
22
+ }, {});
23
+ }
24
+ else if (_.isArray(elem)) {
25
+ return _.map(elem, convert);
26
+ }
27
+ else {
28
+ return elem;
29
+ }
30
+ };
31
+ return convert;
32
+ };
33
+ const keysToCamelCase = walker(toCamel);
34
+ const keysToSnakeCase = walker(k => (k < 0 ? k : toSnake(k)));
35
+ export { keysToCamelCase, keysToSnakeCase, toSentence };
36
+ //# sourceMappingURL=utils.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"utils.js","sourceRoot":"","sources":["../../../src/utils/client/utils.ts"],"names":[],"mappings":"AAAA,OAAO,CAAC,MAAM,QAAQ,CAAA;AAEtB,MAAM,UAAU,GAAG,CAAC,KAAK,EAAE,iBAAiB,GAAG,KAAK,EAAE,EAAE;IACtD,iBAAiB,GAAG,GAAG,KAAK,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,IAAI,iBAAiB,EAAE,CAAA;IACzE,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,OAAO,CAAC,aAAa,EAAE,GAAG,iBAAiB,KAAK,CAAC,CAAA;AAC3E,CAAC,CAAA;AAED,MAAM,OAAO,GAAG,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC,WAAW,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,WAAW,EAAE,CAAC,OAAO,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC,CAAA;AAElF,MAAM,OAAO,GAAG,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,CAAA;AAEhF,MAAM,YAAY,GAAG,IAAI,CAAC,EAAE;IAC1B,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAA;AAC9F,CAAC,CAAA;AAED,iDAAiD;AACjD,MAAM,MAAM,GAAG,CAAC,CAAC,EAAE;IACjB,MAAM,IAAI,GAAG,IAAI,OAAO,EAAE,CAAA;IAE1B,MAAM,OAAO,GAAG,IAAI,CAAC,EAAE;QACrB,IAAI,YAAY,CAAC,IAAI,CAAC,EAAE,CAAC;YACvB,OAAO,CAAC,CAAC,MAAM,CACb,IAAI,EACJ,CAAC,IAAI,EAAE,GAAG,EAAE,GAAG,EAAE,EAAE;gBACjB,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC;oBACpB,IAAI,CAAC,GAAG,CAAC,IAAI,EAAE,IAAI,CAAC,CAAA;gBACtB,CAAC;gBACD,IAAI,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,GAAG,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,IAAI,OAAO,CAAC,GAAG,CAAC,CAAA;gBAC5C,OAAO,IAAI,CAAA;YACb,CAAC,EACD,EAAE,CACH,CAAA;QACH,CAAC;aAAM,IAAI,CAAC,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,CAAC;YAC3B,OAAO,CAAC,CAAC,GAAG,CAAC,IAAI,EAAE,OAAO,CAAC,CAAA;QAC7B,CAAC;aAAM,CAAC;YACN,OAAO,IAAI,CAAA;QACb,CAAC;IACH,CAAC,CAAA;IACD,OAAO,OAAO,CAAA;AAChB,CAAC,CAAA;AAED,MAAM,eAAe,GAAG,MAAM,CAAC,OAAO,CAAC,CAAA;AACvC,MAAM,eAAe,GAAG,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC,CAAA;AAE7D,OAAO,EAAE,eAAe,EAAE,eAAe,EAAE,UAAU,EAAE,CAAA","sourcesContent":["import _ from 'lodash'\n\nconst toSentence = (words, lastWordConnector = 'and') => {\n lastWordConnector = `${words.length > 2 ? ',' : ''} ${lastWordConnector}`\n return words.join(', ').replace(/,\\s([^,]+$)/, `${lastWordConnector} $1`)\n}\n\nconst toCamel = s => s.replace(/(_[a-z])/g, m => m.toUpperCase().replace('_', ''))\n\nconst toSnake = s => (s.startsWith('_') ? `_${_.snakeCase(s)}` : _.snakeCase(s))\n\nconst actualObject = elem => {\n return !((_.isObject(elem) && (_.isArray(elem) || _.isFunction(elem))) || !_.isObject(elem))\n}\n\n// map over tree (object) and apply f to each key\nconst walker = f => {\n const seen = new WeakMap()\n\n const convert = elem => {\n if (actualObject(elem)) {\n return _.reduce(\n elem,\n (memo, obj, key) => {\n if (!seen.has(elem)) {\n seen.set(elem, memo)\n }\n memo[f(key)] = seen.get(obj) || convert(obj)\n return memo\n },\n {}\n )\n } else if (_.isArray(elem)) {\n return _.map(elem, convert)\n } else {\n return elem\n }\n }\n return convert\n}\n\nconst keysToCamelCase = walker(toCamel)\nconst keysToSnakeCase = walker(k => (k < 0 ? k : toSnake(k)))\n\nexport { keysToCamelCase, keysToSnakeCase, toSentence }\n"]}
@@ -1,4 +1,6 @@
1
1
  export * from './session';
2
2
  export * from './theme';
3
3
  export * from './styles';
4
+ export * from './client';
5
+ export * from './uri';
4
6
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/utils/index.ts"],"names":[],"mappings":"AAAA,cAAc,WAAW,CAAA;AACzB,cAAc,SAAS,CAAA;AACvB,cAAc,UAAU,CAAA"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/utils/index.ts"],"names":[],"mappings":"AAAA,cAAc,WAAW,CAAA;AACzB,cAAc,SAAS,CAAA;AACvB,cAAc,UAAU,CAAA;AACxB,cAAc,UAAU,CAAA;AACxB,cAAc,OAAO,CAAA"}
@@ -1,4 +1,6 @@
1
1
  export * from './session';
2
2
  export * from './theme';
3
3
  export * from './styles';
4
+ export * from './client';
5
+ export * from './uri';
4
6
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/utils/index.ts"],"names":[],"mappings":"AAAA,cAAc,WAAW,CAAA;AACzB,cAAc,SAAS,CAAA;AACvB,cAAc,UAAU,CAAA","sourcesContent":["export * from './session'\nexport * from './theme'\nexport * from './styles'\n"]}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/utils/index.ts"],"names":[],"mappings":"AAAA,cAAc,WAAW,CAAA;AACzB,cAAc,SAAS,CAAA;AACvB,cAAc,UAAU,CAAA;AACxB,cAAc,UAAU,CAAA;AACxB,cAAc,OAAO,CAAA","sourcesContent":["export * from './session'\nexport * from './theme'\nexport * from './styles'\nexport * from './client'\nexport * from './uri'\n"]}
@@ -1,15 +1,11 @@
1
1
  import { OAuthToken } from '../types';
2
+ import Uri from './uri';
2
3
  export type ENV = 'production' | 'staging' | 'development';
3
4
  export declare const baseUrlMap: {
4
5
  production: string;
5
6
  staging: string;
6
7
  development: string;
7
8
  };
8
- export declare const uploadUrlMap: {
9
- production: string;
10
- staging: string;
11
- development: string;
12
- };
13
9
  type SessionProps = {
14
10
  env?: ENV;
15
11
  token?: OAuthToken;
@@ -22,13 +18,14 @@ type SessionProps = {
22
18
  export declare class Session {
23
19
  env: ENV;
24
20
  token: OAuthToken | undefined;
21
+ uri: Uri;
25
22
  constructor(props?: SessionProps);
26
23
  get isAuthenticated(): boolean;
24
+ get host(): "api.planningcenteronline.com" | "api-staging.planningcenteronline.com" | "api.pco.test";
27
25
  get baseUrl(): string;
28
- get uploadUrl(): string;
29
26
  toString(): string;
30
27
  static hydrate(sessionString: string): Session;
31
28
  }
32
- export declare const session: Session;
29
+ export declare let session: Session;
33
30
  export {};
34
31
  //# sourceMappingURL=session.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"session.d.ts","sourceRoot":"","sources":["../../src/utils/session.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,UAAU,CAAA;AAErC,MAAM,MAAM,GAAG,GAAG,YAAY,GAAG,SAAS,GAAG,aAAa,CAAA;AAE1D,eAAO,MAAM,UAAU;;;;CAItB,CAAA;AAED,eAAO,MAAM,YAAY;;;;CAIxB,CAAA;AAED,KAAK,YAAY,GAAG;IAAE,GAAG,CAAC,EAAE,GAAG,CAAC;IAAC,KAAK,CAAC,EAAE,UAAU,CAAA;CAAE,GAAG,SAAS,CAAA;AAEjE;;;;GAIG;AACH,qBAAa,OAAO;IAClB,GAAG,EAAE,GAAG,CAAA;IACR,KAAK,EAAE,UAAU,GAAG,SAAS,CAAA;gBAEjB,KAAK,CAAC,EAAE,YAAY;IAMhC,IAAI,eAAe,YAElB;IAED,IAAI,OAAO,WAEV;IAED,IAAI,SAAS,WAEZ;IAED,QAAQ;IAIR,MAAM,CAAC,OAAO,CAAC,aAAa,EAAE,MAAM;CAQrC;AAED,eAAO,MAAM,OAAO,SAAsC,CAAA"}
1
+ {"version":3,"file":"session.d.ts","sourceRoot":"","sources":["../../src/utils/session.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,UAAU,CAAA;AACrC,OAAO,GAAG,MAAM,OAAO,CAAA;AAEvB,MAAM,MAAM,GAAG,GAAG,YAAY,GAAG,SAAS,GAAG,aAAa,CAAA;AAE1D,eAAO,MAAM,UAAU;;;;CAItB,CAAA;AAED,KAAK,YAAY,GAAG;IAAE,GAAG,CAAC,EAAE,GAAG,CAAC;IAAC,KAAK,CAAC,EAAE,UAAU,CAAA;CAAE,GAAG,SAAS,CAAA;AAEjE;;;;GAIG;AACH,qBAAa,OAAO;IAClB,GAAG,EAAE,GAAG,CAAA;IACR,KAAK,EAAE,UAAU,GAAG,SAAS,CAAA;IAC7B,GAAG,EAAE,GAAG,CAAA;gBAEI,KAAK,CAAC,EAAE,YAAY;IAOhC,IAAI,eAAe,YAElB;IAED,IAAI,IAAI,6FAEP;IAED,IAAI,OAAO,WAEV;IAED,QAAQ;IAIR,MAAM,CAAC,OAAO,CAAC,aAAa,EAAE,MAAM;CAQrC;AAED,eAAO,IAAI,OAAO,SAAsC,CAAA"}