lamp-core-lst 2025.11.1-3.basic

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 (130) hide show
  1. package/.github/workflows/publish.yml +34 -0
  2. package/LICENSE.md +29 -0
  3. package/MANUAL.md +26 -0
  4. package/README.md +126 -0
  5. package/cli.js +2 -0
  6. package/dist/index.d.ts +64 -0
  7. package/dist/index.js +311 -0
  8. package/dist/model/Activity.d.ts +81 -0
  9. package/dist/model/Activity.js +30 -0
  10. package/dist/model/ActivityEvent.d.ts +51 -0
  11. package/dist/model/ActivityEvent.js +21 -0
  12. package/dist/model/ActivitySpec.d.ts +38 -0
  13. package/dist/model/ActivitySpec.js +12 -0
  14. package/dist/model/Credential.d.ts +21 -0
  15. package/dist/model/Credential.js +12 -0
  16. package/dist/model/DynamicAttachment.d.ts +34 -0
  17. package/dist/model/DynamicAttachment.js +12 -0
  18. package/dist/model/Participant.d.ts +30 -0
  19. package/dist/model/Participant.js +12 -0
  20. package/dist/model/Researcher.d.ts +27 -0
  21. package/dist/model/Researcher.js +12 -0
  22. package/dist/model/ResearcherSettings.d.ts +57 -0
  23. package/dist/model/ResearcherSettings.js +12 -0
  24. package/dist/model/Sensor.d.ts +22 -0
  25. package/dist/model/Sensor.js +12 -0
  26. package/dist/model/SensorEvent.d.ts +18 -0
  27. package/dist/model/SensorEvent.js +12 -0
  28. package/dist/model/SensorSpec.d.ts +13 -0
  29. package/dist/model/SensorSpec.js +12 -0
  30. package/dist/model/Study.d.ts +24 -0
  31. package/dist/model/Study.js +12 -0
  32. package/dist/model/Type.d.ts +56 -0
  33. package/dist/model/Type.js +30 -0
  34. package/dist/model/index.d.ts +12 -0
  35. package/dist/model/index.js +24 -0
  36. package/dist/service/API.service.d.ts +12 -0
  37. package/dist/service/API.service.js +82 -0
  38. package/dist/service/Activity.service.d.ts +101 -0
  39. package/dist/service/Activity.service.js +756 -0
  40. package/dist/service/ActivityEvent.service.d.ts +46 -0
  41. package/dist/service/ActivityEvent.service.js +303 -0
  42. package/dist/service/ActivitySpec.service.d.ts +31 -0
  43. package/dist/service/ActivitySpec.service.js +173 -0
  44. package/dist/service/Credential.service.d.ts +38 -0
  45. package/dist/service/Credential.service.js +319 -0
  46. package/dist/service/Demo.d.ts +14 -0
  47. package/dist/service/Demo.js +24 -0
  48. package/dist/service/Fetch.d.ts +30 -0
  49. package/dist/service/Fetch.js +245 -0
  50. package/dist/service/Participant.service.d.ts +42 -0
  51. package/dist/service/Participant.service.js +312 -0
  52. package/dist/service/Researcher.service.d.ts +34 -0
  53. package/dist/service/Researcher.service.js +252 -0
  54. package/dist/service/ResearcherSettings.service.d.ts +16 -0
  55. package/dist/service/ResearcherSettings.service.js +114 -0
  56. package/dist/service/Sensor.service.d.ts +47 -0
  57. package/dist/service/Sensor.service.js +372 -0
  58. package/dist/service/SensorEvent.service.d.ts +44 -0
  59. package/dist/service/SensorEvent.service.js +302 -0
  60. package/dist/service/SensorSpec.service.d.ts +31 -0
  61. package/dist/service/SensorSpec.service.js +171 -0
  62. package/dist/service/Study.service.d.ts +42 -0
  63. package/dist/service/Study.service.js +286 -0
  64. package/dist/service/Type.service.d.ts +48 -0
  65. package/dist/service/Type.service.js +352 -0
  66. package/dist/service/index.d.ts +13 -0
  67. package/dist/service/index.js +25 -0
  68. package/docs/APIApi.md +82 -0
  69. package/docs/AccessCitation.md +11 -0
  70. package/docs/Activity.md +13 -0
  71. package/docs/ActivityApi.md +356 -0
  72. package/docs/ActivityEvent.md +13 -0
  73. package/docs/ActivityEventApi.md +251 -0
  74. package/docs/ActivitySpec.md +14 -0
  75. package/docs/ActivitySpecApi.md +222 -0
  76. package/docs/Credential.md +12 -0
  77. package/docs/CredentialApi.md +175 -0
  78. package/docs/Document.md +9 -0
  79. package/docs/DurationInterval.md +11 -0
  80. package/docs/DurationIntervalLegacy.md +10 -0
  81. package/docs/DynamicAttachment.md +14 -0
  82. package/docs/Error.md +8 -0
  83. package/docs/Metadata.md +8 -0
  84. package/docs/Participant.md +14 -0
  85. package/docs/ParticipantApi.md +312 -0
  86. package/docs/Researcher.md +12 -0
  87. package/docs/ResearcherApi.md +223 -0
  88. package/docs/Sensor.md +12 -0
  89. package/docs/SensorApi.md +356 -0
  90. package/docs/SensorEvent.md +11 -0
  91. package/docs/SensorEventApi.md +250 -0
  92. package/docs/SensorSpec.md +10 -0
  93. package/docs/SensorSpecApi.md +222 -0
  94. package/docs/Study.md +11 -0
  95. package/docs/StudyApi.md +268 -0
  96. package/docs/TemporalSlice.md +13 -0
  97. package/docs/TypeApi.md +274 -0
  98. package/package.json +44 -0
  99. package/src/index.ts +256 -0
  100. package/src/model/Activity.ts +93 -0
  101. package/src/model/ActivityEvent.ts +63 -0
  102. package/src/model/ActivitySpec.ts +45 -0
  103. package/src/model/Credential.ts +26 -0
  104. package/src/model/DynamicAttachment.ts +42 -0
  105. package/src/model/Participant.ts +37 -0
  106. package/src/model/Researcher.ts +33 -0
  107. package/src/model/ResearcherSettings.ts +65 -0
  108. package/src/model/Sensor.ts +27 -0
  109. package/src/model/SensorEvent.ts +22 -0
  110. package/src/model/SensorSpec.ts +16 -0
  111. package/src/model/Study.ts +29 -0
  112. package/src/model/Type.ts +68 -0
  113. package/src/model/index.ts +12 -0
  114. package/src/service/API.service.ts +29 -0
  115. package/src/service/Activity.service.ts +625 -0
  116. package/src/service/ActivityEvent.service.ts +244 -0
  117. package/src/service/ActivitySpec.service.ts +98 -0
  118. package/src/service/Credential.service.ts +268 -0
  119. package/src/service/Demo.ts +21 -0
  120. package/src/service/Fetch.ts +187 -0
  121. package/src/service/Participant.service.ts +217 -0
  122. package/src/service/Researcher.service.ts +147 -0
  123. package/src/service/ResearcherSettings.service.ts +62 -0
  124. package/src/service/Sensor.service.ts +256 -0
  125. package/src/service/SensorEvent.service.ts +239 -0
  126. package/src/service/SensorSpec.service.ts +96 -0
  127. package/src/service/Study.service.ts +187 -0
  128. package/src/service/Type.service.ts +297 -0
  129. package/src/service/index.ts +13 -0
  130. package/tsconfig.json +29 -0
@@ -0,0 +1,625 @@
1
+ import { Fetch, Configuration } from "./Fetch"
2
+ import { Activity } from "../model/Activity"
3
+ import { Identifier } from "../model/Type"
4
+ import { Participant } from "../model/Participant"
5
+ import { Demo } from "./Demo"
6
+ import jsonata from "jsonata"
7
+
8
+ export class ActivityService {
9
+ public configuration?: Configuration
10
+
11
+ /**
12
+ * Get the set of all activities.
13
+ */
14
+ public async all(transform?: string): Promise<Activity[]> {
15
+ if (this.configuration.base === "https://demo.lamp.digital") {
16
+ // DEMO
17
+ let auth = (this.configuration.authorization || ":").split(":")
18
+ let credential = Demo.Credential.filter((x) => x["access_key"] === auth[0] && x["secret_key"] === auth[1])
19
+ if (credential.length === 0) return Promise.resolve({ error: "403.invalid-credentials" } as any)
20
+ let output = Demo.Activity?.map((x) => Object.assign(new Activity(), x))
21
+ output = typeof transform === "string" ? jsonata(transform).evaluate(output) : output
22
+ return Promise.resolve(output)
23
+ }
24
+ return (await Fetch.get<{ data: any[] }>(`/activity`, this.configuration)).data?.map((x) =>
25
+ Object.assign(new Activity(), x)
26
+ )
27
+ }
28
+
29
+ /**
30
+ * Get the set of all activities available to a participant, by participant identifier.
31
+ * @param participantId
32
+ */
33
+ public async allByParticipant(
34
+ participantId: Identifier,
35
+ transform?: string,
36
+ ignore_binary?: boolean,
37
+ limit?: number,
38
+ offset?: number
39
+ ): Promise<{ data: Activity[], total: number }> {
40
+ if (participantId === null || participantId === undefined)
41
+ throw new Error("Required parameter participantId was null or undefined when calling activityAllByParticipant.")
42
+ if (ignore_binary === null || ignore_binary === undefined) ignore_binary = false
43
+ if (this.configuration.base === "https://demo.lamp.digital") {
44
+ // DEMO
45
+ let auth = (this.configuration.authorization || ":").split(":")
46
+ let credential = Demo.Credential.filter((x) => x["access_key"] === auth[0] && x["secret_key"] === auth[1])
47
+ if (credential.length === 0) return Promise.resolve({ error: "403.invalid-credentials" } as any)
48
+ if (participantId === "me") participantId = credential.length > 0 ? credential[0]["origin"] : participantId
49
+
50
+ if (Demo.Participant.filter((x) => x["id"] === participantId).length > 0) {
51
+ let output = Demo.Activity.filter((x) =>
52
+ Demo.Participant.filter((y) => y["id"] === participantId)
53
+ ?.map((y) => y["#parent"])
54
+ .includes(x["#parent"])
55
+ )?.map((x) => Object.assign(new Activity(), x))
56
+ output = typeof transform === "string" ? jsonata(transform).evaluate(output) : output
57
+ // For demo, return all data with total count
58
+ const total = output.length
59
+ const paginatedOutput = limit !== undefined && offset !== undefined
60
+ ? output.slice(offset, offset + limit)
61
+ : output
62
+ return Promise.resolve({ data: paginatedOutput, total })
63
+ } else {
64
+ return Promise.resolve({ error: "404.not-found" } as any)
65
+ }
66
+ }
67
+ const params = new URLSearchParams()
68
+ params.append('ignore_binary', String(ignore_binary))
69
+ if (limit !== undefined && limit !== null) {
70
+ params.append('limit', limit.toString())
71
+ }
72
+ if (offset !== undefined && offset !== null) {
73
+ params.append('offset', offset.toString())
74
+ }
75
+ const queryString = params.toString()
76
+ const result: any = await Fetch.get<{ data: { data: Activity[], total: number } }>(
77
+ `/participant/${participantId}/activity?${queryString}`,
78
+ this.configuration
79
+ )
80
+
81
+ // Handle the response structure - API returns { data: { data: Activity[], total: number } }
82
+ let activitiesArray: any[] = []
83
+ let totalCount = 0
84
+
85
+ if (result && result.data) {
86
+ // API wraps response in { data: { data: Activity[], total: number } }
87
+ const responseData = result.data
88
+ if (Array.isArray(responseData.data)) {
89
+ activitiesArray = responseData.data
90
+ totalCount = responseData.total || 0
91
+ } else if (Array.isArray(responseData)) {
92
+ // Fallback: if responseData is directly an array
93
+ activitiesArray = responseData
94
+ totalCount = responseData.length
95
+ }
96
+ } else if (Array.isArray(result)) {
97
+ // Legacy fallback: if result is directly an array
98
+ activitiesArray = result
99
+ totalCount = result.length
100
+ }
101
+
102
+ return {
103
+ data: activitiesArray.map((x: any) => Object.assign(new Activity(), x)),
104
+ total: totalCount
105
+ }
106
+ }
107
+
108
+ /**
109
+ * Get the set of all activities available to participants of any study conducted by a researcher, by researcher identifier.
110
+ * @param researcherId
111
+ */
112
+ public async allByResearcher(researcherId: Identifier, transform?: string): Promise<Activity[]> {
113
+ if (researcherId === null || researcherId === undefined)
114
+ throw new Error("Required parameter researcherId was null or undefined when calling activityAllByResearcher.")
115
+
116
+ if (this.configuration.base === "https://demo.lamp.digital") {
117
+ // DEMO
118
+ let auth = (this.configuration.authorization || ":").split(":")
119
+ let credential = Demo.Credential.filter((x) => x["access_key"] === auth[0] && x["secret_key"] === auth[1])
120
+ if (credential.length === 0) {
121
+ return Promise.resolve({ error: "403.invalid-credentials" } as any)
122
+ }
123
+ if (researcherId === "me") {
124
+ researcherId = credential.length > 0 ? credential[0]["origin"] : researcherId
125
+ }
126
+
127
+ if (Demo.Researcher.filter((x) => x["id"] === researcherId).length > 0) {
128
+ let output = Demo.Activity.filter((x) =>
129
+ Demo.Study.filter((y) => y["#parent"] === researcherId)
130
+ ?.map((y) => y["id"])
131
+ .includes(x["#parent"])
132
+ )?.map((x) => Object.assign(new Activity(), x))
133
+ output = typeof transform === "string" ? jsonata(transform).evaluate(output) : output
134
+ return Promise.resolve(output)
135
+ } else {
136
+ return Promise.resolve({ error: "404.not-found" } as any)
137
+ }
138
+ }
139
+ return (await Fetch.get<{ data: any[] }>(`/researcher/${researcherId}/activity`, this.configuration)).data?.map(
140
+ (x) => Object.assign(new Activity(), x)
141
+ )
142
+ }
143
+
144
+ /**
145
+ * Get the set of all activities available to participants of a single study, by study identifier.
146
+ * @param studyId
147
+ */
148
+ public async allByStudy(studyId: Identifier, transform?: string, ignore_binary?: boolean): Promise<Activity[]> {
149
+ if (studyId === null || studyId === undefined)
150
+ throw new Error("Required parameter studyId was null or undefined when calling activityAllByStudy.")
151
+ if (ignore_binary === null || ignore_binary === undefined) ignore_binary = false
152
+ if (this.configuration.base === "https://demo.lamp.digital") {
153
+ // DEMO
154
+ let auth = (this.configuration.authorization || ":").split(":")
155
+ let credential = Demo.Credential.filter((x) => x["access_key"] === auth[0] && x["secret_key"] === auth[1])
156
+ if (credential.length === 0) return Promise.resolve({ error: "403.invalid-credentials" } as any)
157
+ if (studyId === "me") studyId = credential.length > 0 ? credential[0]["origin"] : studyId
158
+
159
+ if (Demo.Study.filter((x) => x["id"] === studyId).length > 0) {
160
+ let output = Demo.Activity.filter((x) => x["#parent"] === studyId)?.map((x) => Object.assign(new Activity(), x))
161
+ output = typeof transform === "string" ? jsonata(transform).evaluate(output) : output
162
+ return Promise.resolve(output)
163
+ } else {
164
+ return Promise.resolve({ error: "404.not-found" } as any)
165
+ }
166
+ }
167
+ return (
168
+ await Fetch.get<{ data: any[] }>(`/study/${studyId}/activity?ignore_binary=${ignore_binary}`, this.configuration)
169
+ ).data?.map((x) => Object.assign(new Activity(), x))
170
+ }
171
+ /**
172
+ * Get the set of all activities available to participants of a single study, by participant identifier.
173
+ * @param participantId
174
+ */
175
+ public async listActivities(participantId: Identifier, tab?: string, transform?: string, limit?: number, offset?: number): Promise<{ data: any, total: number }> {
176
+ if (participantId === null || participantId === undefined)
177
+ throw new Error("Required parameter participantId was null or undefined when calling listActivities.")
178
+
179
+ if (this.configuration.base === "https://demo.lamp.digital") {
180
+ // DEMO
181
+ let auth = (this.configuration.authorization || ":").split(":")
182
+ let credential = Demo.Credential.filter((x) => x["access_key"] === auth[0] && x["secret_key"] === auth[1])
183
+ if (credential.length === 0) return Promise.resolve({ error: "403.invalid-credentials" } as any)
184
+ if (participantId === "me") participantId = credential.length > 0 ? credential[0]["origin"] : participantId
185
+
186
+ if (Demo.Participant.filter((x) => x["id"] === participantId).length > 0) {
187
+ let output = Demo.Activity.filter((x) => x["#parent"] === participantId)?.map((x) =>
188
+ Object.assign(new Activity(), x)
189
+ )
190
+ output = typeof transform === "string" ? jsonata(transform).evaluate(output) : output
191
+ return Promise.resolve({ data: output, total: output.length } as any)
192
+ } else {
193
+ return Promise.resolve({ error: "404.not-found" } as any)
194
+ }
195
+ }
196
+
197
+ // Build query string with pagination parameters
198
+ const params = new URLSearchParams()
199
+ if (tab) params.append("tab", tab)
200
+ if (typeof limit === 'number' && limit > 0) params.append("limit", limit.toString())
201
+ if (typeof offset === 'number' && offset > 0) params.append("offset", offset.toString())
202
+ const queryString = params.toString()
203
+
204
+ const result: any = await Fetch.get<{ data: any, total: number }>(
205
+ `/activity/${participantId}/activity${queryString ? `?${queryString}` : ''}`,
206
+ this.configuration
207
+ )
208
+
209
+ // Handle different response structures
210
+ if (result && result.data !== undefined && typeof result.total === 'number') {
211
+ return { data: result.data, total: result.total }
212
+ }
213
+ // Legacy fallback: if result is directly the data object
214
+ if (result && !result.total) {
215
+ return { data: result, total: 0 }
216
+ }
217
+ return { data: {}, total: 0 }
218
+ }
219
+
220
+ /**
221
+ * Create a new Activity under the given Study.
222
+ * @param studyId
223
+ * @param activity
224
+ */
225
+ public async create(studyId: Identifier, activity: Activity): Promise<Identifier> {
226
+ if (studyId === null || studyId === undefined)
227
+ throw new Error("Required parameter studyId was null or undefined when calling activityCreate.")
228
+ if (activity === null || activity === undefined)
229
+ throw new Error("Required parameter activity was null or undefined when calling activityCreate.")
230
+
231
+ if (this.configuration.base === "https://demo.lamp.digital") {
232
+ // DEMO
233
+ let auth = (this.configuration.authorization || ":").split(":")
234
+ let credential = Demo.Credential.filter((x) => x["access_key"] === auth[0] && x["secret_key"] === auth[1])
235
+ if (credential.length === 0) return Promise.resolve({ error: "403.invalid-credentials" } as any)
236
+ if (studyId === "me") studyId = credential.length > 0 ? credential[0]["origin"] : studyId
237
+
238
+ if (Demo.Study.filter((x) => x["id"] === studyId).length > 0) {
239
+ let data = {
240
+ "#type": "Activity",
241
+ "#parent": studyId,
242
+ ...(activity as any),
243
+ id: "activity" + Math.random().toString().substring(2, 6),
244
+ }
245
+ Demo.Activity.push(data)
246
+ return Promise.resolve({ data: data["id"] } as any)
247
+ } else {
248
+ return Promise.resolve({ error: "404.not-found" } as any)
249
+ }
250
+ }
251
+ return await Fetch.post(`/study/${studyId}/activity`, activity, this.configuration)
252
+ }
253
+
254
+ /**
255
+ * Delete an Activity.
256
+ * @param activityId
257
+ */
258
+ public async delete(activityId: Identifier): Promise<Identifier> {
259
+ if (activityId === null || activityId === undefined)
260
+ throw new Error("Required parameter activityId was null or undefined when calling activityDelete.")
261
+
262
+ if (this.configuration.base === "https://demo.lamp.digital") {
263
+ // DEMO
264
+ let auth = (this.configuration.authorization || ":").split(":")
265
+ let credential = Demo.Credential.filter((x) => x["access_key"] === auth[0] && x["secret_key"] === auth[1])
266
+ if (credential.length === 0) return Promise.resolve({ error: "403.invalid-credentials" } as any)
267
+ if (activityId === "me") activityId = credential.length > 0 ? credential[0]["origin"] : activityId
268
+
269
+ let idx = Demo.Activity.findIndex((x) => x["id"] === activityId)
270
+ if (idx >= 0) {
271
+ Demo.Activity.splice(idx, 1)
272
+ Demo.ActivityEvent = Demo.ActivityEvent.filter((x) => x["activity"] !== activityId)
273
+ Demo.Credential = Demo.Credential.filter((x) => x["#parent"] !== activityId)
274
+ Demo.Tags = Demo.Tags.filter((x) => x["#parent"] !== activityId && x["target"] !== activityId)
275
+ return Promise.resolve({} as any)
276
+ } else {
277
+ return Promise.resolve({ error: "404.not-found" } as any)
278
+ }
279
+ }
280
+ return await Fetch.delete(`/activity/${activityId}`, this.configuration)
281
+ }
282
+
283
+ /**
284
+ * Update an Activity's settings.
285
+ * @param activityId
286
+ * @param activity
287
+ */
288
+ public async update(activityId: Identifier, activity: Activity): Promise<Identifier> {
289
+ if (activityId === null || activityId === undefined)
290
+ throw new Error("Required parameter activityId was null or undefined when calling activityUpdate.")
291
+ if (activity === null || activity === undefined)
292
+ throw new Error("Required parameter activity was null or undefined when calling activityUpdate.")
293
+
294
+ if (this.configuration.base === "https://demo.lamp.digital") {
295
+ // DEMO
296
+ let auth = (this.configuration.authorization || ":").split(":")
297
+ let credential = Demo.Credential.filter((x) => x["access_key"] === auth[0] && x["secret_key"] === auth[1])
298
+ if (credential.length === 0) return Promise.resolve({ error: "403.invalid-credentials" } as any)
299
+ if (activityId === "me") activityId = credential.length > 0 ? credential[0]["origin"] : activityId
300
+
301
+ let idx = Demo.Activity.findIndex((x) => x["id"] === activityId)
302
+ if (idx >= 0) {
303
+ Demo.Activity[idx] = {
304
+ "#type": "Activity",
305
+ "#parent": Demo.Activity[idx]["#parent"],
306
+ id: Demo.Activity[idx]["id"],
307
+ spec: Demo.Activity[idx]["spec"],
308
+ name: activity.name ?? Demo.Activity[idx]["name"],
309
+ settings:
310
+ Demo.Activity[idx]["spec"] === "lamp.survey" ? Demo.Activity[idx]["settings"] : (activity.settings as any),
311
+ schedule: activity.schedule as any,
312
+ }
313
+ return Promise.resolve({} as any)
314
+ } else {
315
+ return Promise.resolve({ error: "404.not-found" } as any)
316
+ }
317
+ }
318
+ return await Fetch.put(`/activity/${activityId}`, activity, this.configuration)
319
+ }
320
+
321
+ /**
322
+ * Get a single activity, by identifier.
323
+ * @param activityId
324
+ */
325
+ public async view(activityId: Identifier, transform?: string, ignore_binary?: boolean): Promise<Activity> {
326
+ if (activityId === null || activityId === undefined)
327
+ throw new Error("Required parameter activityId was null or undefined when calling activityView.")
328
+ if (ignore_binary === null || ignore_binary === undefined) ignore_binary = false
329
+ if (this.configuration.base === "https://demo.lamp.digital") {
330
+ // DEMO
331
+ let auth = (this.configuration.authorization || ":").split(":")
332
+ let credential = Demo.Credential.filter((x) => x["access_key"] === auth[0] && x["secret_key"] === auth[1])
333
+ if (credential.length === 0) return Promise.resolve({ error: "403.invalid-credentials" } as any)
334
+ if (activityId === "me") activityId = credential.length > 0 ? credential[0]["origin"] : activityId
335
+
336
+ let data = Demo.Activity.filter((x) => x["id"] === activityId)?.map((x) => Object.assign(new Activity(), x))
337
+ if (data.length > 0) {
338
+ let output = data[0]
339
+ output = typeof transform === "string" ? jsonata(transform).evaluate(output) : output
340
+ return Promise.resolve(output)
341
+ } else {
342
+ return Promise.resolve({ error: "404.not-found" } as any)
343
+ }
344
+ }
345
+ const result: any = await Fetch.get<{ data: Activity }>(`/activity/${activityId}?ignore_binary=${ignore_binary}`, this.configuration)
346
+ // API returns { data: Activity } (single object, not array)
347
+ if (result && result.data) {
348
+ return Object.assign(new Activity(), result.data)
349
+ }
350
+ return null as any
351
+ }
352
+
353
+ /**
354
+ * Get the set of all sub-activities available to a module, by module identifier.
355
+ * @param moduleId
356
+ * @param participantId
357
+ */
358
+ public async moduleByParticipant(
359
+ moduleId: Identifier,
360
+ participantId: Identifier,
361
+ startTime?: number,
362
+ endTime?: number
363
+ ): Promise<any[]> {
364
+ if (participantId === null || participantId === undefined)
365
+ throw new Error("Required parameter participantId was null or undefined when calling moduleByParticipant.")
366
+ if (moduleId === null || moduleId === undefined)
367
+ throw new Error("Required parameter moduleId was null or undefined when calling moduleByParticipant.")
368
+ if (this.configuration.base === "https://demo.lamp.digital") {
369
+ // DEMO
370
+ let auth = (this.configuration.authorization || ":").split(":")
371
+ let credential = Demo.Credential.filter((x) => x["access_key"] === auth[0] && x["secret_key"] === auth[1])
372
+ if (credential.length === 0) return Promise.resolve({ error: "403.invalid-credentials" } as any)
373
+ if (participantId === "me") participantId = credential.length > 0 ? credential[0]["origin"] : participantId
374
+ if (moduleId === "me") moduleId = credential.length > 0 ? credential[0]["origin"] : moduleId
375
+
376
+ if (Demo.Activity.filter((x) => x["id"] === moduleId).length > 0) {
377
+ let output = Demo.Activity.filter((x) => x["#parent"] === moduleId)?.map((x) =>
378
+ Object.assign(new Activity(), x)
379
+ )
380
+
381
+ return Promise.resolve(output)
382
+ } else {
383
+ return Promise.resolve({ error: "404.not-found" } as any)
384
+ }
385
+ }
386
+ const params = new URLSearchParams()
387
+ if (startTime !== undefined && startTime !== null) {
388
+ params.append('startTime', startTime.toString())
389
+ }
390
+ if (endTime !== undefined && endTime !== null) {
391
+ params.append('endTime', endTime.toString())
392
+ }
393
+ const queryString = params.toString()
394
+ const url = `/module/${moduleId}/${participantId}${queryString ? `?${queryString}` : ''}`
395
+ return (
396
+ await Fetch.get<{ data: any[] }>(
397
+ url,
398
+ this.configuration
399
+ )
400
+ ).data?.map((x) => Object.assign(new Activity(), x))
401
+ }
402
+
403
+ /**
404
+ * Get the set of all scheduled activities available to a participant, by participant identifier.
405
+ * @param participantId
406
+ */
407
+ public async scheduledActivities(
408
+ participantId: Identifier,
409
+ transform?: string,
410
+ ignore_binary?: boolean
411
+ ): Promise<Activity[]> {
412
+ if (participantId === null || participantId === undefined)
413
+ throw new Error("Required parameter participantId was null or undefined when calling activityAllByParticipant.")
414
+ if (ignore_binary === null || ignore_binary === undefined) ignore_binary = false
415
+ if (this.configuration.base === "https://demo.lamp.digital") {
416
+ // DEMO
417
+ let auth = (this.configuration.authorization || ":").split(":")
418
+ let credential = Demo.Credential.filter((x) => x["access_key"] === auth[0] && x["secret_key"] === auth[1])
419
+ if (credential.length === 0) return Promise.resolve({ error: "403.invalid-credentials" } as any)
420
+ if (participantId === "me") participantId = credential.length > 0 ? credential[0]["origin"] : participantId
421
+
422
+ if (Demo.Participant.filter((x) => x["id"] === participantId).length > 0) {
423
+ let output = Demo.Activity.filter((x) =>
424
+ Demo.Participant.filter((y) => y["id"] === participantId)
425
+ ?.map((y) => y["#parent"])
426
+ .includes(x["#parent"])
427
+ )?.map((x) => Object.assign(new Activity(), x))
428
+ output = typeof transform === "string" ? jsonata(transform).evaluate(output) : output
429
+ return Promise.resolve(output)
430
+ } else {
431
+ return Promise.resolve({ error: "404.not-found" } as any)
432
+ }
433
+ }
434
+
435
+ const result = (await Fetch.get<{ data: any[] }>(
436
+ `/participant/${participantId}/activitySchedule?ignore_binary=${ignore_binary}`,
437
+ this.configuration
438
+ )) as any
439
+ return result
440
+ }
441
+
442
+ /**
443
+ * Get the set of all empty tabs by participant identifier.
444
+ * @param participantId
445
+ */
446
+ public async emptyTabs(participantId: Identifier, transform?: string): Promise<Activity[]> {
447
+ if (participantId === null || participantId === undefined)
448
+ throw new Error("Required parameter participantId was null or undefined when calling activityAllByParticipant.")
449
+ if (this.configuration.base === "https://demo.lamp.digital") {
450
+ // DEMO
451
+ let auth = (this.configuration.authorization || ":").split(":")
452
+ let credential = Demo.Credential.filter((x) => x["access_key"] === auth[0] && x["secret_key"] === auth[1])
453
+ if (credential.length === 0) return Promise.resolve({ error: "403.invalid-credentials" } as any)
454
+ if (participantId === "me") participantId = credential.length > 0 ? credential[0]["origin"] : participantId
455
+
456
+ if (Demo.Participant.filter((x) => x["id"] === participantId).length > 0) {
457
+ let output = Demo.Activity.filter((x) =>
458
+ Demo.Participant.filter((y) => y["id"] === participantId)
459
+ ?.map((y) => y["#parent"])
460
+ .includes(x["#parent"])
461
+ )?.map((x) => Object.assign(new Activity(), x))
462
+ output = typeof transform === "string" ? jsonata(transform).evaluate(output) : output
463
+ return Promise.resolve(output)
464
+ } else {
465
+ return Promise.resolve({ error: "404.not-found" } as any)
466
+ }
467
+ }
468
+
469
+ const result = (await Fetch.get<{ data: any[] }>(
470
+ `/participant/${participantId}/emptyTab`,
471
+ this.configuration
472
+ )) as any
473
+ return result
474
+ }
475
+
476
+ /**
477
+ * Delete multiple activities.
478
+ * @param activities
479
+ */
480
+ public async deleteActivities(activities:any): Promise<{ error?: string }> {
481
+ if (!activities || activities.length === 0) {
482
+ throw new Error("Required parameter 'activities' was null, undefined, or empty when calling deleteActivities.")
483
+ }
484
+
485
+ // Check if we are in DEMO mode
486
+ if (this.configuration.base === "https://demo.lamp.digital") {
487
+ // Parse demo credentials from authorization (format: "access_key:secret_key")
488
+ const auth = (this.configuration.authorization || ":").split(":", 2)
489
+ const [access_key, secret_key] = auth
490
+
491
+ const credential = Demo.Credential.filter((x) => x["access_key"] === access_key && x["secret_key"] === secret_key)
492
+
493
+ // Invalid credentials
494
+ if (credential.length === 0) {
495
+ return { error: "403.invalid-credentials" }
496
+ }
497
+
498
+ // Map "me" to the credential's origin if present
499
+ const resolvedActivities = activities.map((id) =>
500
+ id === "me" && credential[0]["origin"] ? credential[0]["origin"] : id
501
+ )
502
+
503
+ // Track deleted and not-found IDs (for debugging or reporting)
504
+ const notFound: string[] = []
505
+
506
+ for (const activityId of resolvedActivities) {
507
+ const idx = Demo.Activity.findIndex((x) => x["id"] === activityId)
508
+
509
+ if (idx >= 0) {
510
+ // Remove related records
511
+ Demo.ActivityEvent = Demo.ActivityEvent.filter((x) => x["activity"] !== activityId)
512
+ Demo.Credential = Demo.Credential.filter((x) => x["#parent"] !== activityId)
513
+ Demo.Tags = Demo.Tags.filter((x) => x["#parent"] !== activityId && x["target"] !== activityId)
514
+
515
+ // Remove the activity itself
516
+ Demo.Activity.splice(idx, 1)
517
+ } else {
518
+ notFound.push(activityId)
519
+ }
520
+ }
521
+
522
+ // Return error if any IDs were not found
523
+ if (notFound.length > 0) {
524
+ return { error: `404.not-found: ${notFound.join(", ")}` }
525
+ }
526
+ }
527
+ return await Fetch.delete(`/activities`, this.configuration, activities)
528
+ }
529
+
530
+
531
+ /**
532
+ * Get the set of all sub-activities available to a module in participant feed, by module identifier,participant Identifier,startTime and EndTime.
533
+ * @param participantId
534
+ * @param modules
535
+ */
536
+ public async feedModules(participantId: Identifier, modules: any): Promise<any[]> {
537
+ if (participantId === null || participantId === undefined)
538
+ throw new Error("Required parameter participantId was null or undefined when calling feedModules.")
539
+ if (modules === null || modules === undefined)
540
+ throw new Error("Required parameter modules was null or undefined when calling feedModules.")
541
+ if (this.configuration.base === "https://demo.lamp.digital") {
542
+ // DEMO
543
+ let auth = (this.configuration.authorization || ":").split(":")
544
+ let credential = Demo.Credential.filter((x) => x["access_key"] === auth[0] && x["secret_key"] === auth[1])
545
+ if (credential.length === 0) return Promise.resolve({ error: "403.invalid-credentials" } as any)
546
+ if (participantId === "me") participantId = credential.length > 0 ? credential[0]["origin"] : participantId
547
+
548
+ if (Demo.Participant.filter((x) => x["id"] === participantId).length > 0) {
549
+ let output = Demo.Activity.filter((x) =>
550
+ Demo.Participant.filter((y) => y["id"] === participantId)
551
+ ?.map((y) => y["#parent"])
552
+ .includes(x["#parent"])
553
+ )?.map((x) => Object.assign(new Activity(), x))
554
+
555
+ return Promise.resolve(output)
556
+ } else {
557
+ return Promise.resolve({ error: "404.not-found" } as any)
558
+ }
559
+ }
560
+ return (await Fetch.post<{ data: any[] }>(`/feed/module/${participantId}`, this.configuration)).data?.map((x) =>
561
+ Object.assign(new Activity(), x)
562
+ )
563
+ }
564
+
565
+ /**
566
+ * Get the list of favorite activity IDs for a participant.
567
+ * Returns custom selected activity IDs if Researcher_settings choice is "custom",
568
+ * otherwise returns the last 10 activity IDs most recently added to lamp.dashboard.favorite_activities tag.
569
+ * @param participantId
570
+ * @param transform
571
+ */
572
+ public async favoriteActivityIds(participantId: Identifier, transform?: string): Promise<string[]> {
573
+ if (participantId === null || participantId === undefined)
574
+ throw new Error("Required parameter participantId was null or undefined when calling favoriteActivityIds.")
575
+
576
+ if (this.configuration.base === "https://demo.lamp.digital") {
577
+ // DEMO
578
+ let auth = (this.configuration.authorization || ":").split(":")
579
+ let credential = Demo.Credential.filter((x) => x["access_key"] === auth[0] && x["secret_key"] === auth[1])
580
+ if (credential.length === 0) return Promise.resolve({ error: "403.invalid-credentials" } as any)
581
+ if (participantId === "me") participantId = credential.length > 0 ? credential[0]["origin"] : participantId
582
+
583
+ if (Demo.Participant.filter((x) => x["id"] === participantId).length > 0) {
584
+ // Return empty array for demo mode
585
+ let output: string[] = []
586
+ output = typeof transform === "string" ? jsonata(transform).evaluate(output) : output
587
+ return Promise.resolve(output)
588
+ } else {
589
+ return Promise.resolve({ error: "404.not-found" } as any)
590
+ }
591
+ }
592
+
593
+ const result = await Fetch.get<{ data: string[] }>(
594
+ `/participant/${participantId}/favorite_activities`,
595
+ this.configuration
596
+ )
597
+ let output = result.data || []
598
+ output = typeof transform === "string" ? jsonata(transform).evaluate(output) : output
599
+ return output
600
+ }
601
+
602
+ /**
603
+ * Get feed details (schedule window entries with completion) for a participant and optional date (ms since epoch).
604
+ * @param participantId
605
+ * @param dateMs optional UTC ms for the day to fetch; defaults to today if omitted
606
+ */
607
+ public async feedDetails(participantId: Identifier, dateMs?: string): Promise<any> {
608
+ if (participantId === null || participantId === undefined)
609
+ throw new Error("Required parameter participantId was null or undefined when calling feedDetails.")
610
+
611
+ if (this.configuration.base === "https://demo.lamp.digital") {
612
+ // DEMO: no server-side computation; return empty set
613
+ let auth = (this.configuration.authorization || ":").split(":")
614
+ let credential = Demo.Credential.filter((x) => x["access_key"] === auth[0] && x["secret_key"] === auth[1])
615
+ if (credential.length === 0) return Promise.resolve({ error: "403.invalid-credentials" } as any)
616
+ if (participantId === "me") participantId = credential.length > 0 ? credential[0]["origin"] : participantId
617
+ return []
618
+ }
619
+
620
+ const tzOffsetMinutes = new Date().getTimezoneOffset()
621
+ const url = `/participant/${participantId}/feedDetails?date=${dateMs}&tzOffsetMinutes=${tzOffsetMinutes}`
622
+ const result = await Fetch.get<{ data: any }>(url, this.configuration)
623
+ return result.data || {}
624
+ }
625
+ }