@txstate-mws/sveltekit-utils 1.0.1 → 1.0.3

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/dist/api.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { InteractionEvent } from '@txstate-mws/fastify-shared';
1
+ import type { InteractionEvent, ValidatedResponse } from '@txstate-mws/fastify-shared';
2
2
  export type APIBaseQueryPayload = string | Record<string, undefined | string | number | (string | number)[]>;
3
3
  type Optional<T, K extends keyof T> = Pick<Partial<T>, K> & Omit<T, K>;
4
4
  /**
@@ -11,26 +11,54 @@ type Optional<T, K extends keyof T> = Pick<Partial<T>, K> & Omit<T, K>;
11
11
  export declare function recordNavigations(callback: (evt: InteractionEvent) => void): void;
12
12
  export declare class APIBase {
13
13
  protected apiBase: string;
14
- protected authRedirect: string;
15
- protected token?: string;
14
+ authRedirect: string;
15
+ token?: string;
16
16
  fetch: (info: RequestInfo, init?: RequestInit) => Promise<Response>;
17
17
  protected ready: () => void;
18
18
  protected readyPromise: Promise<void>;
19
19
  constructor(apiBase: string, authRedirect: string);
20
20
  init(token: string | undefined, fetch?: (info: RequestInfo, init?: RequestInit) => Promise<Response>): Promise<void>;
21
21
  stringifyQuery(query: undefined | APIBaseQueryPayload): string;
22
- protected request<ReturnType = any>(path: string, method: string, payload?: {
22
+ protected request<ReturnType = any>(path: string, method: string, opts?: {
23
23
  body?: any;
24
24
  query?: APIBaseQueryPayload;
25
- }): Promise<any>;
26
- get<ReturnType = any>(path: string, query?: APIBaseQueryPayload): Promise<any>;
27
- post<ReturnType = any>(path: string, body?: any, query?: APIBaseQueryPayload): Promise<any>;
28
- put<ReturnType = any>(path: string, body?: any, query?: APIBaseQueryPayload): Promise<any>;
29
- patch<ReturnType = any>(path: string, body?: any, query?: APIBaseQueryPayload): Promise<any>;
25
+ inlineValidation?: boolean;
26
+ }): Promise<ReturnType>;
27
+ get<ReturnType = any>(path: string, query?: APIBaseQueryPayload): Promise<ReturnType>;
28
+ /**
29
+ * Remember to use validatedPost when the user is interacting with a form. That way they
30
+ * will get inline errors.
31
+ */
32
+ post<ReturnType = any>(path: string, body?: any, query?: APIBaseQueryPayload): Promise<ReturnType>;
33
+ /**
34
+ * Remember to use validatedPut when the user is interacting with a form. That way they
35
+ * will get inline errors.
36
+ */
37
+ put<ReturnType = any>(path: string, body?: any, query?: APIBaseQueryPayload): Promise<ReturnType>;
38
+ /**
39
+ * Remember to use validatedPatch when the user is interacting with a form. That way they
40
+ * will get inline errors.
41
+ */
42
+ patch<ReturnType = any>(path: string, body?: any, query?: APIBaseQueryPayload): Promise<ReturnType>;
43
+ /**
44
+ * Use this method when the user is interacting with a form. You should expect a ValidatedResponse,
45
+ * e.g. { success: false, messages: [{ type: 'error', message: 'That name is already taken.', path: 'name' }] }
46
+ */
47
+ validatedPost<ReturnType extends ValidatedResponse = ValidatedResponse>(path: string, body?: any, query?: APIBaseQueryPayload): Promise<ReturnType>;
48
+ /**
49
+ * Use this method when the user is interacting with a form. You should expect a ValidatedResponse,
50
+ * e.g. { success: false, messages: [{ type: 'error', message: 'That name is already taken.', path: 'name' }] }
51
+ */
52
+ validatedPut<ReturnType extends ValidatedResponse = ValidatedResponse>(path: string, body?: any, query?: APIBaseQueryPayload): Promise<ReturnType>;
53
+ /**
54
+ * Use this method when the user is interacting with a form. You should expect a ValidatedResponse,
55
+ * e.g. { success: false, messages: [{ type: 'error', message: 'That name is already taken.', path: 'name' }] }
56
+ */
57
+ validatedPatch<ReturnType extends ValidatedResponse = ValidatedResponse>(path: string, body?: any, query?: APIBaseQueryPayload): Promise<ReturnType>;
30
58
  /**
31
59
  * Sending a JSON body with an HTTP DELETE is not recommended
32
60
  */
33
- delete<ReturnType = any>(path: string, query?: APIBaseQueryPayload, body?: any): Promise<any>;
61
+ delete<ReturnType = any>(path: string, query?: APIBaseQueryPayload, body?: any): Promise<ReturnType>;
34
62
  graphql<ReturnType = any>(query: string, variables?: any, querySignature?: string): Promise<ReturnType>;
35
63
  protected analyticsQueue: InteractionEvent[];
36
64
  recordInteraction(evt: Optional<InteractionEvent, 'screen'>): void;
package/dist/api.js CHANGED
@@ -12,8 +12,17 @@ import { afterNavigate } from '$app/navigation';
12
12
  * Must be called from a svelte component. Should usually be your root +layout.svelte.
13
13
  */
14
14
  export function recordNavigations(callback) {
15
+ let timer = 0;
16
+ let from;
15
17
  afterNavigate(navigation => {
16
- callback({ eventType: 'sveltekit-utils-navigation', screen: (navigation.from ?? navigation.to)?.route.id, target: navigation.to?.url.toString(), action: 'navigation', additionalProperties: { fullPageLoad: String(!navigation.from) } });
18
+ // save off the navigation.from in case we're debouncing a redirect
19
+ if (timer === 0)
20
+ from = navigation.from;
21
+ clearTimeout(timer); // we are debouncing because sometimes afterNavigate gets called twice
22
+ timer = setTimeout(() => {
23
+ callback({ eventType: 'sveltekit-utils-navigation', screen: (from ?? navigation.to)?.route.id, target: navigation.to?.url.pathname, action: 'navigation', additionalProperties: { fullPageLoad: String(!from) } });
24
+ timer = 0;
25
+ }, 10);
17
26
  });
18
27
  }
19
28
  export class APIBase {
@@ -29,13 +38,13 @@ export class APIBase {
29
38
  this.readyPromise = new Promise(resolve => { this.ready = resolve; });
30
39
  }
31
40
  async init(token, fetch) {
32
- this.token = token;
33
41
  this.fetch = fetch ?? this.fetch;
34
- if (this.token) {
35
- sessionStorage.setItem('token', this.token);
42
+ if (token) {
43
+ this.token = token;
44
+ sessionStorage.setItem('token', token);
36
45
  }
37
46
  else {
38
- this.token = sessionStorage.getItem('token') ?? undefined;
47
+ this.token ??= sessionStorage.getItem('token') ?? undefined;
39
48
  }
40
49
  this.ready();
41
50
  }
@@ -51,19 +60,21 @@ export class APIBase {
51
60
  }
52
61
  return '?' + p.toString();
53
62
  }
54
- async request(path, method, payload) {
63
+ async request(path, method, opts) {
55
64
  await this.readyPromise;
56
65
  try {
57
- const resp = await this.fetch(this.apiBase + path + this.stringifyQuery(payload?.query), {
66
+ const resp = await this.fetch(this.apiBase + path + this.stringifyQuery(opts?.query), {
58
67
  method,
59
68
  headers: {
60
69
  Authorization: `Bearer ${this.token ?? ''}`,
61
70
  Accept: 'application/json',
62
- ...(payload?.body ? { 'Content-Type': 'application/json' } : {})
71
+ ...(opts?.body ? { 'Content-Type': 'application/json' } : {})
63
72
  },
64
- body: payload?.body ? JSON.stringify(payload.body) : undefined
73
+ body: opts?.body ? JSON.stringify(opts.body) : undefined
65
74
  });
66
- if (!resp.ok) {
75
+ const contentType = resp.headers.get("content-type");
76
+ const isJsonResponse = contentType && contentType.indexOf("application/json") !== -1;
77
+ if (!resp.ok && !(resp.status === 422 && opts?.inlineValidation)) {
67
78
  if (resp.status === 401) {
68
79
  const loginRedirect = new URL(this.authRedirect);
69
80
  loginRedirect.searchParams.set('requestedUrl', location.href);
@@ -71,13 +82,12 @@ export class APIBase {
71
82
  throw error(401);
72
83
  }
73
84
  else {
74
- const message = ((await rescue(resp.json()))?.message ?? resp.statusText);
85
+ const message = ((isJsonResponse ? (await rescue(resp.json()))?.message : await rescue(resp.text())) ?? resp.statusText);
75
86
  toasts.add(message);
76
87
  throw error(resp.status, message);
77
88
  }
78
89
  }
79
- const contentType = resp.headers.get("content-type");
80
- return (contentType && contentType.indexOf("application/json") !== -1) ? await resp.json() : await resp.text();
90
+ return ((isJsonResponse) ? await resp.json() : await resp.text());
81
91
  }
82
92
  catch (e) {
83
93
  toasts.add(e.message);
@@ -87,15 +97,48 @@ export class APIBase {
87
97
  async get(path, query) {
88
98
  return await this.request(path, 'GET', { query });
89
99
  }
100
+ /**
101
+ * Remember to use validatedPost when the user is interacting with a form. That way they
102
+ * will get inline errors.
103
+ */
90
104
  async post(path, body, query) {
91
105
  return await this.request(path, 'POST', { body, query });
92
106
  }
107
+ /**
108
+ * Remember to use validatedPut when the user is interacting with a form. That way they
109
+ * will get inline errors.
110
+ */
93
111
  async put(path, body, query) {
94
112
  return await this.request(path, 'PUT', { body, query });
95
113
  }
114
+ /**
115
+ * Remember to use validatedPatch when the user is interacting with a form. That way they
116
+ * will get inline errors.
117
+ */
96
118
  async patch(path, body, query) {
97
119
  return await this.request(path, 'PATCH', { body, query });
98
120
  }
121
+ /**
122
+ * Use this method when the user is interacting with a form. You should expect a ValidatedResponse,
123
+ * e.g. { success: false, messages: [{ type: 'error', message: 'That name is already taken.', path: 'name' }] }
124
+ */
125
+ async validatedPost(path, body, query) {
126
+ return await this.request(path, 'POST', { body, query, inlineValidation: true });
127
+ }
128
+ /**
129
+ * Use this method when the user is interacting with a form. You should expect a ValidatedResponse,
130
+ * e.g. { success: false, messages: [{ type: 'error', message: 'That name is already taken.', path: 'name' }] }
131
+ */
132
+ async validatedPut(path, body, query) {
133
+ return await this.request(path, 'PUT', { body, query, inlineValidation: true });
134
+ }
135
+ /**
136
+ * Use this method when the user is interacting with a form. You should expect a ValidatedResponse,
137
+ * e.g. { success: false, messages: [{ type: 'error', message: 'That name is already taken.', path: 'name' }] }
138
+ */
139
+ async validatedPatch(path, body, query) {
140
+ return await this.request(path, 'PATCH', { body, query, inlineValidation: true });
141
+ }
99
142
  /**
100
143
  * Sending a JSON body with an HTTP DELETE is not recommended
101
144
  */
package/dist/api.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"api.js","sourceRoot":"","sources":["../src/api.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"api.js","sourceRoot":"","sources":["../src/api.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,gCAAgC,CAAA;AACvD,OAAO,EAAyB,KAAK,EAAE,MAAM,eAAe,CAAA;AAC5D,OAAO,EAAE,GAAG,EAAE,MAAM,cAAc,CAAA;AAClC,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,eAAe,CAAA;AAC/C,OAAO,EAAE,IAAI,EAAE,MAAM,aAAa,CAAA;AAElC,OAAO,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAA;AAK/C;;;;;;GAMG;AACH,MAAM,UAAU,iBAAiB,CAAE,QAAyC;IAC1E,IAAI,KAAK,GAAG,CAAC,CAAA;IACb,IAAI,IAA6B,CAAA;IACjC,aAAa,CAAC,UAAU,CAAC,EAAE;QACvB,mEAAmE;QACnE,IAAI,KAAK,KAAK,CAAC;YAAE,IAAI,GAAG,UAAU,CAAC,IAAI,CAAA;QACvC,YAAY,CAAC,KAAK,CAAC,CAAA,CAAC,sEAAsE;QAC1F,KAAK,GAAG,UAAU,CAAC,GAAG,EAAE;YACtB,QAAQ,CAAC,EAAE,SAAS,EAAE,4BAA4B,EAAE,MAAM,EAAE,CAAC,IAAI,IAAI,UAAU,CAAC,EAAE,CAAC,EAAE,KAAK,CAAC,EAAG,EAAE,MAAM,EAAE,UAAU,CAAC,EAAE,EAAE,GAAG,CAAC,QAAQ,EAAE,MAAM,EAAE,YAAY,EAAE,oBAAoB,EAAE,EAAE,YAAY,EAAE,MAAM,CAAC,CAAC,IAAI,CAAC,EAAE,EAAE,CAAC,CAAA;YACnN,KAAK,GAAG,CAAC,CAAA;QACX,CAAC,EAAE,EAAE,CAAC,CAAA;IACV,CAAC,CAAC,CAAA;AACJ,CAAC;AAED,MAAM,OAAO,OAAO;IAMK;IAAwB;IALxC,KAAK,CAAS;IACd,KAAK,CAA+D;IACjE,KAAK,CAAa;IAClB,YAAY,CAAe;IAErC,YAAuB,OAAe,EAAS,YAAoB;QAA5C,YAAO,GAAP,OAAO,CAAQ;QAAS,iBAAY,GAAZ,YAAY,CAAQ;QACjE,IAAI,CAAC,YAAY,GAAG,IAAI,OAAO,CAAC,OAAO,CAAC,EAAE,GAAG,IAAI,CAAC,KAAK,GAAG,OAAO,CAAA,CAAC,CAAC,CAAC,CAAA;IACtE,CAAC;IAED,KAAK,CAAC,IAAI,CAAE,KAAyB,EAAE,KAAoE;QACzG,IAAI,CAAC,KAAK,GAAG,KAAK,IAAI,IAAI,CAAC,KAAK,CAAA;QAChC,IAAI,KAAK,EAAE,CAAC;YACV,IAAI,CAAC,KAAK,GAAG,KAAK,CAAA;YAClB,cAAc,CAAC,OAAO,CAAC,OAAO,EAAE,KAAK,CAAC,CAAA;QACxC,CAAC;aAAM,CAAC;YACN,IAAI,CAAC,KAAK,KAAK,cAAc,CAAC,OAAO,CAAC,OAAO,CAAC,IAAI,SAAS,CAAA;QAC7D,CAAC;QACD,IAAI,CAAC,KAAK,EAAE,CAAA;IACd,CAAC;IAED,cAAc,CAAE,KAAsC;QACpD,IAAI,KAAK,IAAI,IAAI;YAAE,OAAO,EAAE,CAAA;QAC5B,IAAI,OAAO,KAAK,KAAK,QAAQ;YAAE,OAAO,KAAK,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,GAAG,GAAG,KAAK,CAAA;QACjF,MAAM,CAAC,GAAG,IAAI,eAAe,EAAE,CAAA;QAC/B,KAAK,MAAM,CAAC,GAAG,EAAE,GAAG,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC;YAC/C,KAAK,MAAM,CAAC,IAAI,OAAO,CAAC,GAAG,CAAC;gBAAE,CAAC,CAAC,MAAM,CAAC,GAAG,EAAE,MAAM,CAAC,CAAC,CAAC,CAAC,CAAA;QACxD,CAAC;QACD,OAAO,GAAG,GAAG,CAAC,CAAC,QAAQ,EAAE,CAAA;IAC3B,CAAC;IAES,KAAK,CAAC,OAAO,CAAqB,IAAY,EAAE,MAAc,EAAE,IAA8E;QACtJ,MAAM,IAAI,CAAC,YAAY,CAAA;QACvB,IAAI,CAAC;YACH,MAAM,IAAI,GAAG,MAAM,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,OAAO,GAAG,IAAI,GAAG,IAAI,CAAC,cAAc,CAAC,IAAI,EAAE,KAAK,CAAC,EAAE;gBACpF,MAAM;gBACN,OAAO,EAAE;oBACP,aAAa,EAAE,UAAU,IAAI,CAAC,KAAK,IAAI,EAAE,EAAE;oBAC3C,MAAM,EAAE,kBAAkB;oBAC1B,GAAG,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC,CAAC,EAAE,cAAc,EAAE,kBAAkB,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;iBAC9D;gBACD,IAAI,EAAE,IAAI,EAAE,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,SAAS;aACzD,CAAC,CAAA;YACF,MAAM,WAAW,GAAG,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,cAAc,CAAC,CAAA;YACpD,MAAM,cAAc,GAAG,WAAW,IAAI,WAAW,CAAC,OAAO,CAAC,kBAAkB,CAAC,KAAK,CAAC,CAAC,CAAA;YACpF,IAAI,CAAC,IAAI,CAAC,EAAE,IAAI,CAAC,CAAC,IAAI,CAAC,MAAM,KAAK,GAAG,IAAI,IAAI,EAAE,gBAAgB,CAAC,EAAE,CAAC;gBACjE,IAAI,IAAI,CAAC,MAAM,KAAK,GAAG,EAAE,CAAC;oBACxB,MAAM,aAAa,GAAG,IAAI,GAAG,CAAC,IAAI,CAAC,YAAY,CAAC,CAAA;oBAChD,aAAa,CAAC,YAAY,CAAC,GAAG,CAAC,cAAc,EAAE,QAAQ,CAAC,IAAI,CAAC,CAAA;oBAC7D,QAAQ,CAAC,IAAI,GAAG,aAAa,CAAC,QAAQ,EAAE,CAAA;oBACxC,MAAM,KAAK,CAAC,GAAG,CAAC,CAAA;gBAClB,CAAC;qBAAM,CAAC;oBACN,MAAM,OAAO,GAAG,CAAC,CAAC,cAAc,CAAC,CAAC,CAAC,CAAC,MAAM,MAAM,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC,CAAC,EAAE,OAAO,CAAC,CAAC,CAAC,MAAM,MAAM,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC,CAAC,IAAI,IAAI,CAAC,UAAU,CAAW,CAAA;oBAClI,MAAM,CAAC,GAAG,CAAC,OAAO,CAAC,CAAA;oBACnB,MAAM,KAAK,CAAC,IAAI,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;gBACnC,CAAC;YACH,CAAC;YACD,OAAO,CAAC,CAAC,cAAc,CAAC,CAAC,CAAC,CAAC,MAAM,IAAI,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,MAAM,IAAI,CAAC,IAAI,EAAE,CAAe,CAAA;QACjF,CAAC;QAAC,OAAO,CAAM,EAAE,CAAC;YAChB,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,OAAiB,CAAC,CAAA;YAC/B,MAAM,CAAC,CAAA;QACT,CAAC;IACH,CAAC;IAED,KAAK,CAAC,GAAG,CAAqB,IAAY,EAAE,KAA2B;QACrE,OAAO,MAAM,IAAI,CAAC,OAAO,CAAa,IAAI,EAAE,KAAK,EAAE,EAAE,KAAK,EAAE,CAAC,CAAA;IAC/D,CAAC;IAED;;;OAGG;IACH,KAAK,CAAC,IAAI,CAAqB,IAAY,EAAE,IAAU,EAAE,KAA2B;QAClF,OAAO,MAAM,IAAI,CAAC,OAAO,CAAa,IAAI,EAAE,MAAM,EAAE,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,CAAA;IACtE,CAAC;IAED;;;OAGG;IACH,KAAK,CAAC,GAAG,CAAqB,IAAY,EAAE,IAAU,EAAE,KAA2B;QACjF,OAAO,MAAM,IAAI,CAAC,OAAO,CAAa,IAAI,EAAE,KAAK,EAAE,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,CAAA;IACrE,CAAC;IAED;;;OAGG;IACH,KAAK,CAAC,KAAK,CAAqB,IAAY,EAAE,IAAU,EAAE,KAA2B;QACnF,OAAO,MAAM,IAAI,CAAC,OAAO,CAAa,IAAI,EAAE,OAAO,EAAE,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,CAAA;IACvE,CAAC;IAED;;;OAGG;IACH,KAAK,CAAC,aAAa,CAA6D,IAAY,EAAE,IAAU,EAAE,KAA2B;QACnI,OAAO,MAAM,IAAI,CAAC,OAAO,CAAa,IAAI,EAAE,MAAM,EAAE,EAAE,IAAI,EAAE,KAAK,EAAE,gBAAgB,EAAE,IAAI,EAAE,CAAC,CAAA;IAC9F,CAAC;IAED;;;OAGG;IACH,KAAK,CAAC,YAAY,CAA6D,IAAY,EAAE,IAAU,EAAE,KAA2B;QAClI,OAAO,MAAM,IAAI,CAAC,OAAO,CAAa,IAAI,EAAE,KAAK,EAAE,EAAE,IAAI,EAAE,KAAK,EAAE,gBAAgB,EAAE,IAAI,EAAE,CAAC,CAAA;IAC7F,CAAC;IAED;;;OAGG;IACH,KAAK,CAAC,cAAc,CAA6D,IAAY,EAAE,IAAU,EAAE,KAA2B;QACpI,OAAO,MAAM,IAAI,CAAC,OAAO,CAAa,IAAI,EAAE,OAAO,EAAE,EAAE,IAAI,EAAE,KAAK,EAAE,gBAAgB,EAAE,IAAI,EAAE,CAAC,CAAA;IAC/F,CAAC;IAED;;OAEG;IACH,KAAK,CAAC,MAAM,CAAqB,IAAY,EAAE,KAA2B,EAAE,IAAU;QACpF,OAAO,MAAM,IAAI,CAAC,OAAO,CAAa,IAAI,EAAE,QAAQ,EAAE,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,CAAA;IACxE,CAAC;IAED,KAAK,CAAC,OAAO,CAAqB,KAAa,EAAE,SAAe,EAAE,cAAuB;QACvF,MAAM,WAAW,GAAG,MAAM,IAAI,CAAC,OAAO,CAAC,UAAU,EAAE,MAAM,EAAE,EAAE,IAAI,EAAE;gBACjE,KAAK;gBACL,SAAS;gBACT,UAAU,EAAE;oBACV,cAAc;iBACf;aACF,EAAE,CAAC,CAAA;QACJ,IAAI,WAAW,CAAC,MAAM,EAAE,MAAM,EAAE,CAAC;YAC/B,MAAM,CAAC,GAAG,CAAC,WAAW,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAA;YACzC,MAAM,IAAI,KAAK,CAAC,IAAI,CAAC,SAAS,CAAC,WAAW,CAAC,MAAM,CAAC,CAAC,CAAA;QACrD,CAAC;QACD,OAAO,WAAW,CAAC,IAAI,CAAA;IACzB,CAAC;IAES,cAAc,GAAuB,EAAE,CAAA;IACjD,iBAAiB,CAAC,GAAyC;QACzD,GAAG,CAAC,MAAM,KAAK,GAAG,CAAC,IAAI,CAAC,CAAC,KAAK,CAAC,EAAG,CAAA;QAClC,IAAI,CAAC,cAAc,CAAC,IAAI,CAAC,GAAuB,CAAC,CAAA;QACjD,UAAU,CAAC,GAAG,EAAE;YACd,MAAM,MAAM,GAAG,CAAC,GAAG,IAAI,CAAC,cAAc,CAAC,CAAA;YACvC,IAAI,CAAC,cAAc,CAAC,MAAM,GAAG,CAAC,CAAA;YAC9B,IAAI,CAAC,IAAI,CAAC,YAAY,EAAE,MAAM,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAA;QAChE,CAAC,EAAE,IAAI,CAAC,CAAA;IACV,CAAC;IAED;;;OAGG;IACH,iBAAiB;QACf,iBAAiB,CAAC,IAAI,CAAC,iBAAiB,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAA;IACtD,CAAC;CACF"}
package/dist/index.d.ts CHANGED
@@ -1 +1,21 @@
1
+ import { LoadEvent } from '@sveltejs/kit';
2
+ import { APIBase } from './api.js';
1
3
  export * from './api.js';
4
+ interface HandleOpts {
5
+ /**
6
+ * handleUnifiedAuth redirects users to unified auth by default if they don't have
7
+ * a token yet. If your UI is at least partially available to the public, set
8
+ * allowUnauthenticated to true.
9
+ */
10
+ allowUnauthenticated?: boolean;
11
+ }
12
+ /**
13
+ * Your root +layout.ts' load function should call this method to ensure that it
14
+ * handles authentication from Unified Auth. By default it will redirect unauthenticated
15
+ * users to Unified Auth without a screen flash.
16
+ *
17
+ * If you set allowUnauthenticated: true and wait for the API to send a 401, there
18
+ * will often be a screen flash.
19
+ */
20
+ export declare function handleUnifiedAuth(api: APIBase, input: LoadEvent, opts?: HandleOpts): Promise<void>;
21
+ export declare function requireAuthentication(api: APIBase, input: LoadEvent): void;
package/dist/index.js CHANGED
@@ -1,2 +1,33 @@
1
+ import { redirect } from '@sveltejs/kit';
1
2
  export * from './api.js';
3
+ /**
4
+ * Your root +layout.ts' load function should call this method to ensure that it
5
+ * handles authentication from Unified Auth. By default it will redirect unauthenticated
6
+ * users to Unified Auth without a screen flash.
7
+ *
8
+ * If you set allowUnauthenticated: true and wait for the API to send a 401, there
9
+ * will often be a screen flash.
10
+ */
11
+ export async function handleUnifiedAuth(api, input, opts) {
12
+ const unifiedJwt = input.url.searchParams.get('unifiedJwt') ?? undefined;
13
+ await api.init(unifiedJwt);
14
+ if (unifiedJwt) {
15
+ let redirectUrl = input.url.searchParams.get('requestedUrl') ?? undefined;
16
+ if (!redirectUrl) {
17
+ const currentUrl = new URL(input.url);
18
+ currentUrl.searchParams.delete('unifiedJwt');
19
+ redirectUrl = currentUrl.toString();
20
+ }
21
+ throw redirect(302, redirectUrl);
22
+ }
23
+ if (!opts?.allowUnauthenticated)
24
+ requireAuthentication(api, input);
25
+ }
26
+ export function requireAuthentication(api, input) {
27
+ if (!api.token) {
28
+ const loginRedirect = new URL(api.authRedirect);
29
+ loginRedirect.searchParams.set('requestedUrl', input.url.toString());
30
+ throw redirect(302, loginRedirect);
31
+ }
32
+ }
2
33
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,UAAU,CAAA"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAa,QAAQ,EAAE,MAAM,eAAe,CAAC;AAGpD,cAAc,UAAU,CAAA;AAWxB;;;;;;;GAOG;AACH,MAAM,CAAC,KAAK,UAAU,iBAAiB,CAAE,GAAY,EAAE,KAAgB,EAAE,IAAiB;IACxF,MAAM,UAAU,GAAG,KAAK,CAAC,GAAG,CAAC,YAAY,CAAC,GAAG,CAAC,YAAY,CAAC,IAAI,SAAS,CAAA;IACxE,MAAM,GAAG,CAAC,IAAI,CAAC,UAAU,CAAC,CAAA;IAC1B,IAAI,UAAU,EAAE,CAAC;QACf,IAAI,WAAW,GAAG,KAAK,CAAC,GAAG,CAAC,YAAY,CAAC,GAAG,CAAC,cAAc,CAAC,IAAI,SAAS,CAAA;QACzE,IAAI,CAAC,WAAW,EAAE,CAAC;YACjB,MAAM,UAAU,GAAG,IAAI,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,CAAA;YACrC,UAAU,CAAC,YAAY,CAAC,MAAM,CAAC,YAAY,CAAC,CAAA;YAC5C,WAAW,GAAG,UAAU,CAAC,QAAQ,EAAE,CAAA;QACrC,CAAC;QACD,MAAM,QAAQ,CAAC,GAAG,EAAE,WAAW,CAAC,CAAA;IAClC,CAAC;IACD,IAAI,CAAC,IAAI,EAAE,oBAAoB;QAAE,qBAAqB,CAAC,GAAG,EAAE,KAAK,CAAC,CAAA;AACpE,CAAC;AAED,MAAM,UAAU,qBAAqB,CAAE,GAAY,EAAE,KAAgB;IACnE,IAAI,CAAC,GAAG,CAAC,KAAK,EAAE,CAAC;QACf,MAAM,aAAa,GAAG,IAAI,GAAG,CAAC,GAAG,CAAC,YAAY,CAAC,CAAA;QAC/C,aAAa,CAAC,YAAY,CAAC,GAAG,CAAC,cAAc,EAAE,KAAK,CAAC,GAAG,CAAC,QAAQ,EAAE,CAAC,CAAA;QACpE,MAAM,QAAQ,CAAC,GAAG,EAAE,aAAa,CAAC,CAAA;IACpC,CAAC;AACH,CAAC"}
package/package.json CHANGED
@@ -1,10 +1,13 @@
1
1
  {
2
2
  "name": "@txstate-mws/sveltekit-utils",
3
- "version": "1.0.1",
3
+ "version": "1.0.3",
4
4
  "description": "Shared library for code that is specifically tied to sveltekit in addition to svelte.",
5
5
  "type": "module",
6
6
  "exports": {
7
- ".": "./dist/index.js"
7
+ ".": {
8
+ "types": "./dist/index.d.ts",
9
+ "default": "./dist/index.js"
10
+ }
8
11
  },
9
12
  "types": "./dist/index.d.ts",
10
13
  "dependencies": {