@rezamirzapour/pod-sdk 1.0.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.
package/dist/index.js ADDED
@@ -0,0 +1,1114 @@
1
+ 'use strict';
2
+
3
+ Object.defineProperty(exports, '__esModule', { value: true });
4
+
5
+ var http = require('@rezamirzapour/http');
6
+
7
+ // src/services/sso/index.ts
8
+
9
+ // src/utils/crypto.ts
10
+ function encodeBase64(str) {
11
+ if (typeof btoa === "function") {
12
+ return btoa(str);
13
+ }
14
+ return Buffer.from(str).toString("base64");
15
+ }
16
+ async function createRsaSignature(value, privateKeyPem, encoding = "base64") {
17
+ const pemHeader = "-----BEGIN PRIVATE KEY-----";
18
+ const pemFooter = "-----END PRIVATE KEY-----";
19
+ const pemContents = privateKeyPem.replace(pemHeader, "").replace(pemFooter, "").replace(/\s+/g, "");
20
+ const binaryString = typeof atob === "function" ? atob(pemContents) : Buffer.from(pemContents, "base64").toString("binary");
21
+ const binaryDer = Uint8Array.from(binaryString, (c) => c.charCodeAt(0));
22
+ const cryptoKey = await crypto.subtle.importKey(
23
+ "pkcs8",
24
+ binaryDer.buffer,
25
+ {
26
+ name: "RSASSA-PKCS1-v1_5",
27
+ hash: "SHA-256"
28
+ },
29
+ false,
30
+ ["sign"]
31
+ );
32
+ const encoder = new TextEncoder();
33
+ const data = encoder.encode(value);
34
+ const signature = await crypto.subtle.sign("RSASSA-PKCS1-v1_5", cryptoKey, data);
35
+ const rawBytes = new Uint8Array(signature);
36
+ if (encoding === "base64") {
37
+ if (typeof btoa === "function") {
38
+ return btoa(String.fromCharCode(...rawBytes));
39
+ }
40
+ return Buffer.from(rawBytes).toString("base64");
41
+ }
42
+ return Array.from(rawBytes).map((b) => b.toString(16).padStart(2, "0")).join("");
43
+ }
44
+ async function generatePodSignatureHeader(keyId, privateKeyPem) {
45
+ if (!privateKeyPem) return "";
46
+ const sign = await createRsaSignature("host: accounts.pod.ir", privateKeyPem, "base64");
47
+ return `Signature keyId=${keyId}, signature=${sign}, headers=host`;
48
+ }
49
+
50
+ // src/services/sso/index.ts
51
+ var SsoService = class {
52
+ http;
53
+ clientId;
54
+ clientSecret;
55
+ apiToken;
56
+ privateKeyPem;
57
+ websiteUrl;
58
+ revalidate;
59
+ constructor(options) {
60
+ this.clientId = options.clientId || "";
61
+ this.clientSecret = options.clientSecret || "";
62
+ this.apiToken = options.apiToken || "";
63
+ this.privateKeyPem = options.privateKeyPem || "";
64
+ this.websiteUrl = options.websiteUrl || "";
65
+ this.revalidate = Number(options.revalidate) || 0;
66
+ this.http = http.createNextHttp({
67
+ baseUrl: options.baseUrl,
68
+ serviceName: "POD-SSO"
69
+ });
70
+ }
71
+ /**
72
+ * Performs handshake with POD SSO to obtain a keyId for OTP signing.
73
+ */
74
+ async handshake(deviceUid, ip) {
75
+ const params = {
76
+ device_type: "Desktop",
77
+ algorithm: "rsa-sha256",
78
+ device_uid: deviceUid,
79
+ device_client_ip: ip
80
+ };
81
+ try {
82
+ const result = await this.http.post(
83
+ `/oauth2/clients/handshake/${this.clientId}`,
84
+ void 0,
85
+ {
86
+ params,
87
+ headers: {
88
+ "Content-Type": "application/x-www-form-urlencoded; charset=utf-8",
89
+ Accept: "application/json; charset=utf-8",
90
+ Authorization: `Bearer ${this.apiToken}`
91
+ }
92
+ }
93
+ );
94
+ return {
95
+ hasError: false,
96
+ result
97
+ };
98
+ } catch (err) {
99
+ return {
100
+ hasError: true,
101
+ message: err.data?.error_description || err.message,
102
+ errorCode: err.status
103
+ };
104
+ }
105
+ }
106
+ /**
107
+ * Sends an OTP SMS to the specified phone number.
108
+ */
109
+ async sendOtpCode(keyId, phoneNumber, options) {
110
+ try {
111
+ const authorization = await generatePodSignatureHeader(keyId, this.privateKeyPem);
112
+ const params = {
113
+ identityType: options?.identityType || "phone_number",
114
+ response_type: options?.response_type || "code",
115
+ referrerType: options?.referrerType || "username",
116
+ linkDeliveryType: options?.linkDeliveryType || "SMS",
117
+ scope: options?.scope || "phone profile",
118
+ redirect_uri: options?.redirect_uri || `${this.websiteUrl}/login`
119
+ };
120
+ const result = await this.http.post(`/oauth2/otp/authorize/${phoneNumber}`, void 0, {
121
+ params,
122
+ headers: {
123
+ "Content-Type": "application/x-www-form-urlencoded; charset=utf-8",
124
+ Accept: "application/json; charset=utf-8",
125
+ Authorization: authorization
126
+ }
127
+ });
128
+ return {
129
+ hasError: false,
130
+ authorization,
131
+ identity: phoneNumber,
132
+ result
133
+ };
134
+ } catch (err) {
135
+ return {
136
+ hasError: true,
137
+ message: err.data?.error_description || err.message
138
+ };
139
+ }
140
+ }
141
+ /**
142
+ * Verifies an OTP code received by SMS.
143
+ */
144
+ async verifyOtpCode(authorization, phoneNumber, code, redirectUri) {
145
+ const params = {
146
+ otp: code,
147
+ redirect_uri: redirectUri || `${this.websiteUrl}/login`
148
+ };
149
+ try {
150
+ const result = await this.http.post(
151
+ `/oauth2/otp/verify/${phoneNumber}`,
152
+ void 0,
153
+ {
154
+ params,
155
+ headers: {
156
+ "Content-Type": "application/x-www-form-urlencoded; charset=utf-8",
157
+ Accept: "application/json; charset=utf-8",
158
+ Authorization: authorization
159
+ }
160
+ }
161
+ );
162
+ return {
163
+ hasError: false,
164
+ result
165
+ };
166
+ } catch (err) {
167
+ return {
168
+ hasError: true,
169
+ message: err.data?.error_description || err.data?.error || err.message,
170
+ errorCode: err.status
171
+ };
172
+ }
173
+ }
174
+ /**
175
+ * Exchanges authorization code for access & refresh tokens.
176
+ */
177
+ async generateToken(code, redirectUri) {
178
+ const clientSignature = encodeBase64(`${this.clientId}:${this.clientSecret}`);
179
+ const params = {
180
+ grant_type: "authorization_code",
181
+ code,
182
+ redirect_uri: redirectUri || `${this.websiteUrl}/login`
183
+ };
184
+ try {
185
+ const result = await this.http.post("/oauth2/token", void 0, {
186
+ params,
187
+ headers: {
188
+ "Content-Type": "application/x-www-form-urlencoded; charset=utf-8",
189
+ Accept: "application/json; charset=utf-8",
190
+ Authorization: `Basic ${clientSignature}`
191
+ }
192
+ });
193
+ return {
194
+ hasError: false,
195
+ result
196
+ };
197
+ } catch (err) {
198
+ return {
199
+ hasError: true,
200
+ message: err.data?.error_description || err.message,
201
+ errorCode: err.status
202
+ };
203
+ }
204
+ }
205
+ /**
206
+ * Refreshes an expired access token using a refresh token.
207
+ */
208
+ async refreshToken(refreshToken) {
209
+ const clientSignature = encodeBase64(`${this.clientId}:${this.clientSecret}`);
210
+ const params = {
211
+ grant_type: "refresh_token",
212
+ refresh_token: refreshToken
213
+ };
214
+ try {
215
+ const result = await this.http.post("/oauth2/token", void 0, {
216
+ params,
217
+ headers: {
218
+ "Content-Type": "application/x-www-form-urlencoded",
219
+ Accept: "application/json",
220
+ Authorization: `Basic ${clientSignature}`
221
+ }
222
+ });
223
+ return {
224
+ hasError: false,
225
+ result
226
+ };
227
+ } catch (err) {
228
+ return {
229
+ hasError: true,
230
+ message: err.data?.error_description || err.message,
231
+ errorCode: err.status
232
+ };
233
+ }
234
+ }
235
+ /**
236
+ * Fetches user profile from SSO using the access token.
237
+ */
238
+ async getUserProfile(accessToken) {
239
+ try {
240
+ const result = await this.http.get("/users", {
241
+ headers: {
242
+ Authorization: `Bearer ${accessToken}`
243
+ },
244
+ next: this.revalidate ? { revalidate: this.revalidate } : void 0
245
+ });
246
+ return {
247
+ hasError: false,
248
+ result
249
+ };
250
+ } catch (err) {
251
+ return {
252
+ hasError: true,
253
+ message: err.message,
254
+ errorCode: err.status
255
+ };
256
+ }
257
+ }
258
+ };
259
+
260
+ // src/services/customPost/crud.ts
261
+ var CustomPostCrudService = class {
262
+ constructor(service, config) {
263
+ this.service = service;
264
+ this.config = config;
265
+ }
266
+ service;
267
+ config;
268
+ buildMetadata(data) {
269
+ return {
270
+ objectInfo: {
271
+ type: this.config.type,
272
+ detailedType: this.config.detailedType
273
+ },
274
+ data
275
+ };
276
+ }
277
+ /**
278
+ * Searches and retrieves all entities matching the query.
279
+ */
280
+ async getAll(params, options) {
281
+ return this.service.searchTimelineByMetadata(
282
+ params || {},
283
+ options
284
+ );
285
+ }
286
+ /**
287
+ * Retrieves a single entity by its numerical ID.
288
+ */
289
+ async getById(id, options) {
290
+ return this.service.getCustomPost(
291
+ { id, offset: 0, size: 1 },
292
+ options
293
+ );
294
+ }
295
+ /**
296
+ * Creates a new entity.
297
+ */
298
+ async create(data, options) {
299
+ return this.service.addCustomPost(
300
+ {
301
+ name: this.config.name,
302
+ content: this.config.content || " ",
303
+ metadata: this.buildMetadata(data)
304
+ },
305
+ options
306
+ );
307
+ }
308
+ /**
309
+ * Creates multiple entities in batch.
310
+ */
311
+ async createMultiple(dataList, options) {
312
+ const items = dataList.map((data) => ({
313
+ name: this.config.name,
314
+ content: this.config.content || " ",
315
+ metadata: this.buildMetadata(data)
316
+ }));
317
+ return this.service.addCustomPostList(items, options);
318
+ }
319
+ /**
320
+ * Updates an existing entity by entityId.
321
+ */
322
+ async update(entityId, data, enable = true, options) {
323
+ return this.service.updateCustomPost(
324
+ {
325
+ entityId,
326
+ name: this.config.name,
327
+ content: this.config.content || " ",
328
+ metadata: this.buildMetadata(data),
329
+ enable
330
+ },
331
+ options
332
+ );
333
+ }
334
+ /**
335
+ * Creates a post and automatically updates it by binding the generated entityId into the record data.
336
+ */
337
+ async createAndBindEntityId(data, options) {
338
+ const createResponse = await this.create(data, options);
339
+ if (!createResponse.hasError && createResponse.result?.entityId) {
340
+ return this.update(
341
+ createResponse.result.entityId,
342
+ {
343
+ ...data,
344
+ entityId: createResponse.result.entityId
345
+ },
346
+ true,
347
+ options
348
+ );
349
+ }
350
+ return createResponse;
351
+ }
352
+ /**
353
+ * Archives (disables) an entity without deleting its history.
354
+ */
355
+ async archive(entityId, data, options) {
356
+ return this.update(entityId, data, false, options);
357
+ }
358
+ /**
359
+ * Deletes an entity permanently.
360
+ */
361
+ async delete(entityId, options) {
362
+ return this.service.deleteCustomPost(entityId, options);
363
+ }
364
+ };
365
+
366
+ // src/services/customPost/index.ts
367
+ var CustomPostService = class {
368
+ http;
369
+ apiToken;
370
+ revalidate;
371
+ constructor(options) {
372
+ this.apiToken = options.apiToken || "";
373
+ this.revalidate = Number(options.revalidate) || 0;
374
+ this.http = http.createNextHttp({
375
+ baseUrl: options.baseUrl,
376
+ serviceName: "POD-CustomPost",
377
+ headers: {
378
+ _token_: this.apiToken
379
+ }
380
+ });
381
+ }
382
+ safeParseJson(value) {
383
+ if (typeof value === "string") {
384
+ try {
385
+ return JSON.parse(value);
386
+ } catch {
387
+ return value;
388
+ }
389
+ }
390
+ return value;
391
+ }
392
+ /**
393
+ * Searches timeline entries by structured metadata query, returning typed items.
394
+ */
395
+ async searchTimelineByMetadata(params, options) {
396
+ const rawParams = {
397
+ ...params,
398
+ ...params.metadata ? { metadata: typeof params.metadata === "object" ? JSON.stringify(params.metadata) : params.metadata } : {},
399
+ ...params.metaQuery ? { metaQuery: typeof params.metaQuery === "object" ? JSON.stringify(params.metaQuery) : params.metaQuery } : {}
400
+ };
401
+ const response = await this.http.get(
402
+ "/srv/core/nzh/biz/searchTimelineByMetadata",
403
+ {
404
+ ...options,
405
+ params: rawParams,
406
+ next: this.revalidate ? { revalidate: this.revalidate, ...options?.next || {} } : options?.next
407
+ }
408
+ );
409
+ if (response?.result && Array.isArray(response.result)) {
410
+ response.result = response.result.map((el) => {
411
+ if (el?.item?.metadata) {
412
+ el.item.metadata = this.safeParseJson(el.item.metadata);
413
+ }
414
+ return el;
415
+ });
416
+ }
417
+ return response;
418
+ }
419
+ /**
420
+ * Retrieves custom posts list or a single post by entityId/id with typed metadata.
421
+ */
422
+ async getCustomPost(params, options) {
423
+ const response = await this.http.get(
424
+ "/srv/core/nzh/biz/customPostList",
425
+ {
426
+ ...options,
427
+ params,
428
+ next: this.revalidate ? { revalidate: this.revalidate, ...options?.next || {} } : options?.next
429
+ }
430
+ );
431
+ if (response?.result && Array.isArray(response.result)) {
432
+ response.result = response.result.map((el) => {
433
+ if (el?.metadata) {
434
+ el.metadata = this.safeParseJson(el.metadata);
435
+ }
436
+ return el;
437
+ });
438
+ }
439
+ return response;
440
+ }
441
+ /**
442
+ * Creates a new custom post with strongly typed metadata.
443
+ */
444
+ async addCustomPost(params, options) {
445
+ const payload = {
446
+ ...params,
447
+ metadata: typeof params.metadata === "object" ? JSON.stringify(params.metadata) : params.metadata,
448
+ content: params.content || " "
449
+ };
450
+ const response = await this.http.post(
451
+ "/srv/core/nzh/biz/addCustomPost",
452
+ new URLSearchParams(payload),
453
+ {
454
+ ...options,
455
+ headers: {
456
+ "Content-Type": "application/x-www-form-urlencoded",
457
+ _token_: this.apiToken,
458
+ ...options?.headers
459
+ }
460
+ }
461
+ );
462
+ if (response?.result?.metadata) {
463
+ response.result.metadata = this.safeParseJson(response.result.metadata);
464
+ }
465
+ return response;
466
+ }
467
+ /**
468
+ * Creates multiple custom posts in bulk.
469
+ */
470
+ async addCustomPostList(items, options) {
471
+ const promises = items.map((item) => this.addCustomPost(item, options));
472
+ return Promise.all(promises);
473
+ }
474
+ /**
475
+ * Updates an existing custom post by its entityId with typed metadata.
476
+ */
477
+ async updateCustomPost(params, options) {
478
+ const payload = {
479
+ ...params,
480
+ ...params.metadata ? { metadata: typeof params.metadata === "object" ? JSON.stringify(params.metadata) : params.metadata } : {},
481
+ ...params.entityId ? { entityId: params.entityId.toString() } : {}
482
+ };
483
+ const response = await this.http.post(
484
+ "/srv/core/nzh/biz/updateCustomPost",
485
+ new URLSearchParams(payload),
486
+ {
487
+ ...options,
488
+ headers: {
489
+ "Content-Type": "application/x-www-form-urlencoded",
490
+ _token_: this.apiToken,
491
+ ...options?.headers
492
+ }
493
+ }
494
+ );
495
+ if (response?.result?.metadata) {
496
+ response.result.metadata = this.safeParseJson(response.result.metadata);
497
+ }
498
+ return response;
499
+ }
500
+ /**
501
+ * Deletes a custom post by entityId.
502
+ */
503
+ async deleteCustomPost(entityId, options) {
504
+ return this.http.post(
505
+ "/srv/core/nzh/biz/deleteCustomPost",
506
+ void 0,
507
+ {
508
+ ...options,
509
+ params: { entityId }
510
+ }
511
+ );
512
+ }
513
+ /**
514
+ * Factory method to create a high-level Generic CRUD repository for any entity type.
515
+ */
516
+ createCrud(config) {
517
+ return new CustomPostCrudService(this, config);
518
+ }
519
+ };
520
+ var PodspaceService = class {
521
+ http;
522
+ apiToken;
523
+ baseUrl;
524
+ constructor(options) {
525
+ this.baseUrl = options.baseUrl;
526
+ this.apiToken = options.apiToken || "";
527
+ this.http = http.createNextHttp({
528
+ baseUrl: options.baseUrl,
529
+ serviceName: "POD-Podspace",
530
+ headers: {
531
+ Authorization: `Bearer ${this.apiToken}`
532
+ }
533
+ });
534
+ }
535
+ /**
536
+ * Uploads a file (via FormData) to the POD Podspace storage.
537
+ */
538
+ async uploadFile(formData, path = "/", isPublic = true) {
539
+ const params = {
540
+ path,
541
+ isPublic
542
+ };
543
+ return this.http.post("/api/files", formData, {
544
+ params
545
+ });
546
+ }
547
+ /**
548
+ * Builds the public or private URL to download/view a file.
549
+ */
550
+ getFileUrl(hash, isPublic = true) {
551
+ return `${this.baseUrl}/api/files/${hash}?isPublic=${isPublic}`;
552
+ }
553
+ };
554
+ var PodFormService = class {
555
+ http;
556
+ apiToken;
557
+ revalidate;
558
+ constructor(options) {
559
+ this.apiToken = options.apiToken || "";
560
+ this.revalidate = Number(options.revalidate) || 0;
561
+ this.http = http.createNextHttp({
562
+ baseUrl: options.baseUrl,
563
+ serviceName: "POD-PodForm",
564
+ headers: {
565
+ token: this.apiToken,
566
+ accept: "*/*"
567
+ }
568
+ });
569
+ }
570
+ /**
571
+ * Submits responses/answers to a POD Form.
572
+ */
573
+ async sendForm(formId, data) {
574
+ const payload = new URLSearchParams({
575
+ ...data,
576
+ userResponseTimeMilliSeconds: "230000"
577
+ });
578
+ return this.http.post(`/responses/${formId}`, payload, {
579
+ headers: {
580
+ "Content-Type": "application/x-www-form-urlencoded"
581
+ }
582
+ });
583
+ }
584
+ /**
585
+ * Retrieves a form and its questions by ID.
586
+ */
587
+ async getPodformById(id, options) {
588
+ return this.http.get(`/responses/all/${id}`, {
589
+ ...options,
590
+ next: this.revalidate ? { revalidate: this.revalidate, ...options?.next || {} } : options?.next
591
+ });
592
+ }
593
+ };
594
+ var NotificationService = class {
595
+ http;
596
+ apiToken;
597
+ constructor(options) {
598
+ this.apiToken = options.apiToken || "";
599
+ this.http = http.createNextHttp({
600
+ baseUrl: options.baseUrl,
601
+ serviceName: "POD-Notification",
602
+ headers: {
603
+ apiToken: this.apiToken
604
+ }
605
+ });
606
+ }
607
+ /**
608
+ * Sends an SMS notification to one or multiple mobile numbers.
609
+ */
610
+ async sendSms(params) {
611
+ const payload = {
612
+ content: {
613
+ content: params.content,
614
+ mobileNumbers: params.mobileNumbers,
615
+ receiverType: "MOBILE"
616
+ }
617
+ };
618
+ return this.http.post("/service/sms", payload);
619
+ }
620
+ };
621
+ var SocialService = class {
622
+ http;
623
+ apiToken;
624
+ revalidate;
625
+ constructor(options) {
626
+ this.apiToken = options.apiToken || "";
627
+ this.revalidate = Number(options.revalidate) || 0;
628
+ this.http = http.createNextHttp({
629
+ baseUrl: options.baseUrl,
630
+ serviceName: "POD-Social",
631
+ headers: {
632
+ _token_: this.apiToken,
633
+ _token_issuer_: "1"
634
+ }
635
+ });
636
+ }
637
+ /**
638
+ * Retrieves comments for a specific post or subject ID.
639
+ */
640
+ async getCommentList(params, options) {
641
+ return this.http.get("/srv/core/nzh/commentList", {
642
+ ...options,
643
+ params,
644
+ next: this.revalidate ? { revalidate: this.revalidate, ...options?.next || {} } : options?.next
645
+ });
646
+ }
647
+ /**
648
+ * Adds a new comment to a subject.
649
+ */
650
+ async addComment(params) {
651
+ return this.http.get("/srv/core/nzh/comment", {
652
+ params
653
+ });
654
+ }
655
+ /**
656
+ * Likes or dislikes a comment.
657
+ */
658
+ async likeComment(params) {
659
+ return this.http.get("/srv/core/nzh/likeComment", {
660
+ params
661
+ });
662
+ }
663
+ /**
664
+ * Likes or dislikes a post.
665
+ */
666
+ async likePost(params) {
667
+ return this.http.get("/srv/core/nzh/like", {
668
+ params
669
+ });
670
+ }
671
+ };
672
+
673
+ // src/services/cms/formatter.ts
674
+ var CmsDataFormatter = class {
675
+ podspaceUrl;
676
+ constructor(podspaceUrl = "https://podspace.pod.ir") {
677
+ this.podspaceUrl = podspaceUrl;
678
+ }
679
+ generateImage(hash, defaultSrc = "") {
680
+ return hash ? `${this.podspaceUrl}/api/images/${hash}?dl=1` : defaultSrc;
681
+ }
682
+ formatContentItem(item, normalizer) {
683
+ if (typeof item === "number" || !item || typeof item !== "object") {
684
+ return item;
685
+ }
686
+ const newItem = {
687
+ ...JSON.parse(JSON.stringify(item)),
688
+ formatted: {},
689
+ __normalized: {}
690
+ };
691
+ const formatted = {};
692
+ if (Array.isArray(item?.metadata?.content)) {
693
+ item.metadata.content.forEach((detail) => {
694
+ switch (detail.type) {
695
+ case "IMAGE_TYPE": {
696
+ formatted[detail.code] = Array.isArray(detail.value) ? detail.value.map((v) => this.generateImage(v)) : this.generateImage(detail.value);
697
+ break;
698
+ }
699
+ default:
700
+ formatted[detail.code] = detail.value !== void 0 ? detail.value : "";
701
+ }
702
+ });
703
+ }
704
+ if (Array.isArray(item?.metadata?.content_related)) {
705
+ item.metadata.content_related.forEach((detail) => {
706
+ if (detail?.uniqueId && Array.isArray(detail.values)) {
707
+ formatted[detail.uniqueId] = detail.values.map(
708
+ (val) => this.formatContentItem(val)
709
+ );
710
+ }
711
+ });
712
+ }
713
+ newItem.formatted = formatted;
714
+ if (typeof normalizer === "function") {
715
+ newItem.__normalized = normalizer(newItem);
716
+ }
717
+ return newItem;
718
+ }
719
+ formatGetContentResponse(response, normalizer) {
720
+ if (response && Array.isArray(response.result)) {
721
+ const result = response.result.map(
722
+ (item) => this.formatContentItem(item, normalizer)
723
+ );
724
+ return {
725
+ ...response,
726
+ result
727
+ };
728
+ }
729
+ return response || {};
730
+ }
731
+ };
732
+
733
+ // src/services/cms/index.ts
734
+ var CmsService = class {
735
+ http;
736
+ formatter;
737
+ clientId;
738
+ apiToken;
739
+ revalidate;
740
+ constructor(options) {
741
+ this.clientId = options.clientId || "";
742
+ this.apiToken = options.apiToken || "";
743
+ this.revalidate = Number(options.revalidate) || 0;
744
+ this.formatter = new CmsDataFormatter(options.podspaceUrl || "https://podspace.pod.ir");
745
+ this.http = http.createNextHttp({
746
+ baseUrl: options.baseUrl,
747
+ serviceName: "POD-CMS"
748
+ });
749
+ }
750
+ get commonHeaders() {
751
+ return {
752
+ "Client-Id": this.clientId,
753
+ "Content-Type": "application/json"
754
+ };
755
+ }
756
+ get managingHeaders() {
757
+ return {
758
+ ...this.commonHeaders,
759
+ "Access-Token": this.apiToken
760
+ };
761
+ }
762
+ /**
763
+ * Retrieves enabled published content from CMS, formatted with generic metadata type T and optional normalized type P.
764
+ */
765
+ async getContent(params = {}, options = {}) {
766
+ const transferParams = {
767
+ size: 50,
768
+ offset: 0,
769
+ showDetail: true,
770
+ ...params
771
+ };
772
+ try {
773
+ const res = await this.http.get("/api/core/contents/enable", {
774
+ params: transferParams,
775
+ headers: {
776
+ ...this.commonHeaders,
777
+ ...options.headers
778
+ },
779
+ cache: options.cache,
780
+ signal: options.signal,
781
+ next: {
782
+ revalidate: options.revalidate !== void 0 ? options.revalidate === false ? 0 : options.revalidate : this.revalidate
783
+ }
784
+ });
785
+ return this.formatter.formatGetContentResponse(res, options.normalizer);
786
+ } catch {
787
+ return { hasError: true, result: [] };
788
+ }
789
+ }
790
+ /**
791
+ * Retrieves content using managing credentials (Access-Token).
792
+ */
793
+ async getContent2(params = {}, options = {}) {
794
+ const transferParams = {
795
+ size: 50,
796
+ offset: 0,
797
+ showDetail: true,
798
+ ...params
799
+ };
800
+ try {
801
+ const res = await this.http.get("/api/core/contents", {
802
+ params: transferParams,
803
+ headers: {
804
+ ...this.managingHeaders,
805
+ ...options.headers
806
+ },
807
+ cache: options.cache,
808
+ signal: options.signal,
809
+ next: {
810
+ revalidate: options.revalidate !== void 0 ? options.revalidate === false ? 0 : options.revalidate : this.revalidate
811
+ }
812
+ });
813
+ return this.formatter.formatGetContentResponse(res, options.normalizer);
814
+ } catch {
815
+ return { hasError: true, result: [] };
816
+ }
817
+ }
818
+ /**
819
+ * Retrieves unpublished/draft content (enable: false).
820
+ */
821
+ async getUnpublishedContent(params = {}, options = {}) {
822
+ const transferParams = {
823
+ size: 50,
824
+ offset: 0,
825
+ showDetail: true,
826
+ enable: false,
827
+ ...params
828
+ };
829
+ try {
830
+ const res = await this.http.get("/api/core/contents", {
831
+ params: transferParams,
832
+ headers: {
833
+ ...this.managingHeaders,
834
+ ...options.headers
835
+ },
836
+ cache: options.cache,
837
+ signal: options.signal,
838
+ next: {
839
+ revalidate: options.revalidate !== void 0 ? options.revalidate === false ? 0 : options.revalidate : this.revalidate
840
+ }
841
+ });
842
+ return this.formatter.formatGetContentResponse(res, options.normalizer);
843
+ } catch {
844
+ return { hasError: true, result: [] };
845
+ }
846
+ }
847
+ /**
848
+ * Retrieves single content by entityId and optional contentTypeUniqueId.
849
+ */
850
+ async getContentByEntityId(params, options = {}) {
851
+ const url = params.contentTypeUniqueId ? `/api/core/contents/${params.contentTypeUniqueId}/enable/${params.entityId}` : `/api/core/contents/enable/${params.entityId}`;
852
+ try {
853
+ const res = await this.http.get(url, {
854
+ headers: {
855
+ ...this.commonHeaders,
856
+ ...options.headers
857
+ },
858
+ cache: options.cache,
859
+ signal: options.signal,
860
+ next: {
861
+ revalidate: options.revalidate !== void 0 ? options.revalidate === false ? 0 : options.revalidate : this.revalidate
862
+ }
863
+ });
864
+ return this.formatter.formatGetContentResponse(res, options.normalizer);
865
+ } catch {
866
+ return { hasError: true, result: [] };
867
+ }
868
+ }
869
+ /**
870
+ * Retrieves tag/category tree.
871
+ */
872
+ async getCategories(params = {}, options = {}) {
873
+ try {
874
+ return await this.http.get("/api/core/tags/root/tree/enable", {
875
+ params,
876
+ headers: {
877
+ ...this.commonHeaders,
878
+ ...options.headers
879
+ },
880
+ cache: options.cache,
881
+ signal: options.signal,
882
+ next: {
883
+ revalidate: options.revalidate !== void 0 ? options.revalidate === false ? 0 : options.revalidate : this.revalidate
884
+ }
885
+ });
886
+ } catch {
887
+ return { hasError: true, result: [] };
888
+ }
889
+ }
890
+ /**
891
+ * Retrieves details of a content type structure.
892
+ */
893
+ async getContentTypeDetail(contentTypeUniqueId) {
894
+ try {
895
+ return await this.http.get(`/api/core/content-types/${contentTypeUniqueId}`, {
896
+ headers: this.managingHeaders
897
+ });
898
+ } catch {
899
+ return {};
900
+ }
901
+ }
902
+ /**
903
+ * Adds and publishes new content to CMS.
904
+ */
905
+ async addContent(params, options = {}) {
906
+ const res = await this.http.post(
907
+ `/api/core/contents/${params.contentTypeUniqueId}/add-publish`,
908
+ params.body,
909
+ {
910
+ headers: this.managingHeaders
911
+ }
912
+ );
913
+ return this.formatter.formatGetContentResponse(res, options.normalizer);
914
+ }
915
+ /**
916
+ * Edits and publishes existing content by entityId.
917
+ */
918
+ async editContent(entityId, params, options = {}) {
919
+ const res = await this.http.post(
920
+ `/api/core/contents/${params.contentTypeUniqueId}/${entityId}/edit-publish`,
921
+ params.body,
922
+ {
923
+ headers: this.managingHeaders
924
+ }
925
+ );
926
+ return this.formatter.formatGetContentResponse(res, options.normalizer);
927
+ }
928
+ /**
929
+ * Performs advanced AI timeline search.
930
+ */
931
+ async timelineSearch(query) {
932
+ const params = {};
933
+ if (query?.advance) {
934
+ params.advance = JSON.stringify(query.advance);
935
+ params.newVersion = true;
936
+ }
937
+ if (query?.offset) {
938
+ params.offset = query.offset;
939
+ }
940
+ return this.http.get("/api/core/ai-service/timeline-search/enable", {
941
+ params,
942
+ headers: this.commonHeaders
943
+ });
944
+ }
945
+ };
946
+ var IumsService = class {
947
+ http;
948
+ clientId;
949
+ revalidate;
950
+ constructor(options) {
951
+ this.clientId = options.clientId || "";
952
+ this.revalidate = Number(options.revalidate) || 0;
953
+ this.http = http.createNextHttp({
954
+ baseUrl: options.baseUrl,
955
+ serviceName: "POD-IUMS",
956
+ headers: {
957
+ "Client-Id": this.clientId
958
+ }
959
+ });
960
+ }
961
+ generateIumsDataPayload(method, parameters = [], service = "ExternalFacade") {
962
+ const paramsString = parameters.length > 0 ? "[" + parameters.map((v) => `\\\\\\\\\\\\\\"${v}\\\\\\\\\\\\\\"`) + "]" : null;
963
+ return `{"type":3,"content":"{\\"peerName\\":\\"khatam_eng_hq\\",\\"receivers\\":[],\\"collapseId\\":null,\\"groupId\\":null,\\"index\\":null,\\"messageId\\":\\"8657270951\\",\\"ttl\\":60000,\\"content\\":\\"{\\\\\\"requestHeader\\\\\\":{\\\\\\"trackerId\\\\\\":null,\\\\\\"token\\\\\\":null,\\\\\\"id_token\\\\\\":null,\\\\\\"pod_token\\\\\\":null,\\\\\\"ssoToken\\\\\\":null,\\\\\\"requesterPostId\\\\\\":0,\\\\\\"userIds\\\\\\":null,\\\\\\"ssoIds\\\\\\":null},\\\\\\"messageType\\\\\\":\\\\\\"INVOKE_SERVICE\\\\\\",\\\\\\"processData\\\\\\":[],\\\\\\"content\\\\\\":\\\\\\"{\\\\\\\\\\\\\\"service\\\\\\\\\\\\\\":\\\\\\\\\\\\\\"${service}\\\\\\\\\\\\\\",\\\\\\\\\\\\\\"serviceMethod\\\\\\\\\\\\\\":\\\\\\\\\\\\\\"${method}\\\\\\\\\\\\\\",\\\\\\\\\\\\\\"parameters\\\\\\\\\\\\\\":${paramsString ?? "null"},\\\\\\\\\\\\\\"returnedVarType\\\\\\\\\\\\\\":null,\\\\\\\\\\\\\\"returnedVarJson\\\\\\\\\\\\\\":null,\\\\\\\\\\\\\\"genericType\\\\\\\\\\\\\\":null}\\\\\\",\\\\\\"engineName\\\\\\":null,\\\\\\"peerId\\\\\\":null,\\\\\\"asyncTracker\\\\\\":0,\\\\\\"trackerId\\\\\\":null}\\"}","trackerId":null}`;
964
+ }
965
+ formatIumsResponse(response) {
966
+ const content = response?.content;
967
+ if (!content) return response;
968
+ try {
969
+ let data = JSON.parse(content);
970
+ if (data?.content) {
971
+ data = JSON.parse(data.content);
972
+ }
973
+ if (data?.returnedVarJson) {
974
+ return JSON.parse(data.returnedVarJson);
975
+ }
976
+ return data;
977
+ } catch {
978
+ return response;
979
+ }
980
+ }
981
+ async request(serviceMethod, params = [], options) {
982
+ const dataPayload = this.generateIumsDataPayload(serviceMethod, params);
983
+ const response = await this.http.get("/srv", {
984
+ ...options,
985
+ params: { data: dataPayload },
986
+ next: this.revalidate ? { revalidate: this.revalidate, ...options?.next || {} } : options?.next
987
+ });
988
+ return this.formatIumsResponse(response);
989
+ }
990
+ async getInfOfGraduatedByGraduateDate(startDate = "20240521", endDate = "20250621", options) {
991
+ return this.request(
992
+ "getInfOfGraduatedByGraduateDate3",
993
+ [startDate, endDate],
994
+ options
995
+ );
996
+ }
997
+ async getSessionClassInCurrentDay(options) {
998
+ return this.request(
999
+ "getSessionCalssInCurrentDay",
1000
+ [],
1001
+ options
1002
+ );
1003
+ }
1004
+ async getDetailsOfTermExam(options) {
1005
+ return this.request("getDetailsOfTermExam", [], options);
1006
+ }
1007
+ async getStudentInformationByNumber(studentNumber, options) {
1008
+ return this.request("getStudentInformationByNumber", [Number(studentNumber)], options);
1009
+ }
1010
+ async getStudentInformationByNationalCode(nationalCode, options) {
1011
+ return this.request("getStudentInformationByNationalCode", [Number(nationalCode)], options);
1012
+ }
1013
+ };
1014
+
1015
+ // src/client.ts
1016
+ var PodSdk = class {
1017
+ sso;
1018
+ customPost;
1019
+ podspace;
1020
+ podform;
1021
+ notification;
1022
+ social;
1023
+ cms;
1024
+ iums;
1025
+ constructor(config) {
1026
+ const urls = {
1027
+ accounts: "https://accounts.pod.ir",
1028
+ apiPod: "https://api.pod.ir",
1029
+ cms: "https://cms.pod.ir",
1030
+ podspace: "https://podspace.pod.ir",
1031
+ podform: "https://podform.pod.ir",
1032
+ notification: "https://notification.pod.ir",
1033
+ iums: "https://iums.pod.ir",
1034
+ ...config.urls
1035
+ };
1036
+ const apiToken = config.apiToken || "";
1037
+ const clientId = config.clientId || "";
1038
+ const clientSecret = config.clientSecret || "";
1039
+ const privateKeyPem = config.privateKeyPem || "";
1040
+ const revalidate = config.revalidate;
1041
+ this.sso = new SsoService({
1042
+ baseUrl: urls.accounts,
1043
+ clientId,
1044
+ clientSecret,
1045
+ apiToken,
1046
+ privateKeyPem,
1047
+ websiteUrl: urls.website,
1048
+ revalidate
1049
+ });
1050
+ this.customPost = new CustomPostService({
1051
+ baseUrl: urls.apiPod,
1052
+ apiToken,
1053
+ revalidate
1054
+ });
1055
+ this.podspace = new PodspaceService({
1056
+ baseUrl: urls.podspace,
1057
+ apiToken
1058
+ });
1059
+ this.podform = new PodFormService({
1060
+ baseUrl: urls.podform,
1061
+ apiToken,
1062
+ revalidate
1063
+ });
1064
+ this.notification = new NotificationService({
1065
+ baseUrl: urls.notification,
1066
+ apiToken
1067
+ });
1068
+ this.social = new SocialService({
1069
+ baseUrl: urls.apiPod,
1070
+ apiToken,
1071
+ revalidate
1072
+ });
1073
+ this.cms = new CmsService({
1074
+ baseUrl: urls.cms || urls.apiPod,
1075
+ apiToken,
1076
+ clientId,
1077
+ podspaceUrl: urls.podspace,
1078
+ revalidate
1079
+ });
1080
+ this.iums = new IumsService({
1081
+ baseUrl: urls.iums,
1082
+ clientId,
1083
+ revalidate
1084
+ });
1085
+ }
1086
+ /**
1087
+ * Helper shortcut to instantiate a Generic CRUD repository for any entity type on POD CustomPost.
1088
+ */
1089
+ createCrud(config) {
1090
+ return this.customPost.createCrud(config);
1091
+ }
1092
+ };
1093
+ function createPodSdk(config) {
1094
+ return new PodSdk(config);
1095
+ }
1096
+ var client_default = PodSdk;
1097
+
1098
+ exports.CmsDataFormatter = CmsDataFormatter;
1099
+ exports.CmsService = CmsService;
1100
+ exports.CustomPostCrudService = CustomPostCrudService;
1101
+ exports.CustomPostService = CustomPostService;
1102
+ exports.IumsService = IumsService;
1103
+ exports.NotificationService = NotificationService;
1104
+ exports.PodFormService = PodFormService;
1105
+ exports.PodSdk = PodSdk;
1106
+ exports.PodspaceService = PodspaceService;
1107
+ exports.SocialService = SocialService;
1108
+ exports.SsoService = SsoService;
1109
+ exports.createPodSdk = createPodSdk;
1110
+ exports.default = client_default;
1111
+ exports.encodeBase64 = encodeBase64;
1112
+ exports.generatePodSignatureHeader = generatePodSignatureHeader;
1113
+ //# sourceMappingURL=index.js.map
1114
+ //# sourceMappingURL=index.js.map