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