@ewanc26/atproto 0.2.8 → 0.2.10

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ewanc26/atproto",
3
- "version": "0.2.8",
3
+ "version": "0.2.10",
4
4
  "description": "AT Protocol service layer extracted from ewancroft.uk",
5
5
  "author": "Ewan Croft",
6
6
  "license": "AGPL-3.0-only",
@@ -35,16 +35,16 @@
35
35
  },
36
36
  "main": "./dist/index.js",
37
37
  "types": "./dist/index.d.ts",
38
+ "scripts": {
39
+ "build": "tsc --project tsconfig.json",
40
+ "dev": "tsc --project tsconfig.json --watch",
41
+ "check": "tsc --noEmit"
42
+ },
38
43
  "peerDependencies": {
39
44
  "@atproto/api": ">=0.13.0"
40
45
  },
41
46
  "devDependencies": {
42
47
  "@atproto/api": "^0.19.3",
43
48
  "typescript": "^5.9.3"
44
- },
45
- "scripts": {
46
- "build": "tsc --project tsconfig.json",
47
- "dev": "tsc --project tsconfig.json --watch",
48
- "check": "tsc --noEmit"
49
49
  }
50
- }
50
+ }
package/src/fetch.ts CHANGED
@@ -12,7 +12,19 @@ import type {
12
12
  TangledReposData,
13
13
  PopfeedReview,
14
14
  PopfeedCreativeWorkType,
15
- PopfeedMainCreditRole
15
+ PopfeedMainCreditRole,
16
+ SifaProfileData,
17
+ SifaSkill,
18
+ SifaProject,
19
+ SifaLanguage,
20
+ SifaCertification,
21
+ SifaExternalAccount,
22
+ SifaPosition,
23
+ SifaEducation,
24
+ SifaVolunteering,
25
+ SifaHonor,
26
+ SifaCourse,
27
+ SifaPublication
16
28
  } from './types.js';
17
29
 
18
30
  export async function fetchProfile(did: string, fetchFn?: typeof fetch): Promise<ProfileData> {
@@ -363,6 +375,295 @@ export async function fetchRecentPopfeedReviews(
363
375
  }
364
376
  }
365
377
 
378
+ export async function fetchSifaPositions(
379
+ did: string,
380
+ fetchFn?: typeof fetch
381
+ ): Promise<SifaPosition[]> {
382
+ const cacheKey = `sifa:positions:${did}`;
383
+ const cached = cache.get<SifaPosition[]>(cacheKey);
384
+ if (cached) return cached;
385
+
386
+ try {
387
+ const records = await withFallback(
388
+ did,
389
+ async (agent) => {
390
+ const response = await agent.com.atproto.repo.listRecords({
391
+ repo: did,
392
+ collection: 'id.sifa.profile.position',
393
+ limit: 100
394
+ });
395
+ return response.data.records;
396
+ },
397
+ true,
398
+ fetchFn
399
+ );
400
+
401
+ const data: SifaPosition[] = records.map((record) => {
402
+ const value = record.value as any;
403
+ return {
404
+ company: value.company,
405
+ companyDid: value.companyDid,
406
+ title: value.title,
407
+ description: value.description,
408
+ employmentType: value.employmentType,
409
+ workplaceType: value.workplaceType,
410
+ location: value.location,
411
+ startedAt: value.startedAt,
412
+ endedAt: value.endedAt,
413
+ skills: value.skills,
414
+ isPrimary: value.isPrimary,
415
+ uri: record.uri
416
+ };
417
+ });
418
+
419
+ data.sort((a, b) => {
420
+ if (!a.startedAt) return 1;
421
+ if (!b.startedAt) return -1;
422
+ return new Date(b.startedAt).getTime() - new Date(a.startedAt).getTime();
423
+ });
424
+
425
+ cache.set(cacheKey, data);
426
+ return data;
427
+ } catch {
428
+ return [];
429
+ }
430
+ }
431
+
432
+ export async function fetchSifaEducation(
433
+ did: string,
434
+ fetchFn?: typeof fetch
435
+ ): Promise<SifaEducation[]> {
436
+ const cacheKey = `sifa:education:${did}`;
437
+ const cached = cache.get<SifaEducation[]>(cacheKey);
438
+ if (cached) return cached;
439
+
440
+ try {
441
+ const records = await withFallback(
442
+ did,
443
+ async (agent) => {
444
+ const response = await agent.com.atproto.repo.listRecords({
445
+ repo: did,
446
+ collection: 'id.sifa.profile.education',
447
+ limit: 100
448
+ });
449
+ return response.data.records;
450
+ },
451
+ true,
452
+ fetchFn
453
+ );
454
+
455
+ const data: SifaEducation[] = records.map((record) => {
456
+ const value = record.value as any;
457
+ return {
458
+ institution: value.institution,
459
+ institutionDid: value.institutionDid,
460
+ degree: value.degree,
461
+ fieldOfStudy: value.fieldOfStudy,
462
+ grade: value.grade,
463
+ activities: value.activities,
464
+ description: value.description,
465
+ location: value.location,
466
+ startedAt: value.startedAt,
467
+ endedAt: value.endedAt,
468
+ uri: record.uri
469
+ };
470
+ });
471
+
472
+ data.sort((a, b) => {
473
+ const aEnd = a.endedAt ? new Date(a.endedAt).getTime() : Date.now();
474
+ const bEnd = b.endedAt ? new Date(b.endedAt).getTime() : Date.now();
475
+ return bEnd - aEnd;
476
+ });
477
+
478
+ cache.set(cacheKey, data);
479
+ return data;
480
+ } catch {
481
+ return [];
482
+ }
483
+ }
484
+
485
+ export async function fetchSifaVolunteering(
486
+ did: string,
487
+ fetchFn?: typeof fetch
488
+ ): Promise<SifaVolunteering[]> {
489
+ const cacheKey = `sifa:volunteering:${did}`;
490
+ const cached = cache.get<SifaVolunteering[]>(cacheKey);
491
+ if (cached) return cached;
492
+
493
+ try {
494
+ const records = await withFallback(
495
+ did,
496
+ async (agent) => {
497
+ const response = await agent.com.atproto.repo.listRecords({
498
+ repo: did,
499
+ collection: 'id.sifa.profile.volunteering',
500
+ limit: 100
501
+ });
502
+ return response.data.records;
503
+ },
504
+ true,
505
+ fetchFn
506
+ );
507
+
508
+ const data: SifaVolunteering[] = records.map((record) => {
509
+ const value = record.value as any;
510
+ return {
511
+ organization: value.organization,
512
+ organizationDid: value.organizationDid,
513
+ role: value.role,
514
+ cause: value.cause,
515
+ description: value.description,
516
+ startedAt: value.startedAt,
517
+ endedAt: value.endedAt,
518
+ uri: record.uri
519
+ };
520
+ });
521
+
522
+ cache.set(cacheKey, data);
523
+ return data;
524
+ } catch {
525
+ return [];
526
+ }
527
+ }
528
+
529
+ export async function fetchSifaHonors(
530
+ did: string,
531
+ fetchFn?: typeof fetch
532
+ ): Promise<SifaHonor[]> {
533
+ const cacheKey = `sifa:honors:${did}`;
534
+ const cached = cache.get<SifaHonor[]>(cacheKey);
535
+ if (cached) return cached;
536
+
537
+ try {
538
+ const records = await withFallback(
539
+ did,
540
+ async (agent) => {
541
+ const response = await agent.com.atproto.repo.listRecords({
542
+ repo: did,
543
+ collection: 'id.sifa.profile.honor',
544
+ limit: 100
545
+ });
546
+ return response.data.records;
547
+ },
548
+ true,
549
+ fetchFn
550
+ );
551
+
552
+ const data: SifaHonor[] = records.map((record) => {
553
+ const value = record.value as any;
554
+ return {
555
+ title: value.title,
556
+ issuer: value.issuer,
557
+ issuerDid: value.issuerDid,
558
+ description: value.description,
559
+ awardedAt: value.awardedAt,
560
+ uri: record.uri
561
+ };
562
+ });
563
+
564
+ data.sort((a, b) => {
565
+ if (!a.awardedAt) return 1;
566
+ if (!b.awardedAt) return -1;
567
+ return new Date(b.awardedAt).getTime() - new Date(a.awardedAt).getTime();
568
+ });
569
+
570
+ cache.set(cacheKey, data);
571
+ return data;
572
+ } catch {
573
+ return [];
574
+ }
575
+ }
576
+
577
+ export async function fetchSifaCourses(
578
+ did: string,
579
+ fetchFn?: typeof fetch
580
+ ): Promise<SifaCourse[]> {
581
+ const cacheKey = `sifa:courses:${did}`;
582
+ const cached = cache.get<SifaCourse[]>(cacheKey);
583
+ if (cached) return cached;
584
+
585
+ try {
586
+ const records = await withFallback(
587
+ did,
588
+ async (agent) => {
589
+ const response = await agent.com.atproto.repo.listRecords({
590
+ repo: did,
591
+ collection: 'id.sifa.profile.course',
592
+ limit: 100
593
+ });
594
+ return response.data.records;
595
+ },
596
+ true,
597
+ fetchFn
598
+ );
599
+
600
+ const data: SifaCourse[] = records.map((record) => {
601
+ const value = record.value as any;
602
+ return {
603
+ name: value.name,
604
+ number: value.number,
605
+ institution: value.institution,
606
+ education: value.education,
607
+ uri: record.uri
608
+ };
609
+ });
610
+
611
+ cache.set(cacheKey, data);
612
+ return data;
613
+ } catch {
614
+ return [];
615
+ }
616
+ }
617
+
618
+ export async function fetchSifaPublications(
619
+ did: string,
620
+ fetchFn?: typeof fetch
621
+ ): Promise<SifaPublication[]> {
622
+ const cacheKey = `sifa:publications:${did}`;
623
+ const cached = cache.get<SifaPublication[]>(cacheKey);
624
+ if (cached) return cached;
625
+
626
+ try {
627
+ const records = await withFallback(
628
+ did,
629
+ async (agent) => {
630
+ const response = await agent.com.atproto.repo.listRecords({
631
+ repo: did,
632
+ collection: 'id.sifa.profile.publication',
633
+ limit: 100
634
+ });
635
+ return response.data.records;
636
+ },
637
+ true,
638
+ fetchFn
639
+ );
640
+
641
+ const data: SifaPublication[] = records.map((record) => {
642
+ const value = record.value as any;
643
+ return {
644
+ title: value.title,
645
+ publisher: value.publisher,
646
+ url: value.url,
647
+ description: value.description,
648
+ authors: value.authors,
649
+ publishedAt: value.publishedAt,
650
+ uri: record.uri
651
+ };
652
+ });
653
+
654
+ data.sort((a, b) => {
655
+ if (!a.publishedAt) return 1;
656
+ if (!b.publishedAt) return -1;
657
+ return new Date(b.publishedAt).getTime() - new Date(a.publishedAt).getTime();
658
+ });
659
+
660
+ cache.set(cacheKey, data);
661
+ return data;
662
+ } catch {
663
+ return [];
664
+ }
665
+ }
666
+
366
667
  export async function fetchTangledRepos(
367
668
  did: string,
368
669
  fetchFn?: typeof fetch
@@ -410,3 +711,260 @@ export async function fetchTangledRepos(
410
711
  return null;
411
712
  }
412
713
  }
714
+
715
+ // Sifa Professional Profile fetch functions
716
+
717
+ export async function fetchSifaProfile(
718
+ did: string,
719
+ fetchFn?: typeof fetch
720
+ ): Promise<SifaProfileData | null> {
721
+ const cacheKey = `sifa:profile:${did}`;
722
+ const cached = cache.get<SifaProfileData>(cacheKey);
723
+ if (cached) return cached;
724
+
725
+ try {
726
+ const result = await withFallback(
727
+ did,
728
+ async (agent) => {
729
+ const response = await agent.com.atproto.repo.getRecord({
730
+ repo: did,
731
+ collection: 'id.sifa.profile.self',
732
+ rkey: 'self'
733
+ });
734
+ return response.data;
735
+ },
736
+ true,
737
+ fetchFn
738
+ );
739
+
740
+ if (!result?.value) return null;
741
+ const value = result.value as any;
742
+ const data: SifaProfileData = {
743
+ headline: value.headline,
744
+ about: value.about,
745
+ industry: value.industry,
746
+ location: value.location,
747
+ openTo: value.openTo || [],
748
+ preferredWorkplace: value.preferredWorkplace || [],
749
+ langs: value.langs || [],
750
+ createdAt: value.createdAt
751
+ };
752
+ cache.set(cacheKey, data);
753
+ return data;
754
+ } catch {
755
+ return null;
756
+ }
757
+ }
758
+
759
+ export async function fetchSifaSkills(
760
+ did: string,
761
+ fetchFn?: typeof fetch
762
+ ): Promise<SifaSkill[]> {
763
+ const cacheKey = `sifa:skills:${did}`;
764
+ const cached = cache.get<SifaSkill[]>(cacheKey);
765
+ if (cached) return cached;
766
+
767
+ try {
768
+ const records = await withFallback(
769
+ did,
770
+ async (agent) => {
771
+ const response = await agent.com.atproto.repo.listRecords({
772
+ repo: did,
773
+ collection: 'id.sifa.profile.skill',
774
+ limit: 100
775
+ });
776
+ return response.data.records;
777
+ },
778
+ true,
779
+ fetchFn
780
+ );
781
+
782
+ const data: SifaSkill[] = records.map((record) => {
783
+ const value = record.value as any;
784
+ return {
785
+ name: value.name,
786
+ category: value.category,
787
+ uri: record.uri
788
+ };
789
+ });
790
+
791
+ cache.set(cacheKey, data);
792
+ return data;
793
+ } catch {
794
+ return [];
795
+ }
796
+ }
797
+
798
+ export async function fetchSifaProjects(
799
+ did: string,
800
+ fetchFn?: typeof fetch
801
+ ): Promise<SifaProject[]> {
802
+ const cacheKey = `sifa:projects:${did}`;
803
+ const cached = cache.get<SifaProject[]>(cacheKey);
804
+ if (cached) return cached;
805
+
806
+ try {
807
+ const records = await withFallback(
808
+ did,
809
+ async (agent) => {
810
+ const response = await agent.com.atproto.repo.listRecords({
811
+ repo: did,
812
+ collection: 'id.sifa.profile.project',
813
+ limit: 100
814
+ });
815
+ return response.data.records;
816
+ },
817
+ true,
818
+ fetchFn
819
+ );
820
+
821
+ const data: SifaProject[] = records.map((record) => {
822
+ const value = record.value as any;
823
+ return {
824
+ name: value.name,
825
+ description: value.description,
826
+ url: value.url,
827
+ startedAt: value.startedAt,
828
+ uri: record.uri
829
+ };
830
+ });
831
+
832
+ data.sort((a, b) => {
833
+ if (!a.startedAt) return 1;
834
+ if (!b.startedAt) return -1;
835
+ return new Date(b.startedAt).getTime() - new Date(a.startedAt).getTime();
836
+ });
837
+
838
+ cache.set(cacheKey, data);
839
+ return data;
840
+ } catch {
841
+ return [];
842
+ }
843
+ }
844
+
845
+ export async function fetchSifaLanguages(
846
+ did: string,
847
+ fetchFn?: typeof fetch
848
+ ): Promise<SifaLanguage[]> {
849
+ const cacheKey = `sifa:languages:${did}`;
850
+ const cached = cache.get<SifaLanguage[]>(cacheKey);
851
+ if (cached) return cached;
852
+
853
+ try {
854
+ const records = await withFallback(
855
+ did,
856
+ async (agent) => {
857
+ const response = await agent.com.atproto.repo.listRecords({
858
+ repo: did,
859
+ collection: 'id.sifa.profile.language',
860
+ limit: 100
861
+ });
862
+ return response.data.records;
863
+ },
864
+ true,
865
+ fetchFn
866
+ );
867
+
868
+ const data: SifaLanguage[] = records.map((record) => {
869
+ const value = record.value as any;
870
+ return {
871
+ name: value.name,
872
+ proficiency: value.proficiency,
873
+ uri: record.uri
874
+ };
875
+ });
876
+
877
+ cache.set(cacheKey, data);
878
+ return data;
879
+ } catch {
880
+ return [];
881
+ }
882
+ }
883
+
884
+ export async function fetchSifaCertifications(
885
+ did: string,
886
+ fetchFn?: typeof fetch
887
+ ): Promise<SifaCertification[]> {
888
+ const cacheKey = `sifa:certifications:${did}`;
889
+ const cached = cache.get<SifaCertification[]>(cacheKey);
890
+ if (cached) return cached;
891
+
892
+ try {
893
+ const records = await withFallback(
894
+ did,
895
+ async (agent) => {
896
+ const response = await agent.com.atproto.repo.listRecords({
897
+ repo: did,
898
+ collection: 'id.sifa.profile.certification',
899
+ limit: 100
900
+ });
901
+ return response.data.records;
902
+ },
903
+ true,
904
+ fetchFn
905
+ );
906
+
907
+ const data: SifaCertification[] = records.map((record) => {
908
+ const value = record.value as any;
909
+ return {
910
+ name: value.name,
911
+ authority: value.authority,
912
+ issuedAt: value.issuedAt,
913
+ uri: record.uri
914
+ };
915
+ });
916
+
917
+ data.sort((a, b) => {
918
+ if (!a.issuedAt) return 1;
919
+ if (!b.issuedAt) return -1;
920
+ return new Date(b.issuedAt).getTime() - new Date(a.issuedAt).getTime();
921
+ });
922
+
923
+ cache.set(cacheKey, data);
924
+ return data;
925
+ } catch {
926
+ return [];
927
+ }
928
+ }
929
+
930
+ export async function fetchSifaExternalAccounts(
931
+ did: string,
932
+ fetchFn?: typeof fetch
933
+ ): Promise<SifaExternalAccount[]> {
934
+ const cacheKey = `sifa:externalAccounts:${did}`;
935
+ const cached = cache.get<SifaExternalAccount[]>(cacheKey);
936
+ if (cached) return cached;
937
+
938
+ try {
939
+ const records = await withFallback(
940
+ did,
941
+ async (agent) => {
942
+ const response = await agent.com.atproto.repo.listRecords({
943
+ repo: did,
944
+ collection: 'id.sifa.profile.externalAccount',
945
+ limit: 100
946
+ });
947
+ return response.data.records;
948
+ },
949
+ true,
950
+ fetchFn
951
+ );
952
+
953
+ const data: SifaExternalAccount[] = records.map((record) => {
954
+ const value = record.value as any;
955
+ return {
956
+ platform: value.platform,
957
+ url: value.url,
958
+ label: value.label,
959
+ feedUrl: value.feedUrl,
960
+ isPrimary: value.isPrimary,
961
+ uri: record.uri
962
+ };
963
+ });
964
+
965
+ cache.set(cacheKey, data);
966
+ return data;
967
+ } catch {
968
+ return [];
969
+ }
970
+ }
package/src/index.ts CHANGED
@@ -37,7 +37,21 @@ export type {
37
37
  StandardSiteDocument,
38
38
  StandardSiteDocumentsData,
39
39
  StandardSiteBasicTheme,
40
- StandardSiteThemeColor
40
+ StandardSiteThemeColor,
41
+ SifaProfileData,
42
+ SifaSkill,
43
+ SifaProject,
44
+ SifaLanguage,
45
+ SifaCertification,
46
+ SifaExternalAccount,
47
+ SifaLocation,
48
+ SifaPosition,
49
+ SifaEducation,
50
+ SifaVolunteering,
51
+ SifaHonor,
52
+ SifaCourse,
53
+ SifaPublication,
54
+ SifaPublicationAuthor
41
55
  } from './types.js';
42
56
 
43
57
  export {
@@ -47,7 +61,19 @@ export {
47
61
  fetchMusicStatus,
48
62
  fetchKibunStatus,
49
63
  fetchTangledRepos,
50
- fetchRecentPopfeedReviews
64
+ fetchRecentPopfeedReviews,
65
+ fetchSifaProfile,
66
+ fetchSifaSkills,
67
+ fetchSifaProjects,
68
+ fetchSifaLanguages,
69
+ fetchSifaCertifications,
70
+ fetchSifaExternalAccounts,
71
+ fetchSifaPositions,
72
+ fetchSifaEducation,
73
+ fetchSifaVolunteering,
74
+ fetchSifaHonors,
75
+ fetchSifaCourses,
76
+ fetchSifaPublications
51
77
  } from './fetch.js';
52
78
 
53
79
  export {