offcourse 0.0.2 → 1.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (139) hide show
  1. package/README.md +255 -20
  2. package/dist/cli/commands/config.d.ts +13 -0
  3. package/dist/cli/commands/config.d.ts.map +1 -0
  4. package/dist/cli/commands/config.js +66 -0
  5. package/dist/cli/commands/config.js.map +1 -0
  6. package/dist/cli/commands/inspect.d.ts +11 -0
  7. package/dist/cli/commands/inspect.d.ts.map +1 -0
  8. package/dist/cli/commands/inspect.js +365 -0
  9. package/dist/cli/commands/inspect.js.map +1 -0
  10. package/dist/cli/commands/login.d.ts +12 -0
  11. package/dist/cli/commands/login.d.ts.map +1 -0
  12. package/dist/cli/commands/login.js +55 -0
  13. package/dist/cli/commands/login.js.map +1 -0
  14. package/dist/cli/commands/status.d.ts +15 -0
  15. package/dist/cli/commands/status.d.ts.map +1 -0
  16. package/dist/cli/commands/status.js +118 -0
  17. package/dist/cli/commands/status.js.map +1 -0
  18. package/dist/cli/commands/sync.d.ts +15 -0
  19. package/dist/cli/commands/sync.d.ts.map +1 -0
  20. package/dist/cli/commands/sync.js +921 -0
  21. package/dist/cli/commands/sync.js.map +1 -0
  22. package/dist/cli/commands/syncHighLevel.d.ts +23 -0
  23. package/dist/cli/commands/syncHighLevel.d.ts.map +1 -0
  24. package/dist/cli/commands/syncHighLevel.js +479 -0
  25. package/dist/cli/commands/syncHighLevel.js.map +1 -0
  26. package/dist/cli/index.d.ts +3 -0
  27. package/dist/cli/index.d.ts.map +1 -0
  28. package/dist/cli/index.js +106 -0
  29. package/dist/cli/index.js.map +1 -0
  30. package/dist/config/configManager.d.ts +31 -0
  31. package/dist/config/configManager.d.ts.map +1 -0
  32. package/dist/config/configManager.js +68 -0
  33. package/dist/config/configManager.js.map +1 -0
  34. package/dist/config/paths.d.ts +21 -0
  35. package/dist/config/paths.d.ts.map +1 -0
  36. package/dist/config/paths.js +33 -0
  37. package/dist/config/paths.js.map +1 -0
  38. package/dist/config/schema.d.ts +60 -0
  39. package/dist/config/schema.d.ts.map +1 -0
  40. package/dist/config/schema.js +50 -0
  41. package/dist/config/schema.js.map +1 -0
  42. package/dist/downloader/hlsDownloader.d.ts +58 -0
  43. package/dist/downloader/hlsDownloader.d.ts.map +1 -0
  44. package/dist/downloader/hlsDownloader.js +263 -0
  45. package/dist/downloader/hlsDownloader.js.map +1 -0
  46. package/dist/downloader/hlsValidator.d.ts +35 -0
  47. package/dist/downloader/hlsValidator.d.ts.map +1 -0
  48. package/dist/downloader/hlsValidator.js +152 -0
  49. package/dist/downloader/hlsValidator.js.map +1 -0
  50. package/dist/downloader/index.d.ts +29 -0
  51. package/dist/downloader/index.d.ts.map +1 -0
  52. package/dist/downloader/index.js +55 -0
  53. package/dist/downloader/index.js.map +1 -0
  54. package/dist/downloader/loomDownloader.d.ts +56 -0
  55. package/dist/downloader/loomDownloader.d.ts.map +1 -0
  56. package/dist/downloader/loomDownloader.js +562 -0
  57. package/dist/downloader/loomDownloader.js.map +1 -0
  58. package/dist/downloader/queue.d.ts +56 -0
  59. package/dist/downloader/queue.d.ts.map +1 -0
  60. package/dist/downloader/queue.js +88 -0
  61. package/dist/downloader/queue.js.map +1 -0
  62. package/dist/downloader/vimeoDownloader.d.ts +52 -0
  63. package/dist/downloader/vimeoDownloader.d.ts.map +1 -0
  64. package/dist/downloader/vimeoDownloader.js +569 -0
  65. package/dist/downloader/vimeoDownloader.js.map +1 -0
  66. package/dist/scraper/extractor.d.ts +53 -0
  67. package/dist/scraper/extractor.d.ts.map +1 -0
  68. package/dist/scraper/extractor.js +627 -0
  69. package/dist/scraper/extractor.js.map +1 -0
  70. package/dist/scraper/highlevel/extractor.d.ts +89 -0
  71. package/dist/scraper/highlevel/extractor.d.ts.map +1 -0
  72. package/dist/scraper/highlevel/extractor.js +373 -0
  73. package/dist/scraper/highlevel/extractor.js.map +1 -0
  74. package/dist/scraper/highlevel/index.d.ts +3 -0
  75. package/dist/scraper/highlevel/index.d.ts.map +1 -0
  76. package/dist/scraper/highlevel/index.js +3 -0
  77. package/dist/scraper/highlevel/index.js.map +1 -0
  78. package/dist/scraper/highlevel/navigator.d.ts +86 -0
  79. package/dist/scraper/highlevel/navigator.d.ts.map +1 -0
  80. package/dist/scraper/highlevel/navigator.js +505 -0
  81. package/dist/scraper/highlevel/navigator.js.map +1 -0
  82. package/dist/scraper/highlevel/schemas.d.ts +188 -0
  83. package/dist/scraper/highlevel/schemas.d.ts.map +1 -0
  84. package/dist/scraper/highlevel/schemas.js +139 -0
  85. package/dist/scraper/highlevel/schemas.js.map +1 -0
  86. package/dist/scraper/navigator.d.ts +68 -0
  87. package/dist/scraper/navigator.d.ts.map +1 -0
  88. package/dist/scraper/navigator.js +257 -0
  89. package/dist/scraper/navigator.js.map +1 -0
  90. package/dist/scraper/schemas.d.ts +57 -0
  91. package/dist/scraper/schemas.d.ts.map +1 -0
  92. package/dist/scraper/schemas.js +135 -0
  93. package/dist/scraper/schemas.js.map +1 -0
  94. package/dist/scraper/videoInterceptor.d.ts +23 -0
  95. package/dist/scraper/videoInterceptor.d.ts.map +1 -0
  96. package/dist/scraper/videoInterceptor.js +330 -0
  97. package/dist/scraper/videoInterceptor.js.map +1 -0
  98. package/dist/shared/auth.d.ts +58 -0
  99. package/dist/shared/auth.d.ts.map +1 -0
  100. package/dist/shared/auth.js +197 -0
  101. package/dist/shared/auth.js.map +1 -0
  102. package/dist/shared/firebase.d.ts +60 -0
  103. package/dist/shared/firebase.d.ts.map +1 -0
  104. package/dist/shared/firebase.js +102 -0
  105. package/dist/shared/firebase.js.map +1 -0
  106. package/dist/shared/fs.d.ts +31 -0
  107. package/dist/shared/fs.d.ts.map +1 -0
  108. package/dist/shared/fs.js +77 -0
  109. package/dist/shared/fs.js.map +1 -0
  110. package/dist/shared/http.d.ts +15 -0
  111. package/dist/shared/http.d.ts.map +1 -0
  112. package/dist/shared/http.js +31 -0
  113. package/dist/shared/http.js.map +1 -0
  114. package/dist/shared/index.d.ts +7 -0
  115. package/dist/shared/index.d.ts.map +1 -0
  116. package/dist/shared/index.js +7 -0
  117. package/dist/shared/index.js.map +1 -0
  118. package/dist/shared/slug.d.ts +11 -0
  119. package/dist/shared/slug.d.ts.map +1 -0
  120. package/dist/shared/slug.js +25 -0
  121. package/dist/shared/slug.js.map +1 -0
  122. package/dist/shared/url.d.ts +43 -0
  123. package/dist/shared/url.d.ts.map +1 -0
  124. package/dist/shared/url.js +54 -0
  125. package/dist/shared/url.js.map +1 -0
  126. package/dist/state/database.d.ts +246 -0
  127. package/dist/state/database.d.ts.map +1 -0
  128. package/dist/state/database.js +679 -0
  129. package/dist/state/database.js.map +1 -0
  130. package/dist/state/index.d.ts +2 -0
  131. package/dist/state/index.d.ts.map +1 -0
  132. package/dist/state/index.js +2 -0
  133. package/dist/state/index.js.map +1 -0
  134. package/dist/storage/fileSystem.d.ts +56 -0
  135. package/dist/storage/fileSystem.d.ts.map +1 -0
  136. package/dist/storage/fileSystem.js +129 -0
  137. package/dist/storage/fileSystem.js.map +1 -0
  138. package/package.json +71 -11
  139. package/cli.js +0 -45
@@ -0,0 +1,88 @@
1
+ import PQueue from "p-queue";
2
+ /**
3
+ * An async queue for processing items with concurrency control.
4
+ * Uses p-queue internally for battle-tested concurrency handling.
5
+ */
6
+ export class AsyncQueue {
7
+ items = [];
8
+ queue;
9
+ maxRetries;
10
+ onProgress;
11
+ constructor(options) {
12
+ this.queue = new PQueue({ concurrency: options.concurrency });
13
+ this.maxRetries = options.maxRetries;
14
+ this.onProgress = options.onProgress;
15
+ }
16
+ /**
17
+ * Adds an item to the queue.
18
+ */
19
+ add(id, data) {
20
+ this.items.push({
21
+ id,
22
+ data,
23
+ status: "pending",
24
+ retries: 0,
25
+ });
26
+ }
27
+ /**
28
+ * Adds multiple items to the queue.
29
+ */
30
+ addAll(items) {
31
+ for (const item of items) {
32
+ this.add(item.id, item.data);
33
+ }
34
+ }
35
+ /**
36
+ * Processes all items in the queue using the provided handler.
37
+ */
38
+ async process(handler) {
39
+ const errors = [];
40
+ const processItem = async (item) => {
41
+ item.status = "processing";
42
+ // maxRetries=0 means try once, maxRetries=3 means try up to 3 times total
43
+ const maxAttempts = Math.max(1, this.maxRetries);
44
+ for (let attempt = 0; attempt < maxAttempts; attempt++) {
45
+ try {
46
+ await handler(item.data, item.id);
47
+ item.status = "completed";
48
+ this.reportProgress();
49
+ return;
50
+ }
51
+ catch (error) {
52
+ item.retries = attempt + 1;
53
+ if (attempt >= maxAttempts - 1) {
54
+ item.status = "failed";
55
+ item.error = error instanceof Error ? error.message : String(error);
56
+ errors.push({ id: item.id, error: item.error });
57
+ this.reportProgress();
58
+ }
59
+ }
60
+ }
61
+ };
62
+ // Add all items to the p-queue
63
+ await this.queue.addAll(this.items.map((item) => () => processItem(item)));
64
+ const completed = this.items.filter((i) => i.status === "completed").length;
65
+ const failed = this.items.filter((i) => i.status === "failed").length;
66
+ return { completed, failed, errors };
67
+ }
68
+ reportProgress() {
69
+ if (!this.onProgress)
70
+ return;
71
+ const completed = this.items.filter((i) => i.status === "completed").length;
72
+ const total = this.items.length;
73
+ const current = this.items.find((i) => i.status === "processing");
74
+ this.onProgress(completed, total, current?.id);
75
+ }
76
+ /**
77
+ * Gets the current queue status.
78
+ */
79
+ getStatus() {
80
+ return {
81
+ pending: this.items.filter((i) => i.status === "pending").length,
82
+ processing: this.items.filter((i) => i.status === "processing").length,
83
+ completed: this.items.filter((i) => i.status === "completed").length,
84
+ failed: this.items.filter((i) => i.status === "failed").length,
85
+ };
86
+ }
87
+ }
88
+ //# sourceMappingURL=queue.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"queue.js","sourceRoot":"","sources":["../../src/downloader/queue.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,52 @@
1
+ export interface VimeoVideoInfo {
2
+ id: string;
3
+ title: string;
4
+ duration: number;
5
+ width: number;
6
+ height: number;
7
+ hlsUrl: string | null;
8
+ progressiveUrl: string | null;
9
+ }
10
+ export interface VimeoFetchResult {
11
+ success: boolean;
12
+ info?: VimeoVideoInfo;
13
+ error?: string;
14
+ errorCode?: "VIDEO_NOT_FOUND" | "DRM_PROTECTED" | "PRIVATE_VIDEO" | "RATE_LIMITED" | "NETWORK_ERROR" | "PARSE_ERROR";
15
+ details?: string;
16
+ }
17
+ export interface DownloadProgress {
18
+ percent: number;
19
+ downloaded: number;
20
+ total: number;
21
+ }
22
+ export interface VimeoDownloadResult {
23
+ success: boolean;
24
+ error?: string;
25
+ errorCode?: VimeoFetchResult["errorCode"] | "INVALID_URL" | "NO_STREAM" | "DOWNLOAD_FAILED";
26
+ details?: string;
27
+ }
28
+ /**
29
+ * Extracts the Vimeo video ID from various URL formats.
30
+ */
31
+ export declare function extractVimeoId(url: string): string | null;
32
+ /**
33
+ * Fetches video information from Vimeo's player config.
34
+ * @param referer - Optional referer URL (e.g., the Skool page URL) for domain-restricted videos
35
+ */
36
+ export declare function getVimeoVideoInfo(videoId: string, unlistedHash?: string | null, referer?: string): Promise<VimeoFetchResult>;
37
+ /**
38
+ * Fetches Vimeo config from within a Playwright browser context.
39
+ * Uses page.request API which runs at browser level (no CORS restrictions)
40
+ * and includes the browser's cookies/session.
41
+ *
42
+ * @param page - Playwright page (should be on the Skool lesson page)
43
+ * @param videoId - Vimeo video ID
44
+ * @param unlistedHash - Optional hash for unlisted videos
45
+ */
46
+ export declare function getVimeoVideoInfoFromBrowser(page: import("playwright").Page, videoId: string, unlistedHash?: string | null): Promise<VimeoFetchResult>;
47
+ /**
48
+ * Downloads a Vimeo video.
49
+ * Prefers progressive (direct MP4) download, falls back to HLS.
50
+ */
51
+ export declare function downloadVimeoVideo(url: string, outputPath: string, onProgress?: (progress: DownloadProgress) => void): Promise<VimeoDownloadResult>;
52
+ //# sourceMappingURL=vimeoDownloader.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"vimeoDownloader.d.ts","sourceRoot":"","sources":["../../src/downloader/vimeoDownloader.ts"],"names":[],"mappings":"AAKA,MAAM,WAAW,cAAc;IAC7B,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,cAAc,EAAE,MAAM,GAAG,IAAI,CAAC;CAC/B;AAED,MAAM,WAAW,gBAAgB;IAC/B,OAAO,EAAE,OAAO,CAAC;IACjB,IAAI,CAAC,EAAE,cAAc,CAAC;IACtB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,SAAS,CAAC,EACN,iBAAiB,GACjB,eAAe,GACf,eAAe,GACf,cAAc,GACd,eAAe,GACf,aAAa,CAAC;IAClB,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,WAAW,gBAAgB;IAC/B,OAAO,EAAE,MAAM,CAAC;IAChB,UAAU,EAAE,MAAM,CAAC;IACnB,KAAK,EAAE,MAAM,CAAC;CACf;AAED,MAAM,WAAW,mBAAmB;IAClC,OAAO,EAAE,OAAO,CAAC;IACjB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,SAAS,CAAC,EAAE,gBAAgB,CAAC,WAAW,CAAC,GAAG,aAAa,GAAG,WAAW,GAAG,iBAAiB,CAAC;IAC5F,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED;;GAEG;AACH,wBAAgB,cAAc,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAqBzD;AAyBD;;;GAGG;AACH,wBAAsB,iBAAiB,CACrC,OAAO,EAAE,MAAM,EACf,YAAY,CAAC,EAAE,MAAM,GAAG,IAAI,EAC5B,OAAO,CAAC,EAAE,MAAM,GACf,OAAO,CAAC,gBAAgB,CAAC,CAgK3B;AAED;;;;;;;;GAQG;AACH,wBAAsB,4BAA4B,CAChD,IAAI,EAAE,OAAO,YAAY,EAAE,IAAI,EAC/B,OAAO,EAAE,MAAM,EACf,YAAY,CAAC,EAAE,MAAM,GAAG,IAAI,GAC3B,OAAO,CAAC,gBAAgB,CAAC,CAiH3B;AAED;;;GAGG;AACH,wBAAsB,kBAAkB,CACtC,GAAG,EAAE,MAAM,EACX,UAAU,EAAE,MAAM,EAClB,UAAU,CAAC,EAAE,CAAC,QAAQ,EAAE,gBAAgB,KAAK,IAAI,GAChD,OAAO,CAAC,mBAAmB,CAAC,CAsE9B"}