politeshop 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (42) hide show
  1. package/README.md +33 -0
  2. package/dist/clients/brightspace.d.ts +75 -0
  3. package/dist/clients/brightspace.d.ts.map +1 -0
  4. package/dist/clients/brightspace.js +104 -0
  5. package/dist/clients/brightspace.js.map +1 -0
  6. package/dist/clients/polite.d.ts +117 -0
  7. package/dist/clients/polite.d.ts.map +1 -0
  8. package/dist/clients/polite.js +191 -0
  9. package/dist/clients/polite.js.map +1 -0
  10. package/dist/clients/politeshop.d.ts +119 -0
  11. package/dist/clients/politeshop.d.ts.map +1 -0
  12. package/dist/clients/politeshop.js +401 -0
  13. package/dist/clients/politeshop.js.map +1 -0
  14. package/dist/errors.d.ts +7 -0
  15. package/dist/errors.d.ts.map +1 -0
  16. package/dist/errors.js +9 -0
  17. package/dist/errors.js.map +1 -0
  18. package/dist/index.d.ts +5 -0
  19. package/dist/index.d.ts.map +1 -0
  20. package/dist/index.js +4 -0
  21. package/dist/index.js.map +1 -0
  22. package/dist/schema/polite.d.ts +809 -0
  23. package/dist/schema/polite.d.ts.map +1 -0
  24. package/dist/schema/polite.js +197 -0
  25. package/dist/schema/polite.js.map +1 -0
  26. package/dist/schema/siren.d.ts +66 -0
  27. package/dist/schema/siren.d.ts.map +1 -0
  28. package/dist/schema/siren.js +112 -0
  29. package/dist/schema/siren.js.map +1 -0
  30. package/dist/types.d.ts +105 -0
  31. package/dist/types.d.ts.map +1 -0
  32. package/dist/types.js +6 -0
  33. package/dist/types.js.map +1 -0
  34. package/dist/utils/array.d.ts +5 -0
  35. package/dist/utils/array.d.ts.map +1 -0
  36. package/dist/utils/array.js +13 -0
  37. package/dist/utils/array.js.map +1 -0
  38. package/dist/utils/url.d.ts +23 -0
  39. package/dist/utils/url.d.ts.map +1 -0
  40. package/dist/utils/url.js +53 -0
  41. package/dist/utils/url.js.map +1 -0
  42. package/package.json +42 -0
@@ -0,0 +1 @@
1
+ {"version":3,"file":"polite.d.ts","sourceRoot":"","sources":["../../schema/polite.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,197 @@
1
+ /**
2
+ * Zod schemas for POLITE API (*.polite.edu.sg) responses.
3
+ * Adapted from https://docs.valence.desire2learn.com/reference.html.
4
+ * These schemas only cover the parts of the API used by POLITEShop.
5
+ */
6
+ import { z } from "zod";
7
+ // ── Auth ──────────────────────────────────────────────────────────────────────
8
+ /** Response from GET /d2l/lp/auth/oauth2/token */
9
+ export const brightspaceToken = z.object({
10
+ access_token: z.string(),
11
+ expires_at: z.number(),
12
+ });
13
+ // ── Users ─────────────────────────────────────────────────────────────────────
14
+ /** https://docs.valence.desire2learn.com/res/user.html#User.WhoAmIUser */
15
+ export const whoAmIUser = z.object({
16
+ Identifier: z.string(),
17
+ FirstName: z.string(),
18
+ LastName: z.string(),
19
+ /** POLITEMall uses this as the user's email address. */
20
+ UniqueName: z.string(),
21
+ ProfileIdentifier: z.string(),
22
+ });
23
+ // ── Organization ──────────────────────────────────────────────────────────────
24
+ /** https://docs.valence.desire2learn.com/res/orgunit.html#Org.Organization */
25
+ export const organization = z.object({
26
+ Identifier: z.string(),
27
+ Name: z.string(),
28
+ TimeZone: z.string(),
29
+ });
30
+ // ── Enrollments ───────────────────────────────────────────────────────────────
31
+ /** https://docs.valence.desire2learn.com/res/enroll.html#Enrollment.MyOrgUnitInfo */
32
+ export const myOrgUnitInfo = z.object({
33
+ OrgUnit: z.object({
34
+ Id: z.number(),
35
+ Type: z.object({
36
+ Id: z.number(),
37
+ Code: z.string(),
38
+ Name: z.string(),
39
+ }),
40
+ Name: z.string(),
41
+ Code: z.string().nullable(),
42
+ HomeUrl: z.string().nullable(),
43
+ ImageUrl: z.string().nullable(),
44
+ }),
45
+ });
46
+ export const courseParent = z.object({
47
+ CourseOfferingId: z.string(),
48
+ Semester: z.object({
49
+ Identifier: z.string(),
50
+ Name: z.string(),
51
+ Code: z.string(),
52
+ }),
53
+ Department: z.object({
54
+ Identifier: z.string(),
55
+ Name: z.string(),
56
+ Code: z.string(),
57
+ }),
58
+ });
59
+ // ── Content / Table of Contents ───────────────────────────────────────────────
60
+ const richText = z.object({
61
+ Text: z.string(),
62
+ Html: z.string(),
63
+ });
64
+ /**
65
+ * `ToC.Topic` of https://docs.valence.desire2learn.com/res/content.html#ToC.TableOfContents
66
+ *
67
+ * ActivityType values:
68
+ * 1 = File / ContentService
69
+ * 2 = Link (web embed)
70
+ * 3 = Dropbox (submission)
71
+ * 4 = Quiz
72
+ */
73
+ export const tocTopic = z
74
+ .object({
75
+ Identifier: z.string(),
76
+ /** Same identifier as `Identifier`, but as a number. */
77
+ TopicId: z.number(),
78
+ Title: z.string(),
79
+ Description: richText,
80
+ ActivityType: z.number(),
81
+ TypeIdentifier: z.enum(["Link", "File", "ContentService"]),
82
+ Unread: z.boolean(),
83
+ ToolId: z.number().nullable(),
84
+ ToolItemId: z.number().nullable(),
85
+ SortOrder: z.number(),
86
+ })
87
+ .and(z
88
+ .object({ IsBroken: z.literal(false), Url: z.string() })
89
+ .or(z.object({ IsBroken: z.literal(true), Url: z.string().nullable() })));
90
+ const baseModule = z.object({
91
+ ModuleId: z.number(),
92
+ Title: z.string(),
93
+ Description: richText,
94
+ SortOrder: z.number(),
95
+ Topics: tocTopic.array(),
96
+ });
97
+ /**
98
+ * Brightspace calls these "Module" objects but POLITEShop calls them "activity folders".
99
+ * `ToC.Module` of https://docs.valence.desire2learn.com/res/content.html#ToC.TableOfContents
100
+ */
101
+ export const tocModule = baseModule.extend({
102
+ Modules: z.lazy(() => tocModule.array()),
103
+ });
104
+ /** https://docs.valence.desire2learn.com/res/content.html#ToC.TableOfContents */
105
+ export const tableOfContents = z.object({
106
+ Modules: tocModule.array(),
107
+ });
108
+ // ── Dropbox / Submissions ─────────────────────────────────────────────────────
109
+ const file = z.object({
110
+ FileId: z.number(),
111
+ FileName: z.string(),
112
+ Size: z.number(),
113
+ });
114
+ /** https://docs.valence.desire2learn.com/res/dropbox.html#Dropbox.EntityDropbox */
115
+ export const entityDropbox = z.object({
116
+ CompletionDate: z.string().nullable(),
117
+ Submissions: z
118
+ .object({
119
+ Id: z.number(),
120
+ SubmissionDate: z.coerce.date().nullable(),
121
+ Comment: richText,
122
+ Files: file.array(),
123
+ })
124
+ .array(),
125
+ });
126
+ /** https://docs.valence.desire2learn.com/res/dropbox.html#Dropbox.DropboxFolder */
127
+ export const dropboxFolder = z.object({
128
+ Id: z.number(),
129
+ Name: z.string(),
130
+ CustomInstructions: richText,
131
+ Attachments: file.array(),
132
+ DueDate: z.coerce.date().nullable(),
133
+ SubmissionType: z.literal(0),
134
+ CompletionType: z.number(),
135
+ Availability: z
136
+ .object({
137
+ StartDate: z.coerce.date().nullable(),
138
+ EndDate: z.coerce.date().nullable(),
139
+ StartDateAvailabilityType: z.number().nullable(),
140
+ EndDateAvailabilityType: z.number().nullable(),
141
+ })
142
+ .nullable(),
143
+ });
144
+ // ── Quizzes ───────────────────────────────────────────────────────────────────
145
+ /** https://docs.valence.desire2learn.com/res/quiz.html#Quiz.QuizReadData */
146
+ export const quizReadData = z.object({
147
+ QuizId: z.number(),
148
+ Name: z.string(),
149
+ Instructions: z.object({
150
+ Text: richText,
151
+ IsDisplayed: z.boolean(),
152
+ }),
153
+ Description: z.object({
154
+ Text: richText,
155
+ IsDisplayed: z.boolean(),
156
+ }),
157
+ StartDate: z.coerce.date(),
158
+ EndDate: z.coerce.date(),
159
+ DueDate: z.coerce.date().nullable(),
160
+ SortOrder: z.number(),
161
+ SubmissionTimeLimit: z.object({
162
+ IsEnforced: z.boolean(),
163
+ ShowClock: z.boolean(),
164
+ TimeLimitValue: z.number(),
165
+ }),
166
+ AttemptsAllowed: z.object({
167
+ IsUnlimited: z.boolean(),
168
+ NumberOfAttemptsAllowed: z.number().nullable(),
169
+ }),
170
+ CalcTypeId: z.number(),
171
+ Shuffle: z.boolean(),
172
+ });
173
+ // ── Pagination helpers ────────────────────────────────────────────────────────
174
+ /**
175
+ * Wraps a schema in an
176
+ * [ObjectListPage](https://docs.valence.desire2learn.com/basic/apicall.html#Api.ObjectListPage).
177
+ */
178
+ export function objectListPage(s) {
179
+ return z.object({
180
+ Next: z.string().nullable(),
181
+ Objects: s.array(),
182
+ });
183
+ }
184
+ /**
185
+ * Wraps a schema in a
186
+ * [PagedResultSet](https://docs.valence.desire2learn.com/basic/apicall.html#Api.PagedResultSet).
187
+ */
188
+ export function pagedResultSet(s) {
189
+ return z.object({
190
+ PagingInfo: z.object({
191
+ Bookmark: z.string(),
192
+ HasMoreItems: z.boolean(),
193
+ }),
194
+ Items: s.array(),
195
+ });
196
+ }
197
+ //# sourceMappingURL=polite.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"polite.js","sourceRoot":"","sources":["../../schema/polite.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,66 @@
1
+ import { z } from "zod";
2
+ export type SirenLink = {
3
+ class?: string[];
4
+ rel: string[];
5
+ href: string;
6
+ };
7
+ export type SirenAction = {
8
+ href: string;
9
+ method: string;
10
+ name: string;
11
+ fields?: {
12
+ name: string;
13
+ type: string;
14
+ value?: any;
15
+ title?: string;
16
+ }[];
17
+ class?: string[];
18
+ title?: string;
19
+ type?: string;
20
+ };
21
+ export declare class SirenEntity {
22
+ class: (string | null | undefined)[];
23
+ rel?: string[];
24
+ actions?: SirenAction[];
25
+ entities?: SirenEntity[];
26
+ links?: SirenLink[];
27
+ properties?: Record<string, any>;
28
+ href?: string;
29
+ constructor(data: {
30
+ class: (string | null | undefined)[];
31
+ rel?: string[];
32
+ actions?: SirenAction[];
33
+ entities?: SirenEntity[];
34
+ links?: SirenLink[];
35
+ properties?: Record<string, any>;
36
+ href?: string;
37
+ });
38
+ findChild(query: {
39
+ class: string | string[];
40
+ } | {
41
+ rel: string | string[];
42
+ }): SirenEntity | undefined;
43
+ getChild(query: {
44
+ class: string | string[];
45
+ } | {
46
+ rel: string | string[];
47
+ }): SirenEntity;
48
+ findLink(query: {
49
+ class: string | string[];
50
+ } | {
51
+ rel: string | string[];
52
+ }): SirenLink | undefined;
53
+ getLink(query: {
54
+ class: string | string[];
55
+ } | {
56
+ rel: string | string[];
57
+ }): SirenLink;
58
+ findAction(query: {
59
+ name: string;
60
+ }): SirenAction | undefined;
61
+ getAction(query: {
62
+ name: string;
63
+ }): SirenAction;
64
+ }
65
+ export declare const sirenEntity: z.ZodType<SirenEntity, z.ZodTypeDef, unknown>;
66
+ //# sourceMappingURL=siren.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"siren.d.ts","sourceRoot":"","sources":["../../schema/siren.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAKxB,MAAM,MAAM,SAAS,GAAG;IAAE,KAAK,CAAC,EAAE,MAAM,EAAE,CAAC;IAAC,GAAG,EAAE,MAAM,EAAE,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,CAAC;AAE1E,MAAM,MAAM,WAAW,GAAG;IACxB,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,CAAC,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAC;QAAC,KAAK,CAAC,EAAE,GAAG,CAAC;QAAC,KAAK,CAAC,EAAE,MAAM,CAAA;KAAE,EAAE,CAAC;IACvE,KAAK,CAAC,EAAE,MAAM,EAAE,CAAC;IACjB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,IAAI,CAAC,EAAE,MAAM,CAAC;CACf,CAAC;AAIF,qBAAa,WAAW;IACtB,KAAK,EAAE,CAAC,MAAM,GAAG,IAAI,GAAG,SAAS,CAAC,EAAE,CAAC;IACrC,GAAG,CAAC,EAAE,MAAM,EAAE,CAAC;IACf,OAAO,CAAC,EAAE,WAAW,EAAE,CAAC;IACxB,QAAQ,CAAC,EAAE,WAAW,EAAE,CAAC;IACzB,KAAK,CAAC,EAAE,SAAS,EAAE,CAAC;IACpB,UAAU,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;IACjC,IAAI,CAAC,EAAE,MAAM,CAAC;gBAEF,IAAI,EAAE;QAChB,KAAK,EAAE,CAAC,MAAM,GAAG,IAAI,GAAG,SAAS,CAAC,EAAE,CAAC;QACrC,GAAG,CAAC,EAAE,MAAM,EAAE,CAAC;QACf,OAAO,CAAC,EAAE,WAAW,EAAE,CAAC;QACxB,QAAQ,CAAC,EAAE,WAAW,EAAE,CAAC;QACzB,KAAK,CAAC,EAAE,SAAS,EAAE,CAAC;QACpB,UAAU,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;QACjC,IAAI,CAAC,EAAE,MAAM,CAAC;KACf;IAYD,SAAS,CACP,KAAK,EAAE;QAAE,KAAK,EAAE,MAAM,GAAG,MAAM,EAAE,CAAA;KAAE,GAAG;QAAE,GAAG,EAAE,MAAM,GAAG,MAAM,EAAE,CAAA;KAAE,GAC/D,WAAW,GAAG,SAAS;IAmB1B,QAAQ,CACN,KAAK,EAAE;QAAE,KAAK,EAAE,MAAM,GAAG,MAAM,EAAE,CAAA;KAAE,GAAG;QAAE,GAAG,EAAE,MAAM,GAAG,MAAM,EAAE,CAAA;KAAE,GAC/D,WAAW;IAWd,QAAQ,CACN,KAAK,EAAE;QAAE,KAAK,EAAE,MAAM,GAAG,MAAM,EAAE,CAAA;KAAE,GAAG;QAAE,GAAG,EAAE,MAAM,GAAG,MAAM,EAAE,CAAA;KAAE,GAC/D,SAAS,GAAG,SAAS;IAiBxB,OAAO,CACL,KAAK,EAAE;QAAE,KAAK,EAAE,MAAM,GAAG,MAAM,EAAE,CAAA;KAAE,GAAG;QAAE,GAAG,EAAE,MAAM,GAAG,MAAM,EAAE,CAAA;KAAE,GAC/D,SAAS;IASZ,UAAU,CAAC,KAAK,EAAE;QAAE,IAAI,EAAE,MAAM,CAAA;KAAE,GAAG,WAAW,GAAG,SAAS;IAI5D,SAAS,CAAC,KAAK,EAAE;QAAE,IAAI,EAAE,MAAM,CAAA;KAAE,GAAG,WAAW;CAKhD;AAID,eAAO,MAAM,WAAW,EAAE,CAAC,CAAC,OAAO,CAAC,WAAW,EAAE,CAAC,CAAC,UAAU,EAAE,OAAO,CAuCnE,CAAC"}
@@ -0,0 +1,112 @@
1
+ import { z } from "zod";
2
+ import { arrEq } from "../utils/array";
3
+ // ── SirenEntity class ─────────────────────────────────────────────────────────
4
+ export class SirenEntity {
5
+ class;
6
+ rel;
7
+ actions;
8
+ entities;
9
+ links;
10
+ properties;
11
+ href;
12
+ constructor(data) {
13
+ this.class = data.class;
14
+ this.rel = data.rel;
15
+ this.actions = data.actions;
16
+ this.entities = data.entities;
17
+ this.links = data.links;
18
+ this.properties = data.properties;
19
+ this.href = data.href;
20
+ }
21
+ // ── Sub-entity lookup ───────────────────────────────────────────────────────
22
+ findChild(query) {
23
+ if ("class" in query) {
24
+ const cls = query.class;
25
+ if (typeof cls === "string")
26
+ return this.entities?.find(({ class: c }) => c.includes(cls));
27
+ return this.entities?.find(({ class: c }) => arrEq(c, cls));
28
+ }
29
+ if ("rel" in query) {
30
+ const rel = query.rel;
31
+ if (typeof rel === "string")
32
+ return this.entities?.find(({ rel: r }) => r?.includes(rel));
33
+ return this.entities?.find(({ rel: r }) => r != null && arrEq(r, rel));
34
+ }
35
+ }
36
+ getChild(query) {
37
+ const result = this.findChild(query);
38
+ if (!result)
39
+ throw new Error(`No child entity found matching query: ${JSON.stringify(query)}`);
40
+ return result;
41
+ }
42
+ // ── Link lookup ─────────────────────────────────────────────────────────────
43
+ findLink(query) {
44
+ if ("class" in query) {
45
+ const cls = query.class;
46
+ if (typeof cls === "string")
47
+ return this.links?.find(({ class: c }) => c?.includes(cls));
48
+ return this.links?.find(({ class: c }) => c != null && arrEq(c, cls));
49
+ }
50
+ if ("rel" in query) {
51
+ const rel = query.rel;
52
+ if (typeof rel === "string")
53
+ return this.links?.find(({ rel: r }) => r.includes(rel));
54
+ return this.links?.find(({ rel: r }) => arrEq(r, rel));
55
+ }
56
+ }
57
+ getLink(query) {
58
+ const result = this.findLink(query);
59
+ if (!result)
60
+ throw new Error(`No link found matching query: ${JSON.stringify(query)}`);
61
+ return result;
62
+ }
63
+ // ── Action lookup ───────────────────────────────────────────────────────────
64
+ findAction(query) {
65
+ return this.actions?.find((a) => a.name === query.name);
66
+ }
67
+ getAction(query) {
68
+ const result = this.findAction(query);
69
+ if (!result)
70
+ throw new Error(`No action found with name: "${query.name}"`);
71
+ return result;
72
+ }
73
+ }
74
+ // ── Zod schema ────────────────────────────────────────────────────────────────
75
+ export const sirenEntity = z.lazy(() => z
76
+ .object({
77
+ actions: z
78
+ .object({
79
+ href: z.string(),
80
+ method: z.string(),
81
+ name: z.string(),
82
+ fields: z
83
+ .object({
84
+ name: z.string(),
85
+ type: z.string(),
86
+ value: z.any(),
87
+ title: z.string().optional(),
88
+ })
89
+ .array()
90
+ .optional(),
91
+ class: z.string().array().optional(),
92
+ title: z.string().optional(),
93
+ type: z.string().optional(),
94
+ })
95
+ .array()
96
+ .optional(),
97
+ entities: sirenEntity.array().optional(),
98
+ links: z
99
+ .object({
100
+ class: z.string().array().optional(),
101
+ rel: z.string().array(),
102
+ href: z.string(),
103
+ })
104
+ .array()
105
+ .optional(),
106
+ rel: z.string().array().optional(),
107
+ properties: z.record(z.string(), z.any()).optional(),
108
+ class: z.string().nullable().array(),
109
+ href: z.string().optional(),
110
+ })
111
+ .transform((data) => new SirenEntity(data)));
112
+ //# sourceMappingURL=siren.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"siren.js","sourceRoot":"","sources":["../../schema/siren.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,105 @@
1
+ /**
2
+ * Domain types returned by the {@link POLITEShop} client. These are plain
3
+ * TypeScript interfaces, independent of any ORM or database schema.
4
+ */
5
+ export interface User {
6
+ id: string;
7
+ name: string;
8
+ }
9
+ export interface Institution {
10
+ id: string;
11
+ name: string;
12
+ }
13
+ export interface Semester {
14
+ id: string;
15
+ name: string;
16
+ }
17
+ export interface Module {
18
+ id: string;
19
+ name: string;
20
+ code: string;
21
+ }
22
+ export interface ActivityFolder {
23
+ type: "folder";
24
+ id: string;
25
+ name: string;
26
+ description: string;
27
+ sortOrder: number;
28
+ contents: (AnyActivity | ActivityFolder)[];
29
+ }
30
+ interface BaseActivity {
31
+ id: string;
32
+ sortOrder: number;
33
+ }
34
+ export interface HTMLActivity extends BaseActivity {
35
+ type: "html";
36
+ name: string;
37
+ /** Raw HTML content of the activity page. */
38
+ content: string;
39
+ }
40
+ export interface WebEmbedActivity extends BaseActivity {
41
+ type: "web_embed";
42
+ name: string;
43
+ /** The URL to embed in an iframe. */
44
+ url: string;
45
+ }
46
+ export interface DocEmbedActivity extends BaseActivity {
47
+ type: "doc_embed";
48
+ name: string;
49
+ /** Original source file URL (e.g. .pptx, .docx, .pdf). */
50
+ sourceURL: string;
51
+ /** URL of a browser-renderable PDF preview generated by Brightspace, if available. */
52
+ previewURL?: string;
53
+ /** Expiry date of the preview URL, if it is time-limited. */
54
+ previewURLExpiry?: Date;
55
+ }
56
+ export interface VideoEmbedActivity extends BaseActivity {
57
+ type: "video_embed";
58
+ name: string;
59
+ /** Signed URL of the video file hosted on Brightspace Content Service / S3. */
60
+ sourceURL: string;
61
+ /** Expiry date of the source URL. */
62
+ sourceURLExpiry?: Date;
63
+ /** Signed URL of the video thumbnail. */
64
+ thumbnailURL: string;
65
+ /** Expiry date of the thumbnail URL. */
66
+ thumbnailURLExpiry?: Date;
67
+ }
68
+ export interface SubmissionActivity extends BaseActivity {
69
+ type: "submission";
70
+ /** ID of the dropbox folder this activity links to. */
71
+ dropboxId: string;
72
+ }
73
+ export interface QuizActivity extends BaseActivity {
74
+ type: "quiz";
75
+ /** ID of the quiz this activity links to. */
76
+ quizId: string;
77
+ }
78
+ export interface UnknownActivity extends BaseActivity {
79
+ type: "unknown";
80
+ }
81
+ export type AnyActivity = HTMLActivity | WebEmbedActivity | DocEmbedActivity | VideoEmbedActivity | SubmissionActivity | QuizActivity | UnknownActivity;
82
+ export interface SubmissionDropbox {
83
+ id: string;
84
+ name: string;
85
+ moduleId: string;
86
+ description: string;
87
+ dueAt: Date | null;
88
+ opensAt?: Date | null;
89
+ closesAt?: Date | null;
90
+ }
91
+ export interface Submission {
92
+ id: string;
93
+ dropboxId: string;
94
+ submittedAt: Date | null;
95
+ comment?: string;
96
+ }
97
+ export interface Quiz {
98
+ id: string;
99
+ moduleId: string;
100
+ name: string;
101
+ description: string;
102
+ dueAt: Date | null;
103
+ }
104
+ export {};
105
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../types.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAIH,MAAM,WAAW,IAAI;IACnB,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;CACd;AAED,MAAM,WAAW,WAAW;IAC1B,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;CACd;AAID,MAAM,WAAW,QAAQ;IACvB,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;CACd;AAED,MAAM,WAAW,MAAM;IACrB,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;CACd;AAID,MAAM,WAAW,cAAc;IAC7B,IAAI,EAAE,QAAQ,CAAC;IACf,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,EAAE,CAAC,WAAW,GAAG,cAAc,CAAC,EAAE,CAAC;CAC5C;AAID,UAAU,YAAY;IACpB,EAAE,EAAE,MAAM,CAAC;IACX,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,YAAa,SAAQ,YAAY;IAChD,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,6CAA6C;IAC7C,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,gBAAiB,SAAQ,YAAY;IACpD,IAAI,EAAE,WAAW,CAAC;IAClB,IAAI,EAAE,MAAM,CAAC;IACb,qCAAqC;IACrC,GAAG,EAAE,MAAM,CAAC;CACb;AAED,MAAM,WAAW,gBAAiB,SAAQ,YAAY;IACpD,IAAI,EAAE,WAAW,CAAC;IAClB,IAAI,EAAE,MAAM,CAAC;IACb,0DAA0D;IAC1D,SAAS,EAAE,MAAM,CAAC;IAClB,sFAAsF;IACtF,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,6DAA6D;IAC7D,gBAAgB,CAAC,EAAE,IAAI,CAAC;CACzB;AAED,MAAM,WAAW,kBAAmB,SAAQ,YAAY;IACtD,IAAI,EAAE,aAAa,CAAC;IACpB,IAAI,EAAE,MAAM,CAAC;IACb,+EAA+E;IAC/E,SAAS,EAAE,MAAM,CAAC;IAClB,qCAAqC;IACrC,eAAe,CAAC,EAAE,IAAI,CAAC;IACvB,yCAAyC;IACzC,YAAY,EAAE,MAAM,CAAC;IACrB,wCAAwC;IACxC,kBAAkB,CAAC,EAAE,IAAI,CAAC;CAC3B;AAED,MAAM,WAAW,kBAAmB,SAAQ,YAAY;IACtD,IAAI,EAAE,YAAY,CAAC;IACnB,uDAAuD;IACvD,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,YAAa,SAAQ,YAAY;IAChD,IAAI,EAAE,MAAM,CAAC;IACb,6CAA6C;IAC7C,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,eAAgB,SAAQ,YAAY;IACnD,IAAI,EAAE,SAAS,CAAC;CACjB;AAED,MAAM,MAAM,WAAW,GACnB,YAAY,GACZ,gBAAgB,GAChB,gBAAgB,GAChB,kBAAkB,GAClB,kBAAkB,GAClB,YAAY,GACZ,eAAe,CAAC;AAIpB,MAAM,WAAW,iBAAiB;IAChC,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,MAAM,CAAC;IACjB,WAAW,EAAE,MAAM,CAAC;IACpB,KAAK,EAAE,IAAI,GAAG,IAAI,CAAC;IACnB,OAAO,CAAC,EAAE,IAAI,GAAG,IAAI,CAAC;IACtB,QAAQ,CAAC,EAAE,IAAI,GAAG,IAAI,CAAC;CACxB;AAED,MAAM,WAAW,UAAU;IACzB,EAAE,EAAE,MAAM,CAAC;IACX,SAAS,EAAE,MAAM,CAAC;IAClB,WAAW,EAAE,IAAI,GAAG,IAAI,CAAC;IACzB,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAID,MAAM,WAAW,IAAI;IACnB,EAAE,EAAE,MAAM,CAAC;IACX,QAAQ,EAAE,MAAM,CAAC;IACjB,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,KAAK,EAAE,IAAI,GAAG,IAAI,CAAC;CACpB"}
package/dist/types.js ADDED
@@ -0,0 +1,6 @@
1
+ /**
2
+ * Domain types returned by the {@link POLITEShop} client. These are plain
3
+ * TypeScript interfaces, independent of any ORM or database schema.
4
+ */
5
+ export {};
6
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../types.ts"],"names":[],"mappings":"AAAA;;;GAGG"}
@@ -0,0 +1,5 @@
1
+ /** Check if two arrays are equal (shallow). */
2
+ export declare function arrEq<T>(a: T[], b: T[]): boolean;
3
+ /** Split an array into consecutive chunks of at most `size` elements. */
4
+ export declare function chunk<T>(arr: T[], size: number): T[][];
5
+ //# sourceMappingURL=array.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"array.d.ts","sourceRoot":"","sources":["../../utils/array.ts"],"names":[],"mappings":"AAAA,+CAA+C;AAC/C,wBAAgB,KAAK,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,EAAE,CAAC,EAAE,GAAG,OAAO,CAEhD;AAED,yEAAyE;AACzE,wBAAgB,KAAK,CAAC,CAAC,EAAE,GAAG,EAAE,CAAC,EAAE,EAAE,IAAI,EAAE,MAAM,GAAG,CAAC,EAAE,EAAE,CAMtD"}
@@ -0,0 +1,13 @@
1
+ /** Check if two arrays are equal (shallow). */
2
+ export function arrEq(a, b) {
3
+ return a.length === b.length && a.every((v, i) => v === b[i]);
4
+ }
5
+ /** Split an array into consecutive chunks of at most `size` elements. */
6
+ export function chunk(arr, size) {
7
+ const result = [];
8
+ for (let i = 0; i < arr.length; i += size) {
9
+ result.push(arr.slice(i, i + size));
10
+ }
11
+ return result;
12
+ }
13
+ //# sourceMappingURL=array.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"array.js","sourceRoot":"","sources":["../../utils/array.ts"],"names":[],"mappings":"AAAA,+CAA+C;AAC/C,MAAM,UAAU,KAAK,CAAI,CAAM,EAAE,CAAM;IACrC,OAAO,CAAC,CAAC,MAAM,KAAK,CAAC,CAAC,MAAM,IAAI,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;AAChE,CAAC;AAED,yEAAyE;AACzE,MAAM,UAAU,KAAK,CAAI,GAAQ,EAAE,IAAY;IAC7C,MAAM,MAAM,GAAU,EAAE,CAAC;IACzB,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,GAAG,CAAC,MAAM,EAAE,CAAC,IAAI,IAAI,EAAE,CAAC;QAC1C,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,GAAG,IAAI,CAAC,CAAC,CAAC;IACtC,CAAC;IACD,OAAO,MAAM,CAAC;AAChB,CAAC"}
@@ -0,0 +1,23 @@
1
+ /**
2
+ * Return the last path component of a URL.
3
+ * e.g. `lastPathComponent("https://host.com/foo/bar/123")` → `"123"`
4
+ */
5
+ export declare function lastPathComponent(url: string | URL): string;
6
+ /**
7
+ * Parse the expiry date from a time-limited resource URL.
8
+ *
9
+ * Handles:
10
+ * - AWS S3 pre-signed URLs (`*.amazonaws.com`), which encode their expiry via
11
+ * `X-Amz-Date` + `X-Amz-Expires` query parameters.
12
+ * - Brightspace Content Service URLs (`*.content-service.brightspace.com`),
13
+ * which encode their expiry as a Unix timestamp in the `Expires` query parameter.
14
+ *
15
+ * Returns `undefined` if the URL does not contain recognisable expiry information.
16
+ */
17
+ export declare function getURLExpiry(url: string): Date | undefined;
18
+ /**
19
+ * If `url` is a string with no base URL, this returns `url` with
20
+ * the given `baseURL`. Otherwise, this returns `url` as-is.
21
+ */
22
+ export declare function defaultToBaseURL(url: string | URL, baseURL: string | URL): URL;
23
+ //# sourceMappingURL=url.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"url.d.ts","sourceRoot":"","sources":["../../utils/url.ts"],"names":[],"mappings":"AAEA;;;GAGG;AACH,wBAAgB,iBAAiB,CAAC,GAAG,EAAE,MAAM,GAAG,GAAG,GAAG,MAAM,CAG3D;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,YAAY,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,CAuB1D;AAED;;;GAGG;AACH,wBAAgB,gBAAgB,CAC9B,GAAG,EAAE,MAAM,GAAG,GAAG,EACjB,OAAO,EAAE,MAAM,GAAG,GAAG,GACpB,GAAG,CAML"}
@@ -0,0 +1,53 @@
1
+ import { addSeconds, parse } from "date-fns";
2
+ /**
3
+ * Return the last path component of a URL.
4
+ * e.g. `lastPathComponent("https://host.com/foo/bar/123")` → `"123"`
5
+ */
6
+ export function lastPathComponent(url) {
7
+ if (typeof url === "string")
8
+ url = new URL(url);
9
+ return url.pathname.split("/").at(-1);
10
+ }
11
+ /**
12
+ * Parse the expiry date from a time-limited resource URL.
13
+ *
14
+ * Handles:
15
+ * - AWS S3 pre-signed URLs (`*.amazonaws.com`), which encode their expiry via
16
+ * `X-Amz-Date` + `X-Amz-Expires` query parameters.
17
+ * - Brightspace Content Service URLs (`*.content-service.brightspace.com`),
18
+ * which encode their expiry as a Unix timestamp in the `Expires` query parameter.
19
+ *
20
+ * Returns `undefined` if the URL does not contain recognisable expiry information.
21
+ */
22
+ export function getURLExpiry(url) {
23
+ const urlObj = new URL(url);
24
+ if (urlObj.hostname.endsWith(".amazonaws.com")) {
25
+ const expiresIn = urlObj.searchParams.get("X-Amz-Expires");
26
+ if (!expiresIn)
27
+ return undefined;
28
+ const startDate = urlObj.searchParams.get("X-Amz-Date");
29
+ if (!startDate)
30
+ return undefined;
31
+ return addSeconds(parse(startDate, "yyyyMMdd'T'HHmmssX", new Date()), +expiresIn);
32
+ }
33
+ if (urlObj.hostname.endsWith("content-service.brightspace.com")) {
34
+ const expires = urlObj.searchParams.get("Expires");
35
+ if (!expires)
36
+ return undefined;
37
+ return new Date(+expires * 1000);
38
+ }
39
+ return undefined;
40
+ }
41
+ /**
42
+ * If `url` is a string with no base URL, this returns `url` with
43
+ * the given `baseURL`. Otherwise, this returns `url` as-is.
44
+ */
45
+ export function defaultToBaseURL(url, baseURL) {
46
+ try {
47
+ return new URL(url);
48
+ }
49
+ catch {
50
+ return new URL(url, baseURL);
51
+ }
52
+ }
53
+ //# sourceMappingURL=url.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"url.js","sourceRoot":"","sources":["../../utils/url.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,KAAK,EAAE,MAAM,UAAU,CAAC;AAE7C;;;GAGG;AACH,MAAM,UAAU,iBAAiB,CAAC,GAAiB;IACjD,IAAI,OAAO,GAAG,KAAK,QAAQ;QAAE,GAAG,GAAG,IAAI,GAAG,CAAC,GAAG,CAAC,CAAC;IAChD,OAAO,GAAG,CAAC,QAAQ,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAE,CAAC;AACzC,CAAC;AAED;;;;;;;;;;GAUG;AACH,MAAM,UAAU,YAAY,CAAC,GAAW;IACtC,MAAM,MAAM,GAAG,IAAI,GAAG,CAAC,GAAG,CAAC,CAAC;IAE5B,IAAI,MAAM,CAAC,QAAQ,CAAC,QAAQ,CAAC,gBAAgB,CAAC,EAAE,CAAC;QAC/C,MAAM,SAAS,GAAG,MAAM,CAAC,YAAY,CAAC,GAAG,CAAC,eAAe,CAAC,CAAC;QAC3D,IAAI,CAAC,SAAS;YAAE,OAAO,SAAS,CAAC;QAEjC,MAAM,SAAS,GAAG,MAAM,CAAC,YAAY,CAAC,GAAG,CAAC,YAAY,CAAC,CAAC;QACxD,IAAI,CAAC,SAAS;YAAE,OAAO,SAAS,CAAC;QAEjC,OAAO,UAAU,CACf,KAAK,CAAC,SAAS,EAAE,oBAAoB,EAAE,IAAI,IAAI,EAAE,CAAC,EAClD,CAAC,SAAS,CACX,CAAC;IACJ,CAAC;IAED,IAAI,MAAM,CAAC,QAAQ,CAAC,QAAQ,CAAC,iCAAiC,CAAC,EAAE,CAAC;QAChE,MAAM,OAAO,GAAG,MAAM,CAAC,YAAY,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC;QACnD,IAAI,CAAC,OAAO;YAAE,OAAO,SAAS,CAAC;QAC/B,OAAO,IAAI,IAAI,CAAC,CAAC,OAAO,GAAG,IAAI,CAAC,CAAC;IACnC,CAAC;IAED,OAAO,SAAS,CAAC;AACnB,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,gBAAgB,CAC9B,GAAiB,EACjB,OAAqB;IAErB,IAAI,CAAC;QACH,OAAO,IAAI,GAAG,CAAC,GAAG,CAAC,CAAC;IACtB,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,IAAI,GAAG,CAAC,GAAG,EAAE,OAAO,CAAC,CAAC;IAC/B,CAAC;AACH,CAAC"}