@zucker-framework/ext-kit 1.0.2 → 1.0.6

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.d.mts CHANGED
@@ -1,26 +1,109 @@
1
1
  type Settings = Record<string, unknown>;
2
+ /** Structural browser ports keep public declarations independent of @types/chrome. */
3
+ interface BrowserTab {
4
+ id?: number;
5
+ url?: string;
6
+ pendingUrl?: string;
7
+ windowId: number;
8
+ title?: string;
9
+ width?: number;
10
+ height?: number;
11
+ active: boolean;
12
+ }
13
+ interface DownloadRecord {
14
+ id: number;
15
+ url: string;
16
+ finalUrl?: string;
17
+ filename: string;
18
+ state: 'in_progress' | 'interrupted' | 'complete';
19
+ error?: string;
20
+ byExtensionId?: string;
21
+ }
2
22
  interface CaptureContext {
3
- /** batch = 后台批量新开 tab;quick = 用户当前浏览的 tab(不得改视口、需还原页面状态) */
4
23
  mode: 'batch' | 'quick';
5
24
  tabId: number;
6
25
  url: string;
7
26
  options: Settings;
8
- /** chrome.debugger sendCommand(已 attach) */
27
+ /** Capture commands reject on cancellation. */
9
28
  send(method: string, params?: Record<string, unknown>): Promise<Record<string, unknown>>;
29
+ /** Restoration MUST remain usable after Stop/abort. */
30
+ cleanup(method: string, params?: Record<string, unknown>): Promise<Record<string, unknown>>;
10
31
  }
11
32
  interface CaptureOutput {
12
33
  base64: string;
13
34
  mime: string;
14
- /** 文件扩展名,不含点:"png" | "jpg" | "pdf" … */
15
35
  extension: string;
16
- /** 非致命告警(如超高截断),展示在结果列表 */
17
36
  warning?: string;
18
37
  }
38
+ interface Entitlement {
39
+ expiresAt: string;
40
+ [key: string]: unknown;
41
+ }
42
+ interface LicenseReply {
43
+ accepted: boolean;
44
+ /** Authoritative server rejection, NOT a proxy/network error. */
45
+ denied?: boolean;
46
+ entitlement?: unknown;
47
+ token?: string;
48
+ deactivated?: boolean;
49
+ }
19
50
  interface LicensingConfig {
20
- apiBase: string;
21
- purchaseUrl: string;
51
+ purchaseUrl?: string;
52
+ cacheTtlMs: number;
53
+ offlineGraceMs: number;
54
+ requestTimeoutMs: number;
55
+ retryDelayMs: number;
56
+ /** Consumer owns transport, endpoints, code normalization and envelope validation. */
57
+ request(operation: 'activate' | 'me' | 'deactivate', input: {
58
+ code?: string;
59
+ deviceId?: string;
60
+ brand?: string;
61
+ token?: string;
62
+ }, signal: AbortSignal): Promise<LicenseReply>;
63
+ /** Validate the consumer's actual grant/plan. The kit additionally checks expiry. */
64
+ normalizeEntitlement(value: unknown): Entitlement | null;
65
+ }
66
+ interface LicenseStatus {
67
+ state: 'free' | 'checking' | 'pro' | 'invalid' | 'unavailable';
68
+ entitlement?: Entitlement;
69
+ message?: string;
70
+ refreshing?: boolean;
71
+ }
72
+ interface LicenseStatusOptions {
73
+ cachedOnly?: boolean;
74
+ force?: boolean;
75
+ }
76
+ interface Licensing {
77
+ activate(code: string): Promise<Entitlement>;
78
+ getEntitlement(options?: LicenseStatusOptions): Promise<Entitlement | null>;
79
+ getStatus(options?: LicenseStatusOptions): Promise<LicenseStatus>;
80
+ /** Releases the device remotely before deleting local identity. */
81
+ deactivate(): Promise<void>;
82
+ purchaseUrl?: string;
83
+ }
84
+ interface DownloadOptions {
85
+ deadlineMs?: number;
86
+ /** Must exceed deadlineMs; offscreen reclaims URLs if the worker disappears. */
87
+ blobLeaseMs?: number;
88
+ pollMs?: number;
89
+ offscreenUrl?: string;
90
+ }
91
+ interface DownloadCheckpoint {
92
+ downloadId?: number;
93
+ downloadUrl?: string;
94
+ }
95
+ interface Downloader {
96
+ downloadViaBlob(base64: string, mime: string, filename: string, options?: {
97
+ signal?: AbortSignal;
98
+ onPrepared?(url: string): Promise<void>;
99
+ onCreated?(id: number): Promise<void>;
100
+ }): Promise<number>;
101
+ recover(item: DownloadCheckpoint, signal?: AbortSignal): Promise<DownloadRecord>;
102
+ }
103
+ interface ScrollCapture {
104
+ prepare(ctx: CaptureContext, waitForContent?: () => Promise<void>): Promise<void>;
105
+ restore(ctx: CaptureContext): Promise<void>;
22
106
  }
23
- /** 措辞(capture/convert 等动词差异);不配则用 capture 系默认值 */
24
107
  interface ExtTexts {
25
108
  alreadyRunning: string;
26
109
  cannotQuick: string;
@@ -28,20 +111,30 @@ interface ExtTexts {
28
111
  quickFolder: string;
29
112
  }
30
113
  interface ExtKitConfig {
31
- /** 消费项目提供的存储 key 命名空间;已发布产品应保持原值,以兼容既有安装 */
114
+ /** Keep existing storage namespace and message prefix on upgrades. */
32
115
  product: string;
33
- /** 品牌名:下载文件夹前缀、设备名 */
34
116
  brand: string;
35
- /** 消费项目提供的消息类型前缀,用于构造 START 等消息类型 */
36
117
  messagePrefix: string;
37
- freeDailyLimit?: number;
118
+ freeDailyLimit: number;
38
119
  badgeColor: string;
39
120
  defaultSettings: Settings;
40
121
  licensing: LicensingConfig;
122
+ downloads?: DownloadOptions;
123
+ sameHostGapMs?: number;
41
124
  texts?: Partial<ExtTexts>;
42
- /** 仅批量模式、autoScroll 之前调用(如固定视口宽度);quick 模式不调用(不能动用户的 tab) */
125
+ /** PDF/image settings validation and migration belong to the consumer. */
126
+ normalizeSettings?(defaults: Settings, input?: unknown): Settings;
127
+ migrateSettings?(saved: unknown): Settings;
128
+ captureScope?(options: Settings): 'full' | 'viewport';
129
+ scrollCapture?: ScrollCapture;
43
130
  beforeScroll?(ctx: CaptureContext): Promise<void>;
44
- /** 核心业务:页面已加载、已过验证、已滚动揭示,产出要下载的数据 */
131
+ beforeQuick?(ctx: CaptureContext, tab: BrowserTab): Promise<void>;
132
+ afterQuick?(ctx: CaptureContext): Promise<void>;
133
+ captureQuick?(input: {
134
+ tab: BrowserTab;
135
+ options: Settings;
136
+ signal: AbortSignal;
137
+ }): Promise<CaptureOutput | null | undefined>;
45
138
  capture(ctx: CaptureContext): Promise<CaptureOutput>;
46
139
  }
47
140
  interface PopupTexts {
@@ -52,16 +145,14 @@ interface PopupTexts {
52
145
  }
53
146
  interface PopupConfig {
54
147
  messagePrefix: string;
55
- /** 消费项目提供的 URL 队列存储 key;已发布产品应保持原值 */
56
148
  queueKey: string;
57
- /** 快速处理当前页的消息类型后缀:CAPTURE_CURRENT / CONVERT_CURRENT */
149
+ settingsKey?: string;
58
150
  quickType: string;
59
- /** 快速按钮的元素 id,默认 "captureCurrent",可由消费项目覆盖 */
60
151
  quickButtonId?: string;
61
152
  texts: PopupTexts;
62
- collectSettings(): Settings;
63
- collectQuickSettings(): Settings;
64
- /** 快速处理成功后的状态栏文案 */
153
+ onSettingsLoaded?(): void;
154
+ collectSettings(): Settings | Promise<Settings>;
155
+ collectQuickSettings(): Settings | Promise<Settings>;
65
156
  quickResult(result: {
66
157
  fileName: string;
67
158
  warning?: string;
@@ -71,19 +162,29 @@ interface PopupConfig {
71
162
  declare function initExtension(config: ExtKitConfig): void;
72
163
 
73
164
  declare function initPopup(config: PopupConfig): void;
165
+ declare function collectSameOriginLinks(options?: { phase?: 'links' | 'sitemap' | 'cancel'; id?: string }): Promise<{ urls: string[]; sitemapCount?: number; incomplete?: boolean; cancelled?: boolean }>;
74
166
 
75
- interface Entitlement {
76
- plan: string;
77
- expiresAt: string;
78
- }
79
- interface Licensing {
80
- activate(code: string): Promise<unknown>;
81
- getEntitlement(): Promise<Entitlement | null>;
82
- isPro(): Promise<boolean>;
83
- clear(): Promise<void>;
84
- purchaseUrl: string;
167
+ declare function createDownloader(justification: string, options?: DownloadOptions): Downloader;
168
+
169
+ declare function prepare(ctx: CaptureContext, waitForContent?: () => Promise<void>): Promise<void>;
170
+ declare function restore(ctx: CaptureContext): Promise<void>;
171
+
172
+ declare const scrollCapture_d_prepare: typeof prepare;
173
+ declare const scrollCapture_d_restore: typeof restore;
174
+ declare namespace scrollCapture_d {
175
+ export { scrollCapture_d_prepare as prepare, scrollCapture_d_restore as restore };
85
176
  }
86
- declare function createLicensing(product: string, brand: string, config: LicensingConfig): Licensing;
177
+
178
+ declare const CAPTURE_LIMITS: Readonly<{ maxEdgeDevicePx: number; maxDevicePixels: number }>;
179
+ declare function captureFits(width: number, height: number, dpr: number): boolean;
180
+ declare function assertCaptureFits(width: number, height: number, dpr: number, message: string): void;
181
+ declare function captureBudget(dpr: number): { maxEdge: number; maxArea: number };
182
+ declare function readDevicePixelRatio(ctx: CaptureContext): Promise<number>;
183
+
184
+ declare function hidePageCaptureDecorations(): void;
185
+ declare function showPageCaptureDecorations(): void;
186
+
187
+ declare function createLicensing(namespace: string, brand: string, config: LicensingConfig): Licensing;
87
188
 
88
189
  declare function sanitize(value: string): string;
89
190
  declare function hostOf(url: string): string;
@@ -99,4 +200,4 @@ declare function buildBatchFileName(folder: string, item: {
99
200
  }, extension: string): string;
100
201
  declare function buildQuickFileName(brand: string, quickFolder: string, pageUrl: string, extension: string): string;
101
202
 
102
- export { type CaptureContext, type CaptureOutput, type Entitlement, type ExtKitConfig, type ExtTexts, type Licensing, type LicensingConfig, type PopupConfig, type PopupTexts, type Settings, buildBatchFileName, buildQuickFileName, createLicensing, fileStamp, folderNameFor, hostOf, initExtension, initPopup, normalizeUrls, sanitize, sessionStamp, todayString, urlBaseName };
203
+ export { type BrowserTab, CAPTURE_LIMITS, type CaptureContext, type CaptureOutput, type DownloadCheckpoint, type DownloadOptions, type DownloadRecord, type Downloader, type Entitlement, type ExtKitConfig, type ExtTexts, type LicenseReply, type LicenseStatus, type LicenseStatusOptions, type Licensing, type LicensingConfig, type PopupConfig, type PopupTexts, type ScrollCapture, type Settings, assertCaptureFits, buildBatchFileName, buildQuickFileName, captureBudget, captureFits, collectSameOriginLinks, createDownloader, createLicensing, fileStamp, folderNameFor, hidePageCaptureDecorations, hostOf, initExtension, initPopup, normalizeUrls, readDevicePixelRatio, sanitize, scrollCapture_d as scrollCapture, sessionStamp, showPageCaptureDecorations, todayString, urlBaseName };
package/dist/index.d.ts CHANGED
@@ -1,26 +1,109 @@
1
1
  type Settings = Record<string, unknown>;
2
+ /** Structural browser ports keep public declarations independent of @types/chrome. */
3
+ interface BrowserTab {
4
+ id?: number;
5
+ url?: string;
6
+ pendingUrl?: string;
7
+ windowId: number;
8
+ title?: string;
9
+ width?: number;
10
+ height?: number;
11
+ active: boolean;
12
+ }
13
+ interface DownloadRecord {
14
+ id: number;
15
+ url: string;
16
+ finalUrl?: string;
17
+ filename: string;
18
+ state: 'in_progress' | 'interrupted' | 'complete';
19
+ error?: string;
20
+ byExtensionId?: string;
21
+ }
2
22
  interface CaptureContext {
3
- /** batch = 后台批量新开 tab;quick = 用户当前浏览的 tab(不得改视口、需还原页面状态) */
4
23
  mode: 'batch' | 'quick';
5
24
  tabId: number;
6
25
  url: string;
7
26
  options: Settings;
8
- /** chrome.debugger sendCommand(已 attach) */
27
+ /** Capture commands reject on cancellation. */
9
28
  send(method: string, params?: Record<string, unknown>): Promise<Record<string, unknown>>;
29
+ /** Restoration MUST remain usable after Stop/abort. */
30
+ cleanup(method: string, params?: Record<string, unknown>): Promise<Record<string, unknown>>;
10
31
  }
11
32
  interface CaptureOutput {
12
33
  base64: string;
13
34
  mime: string;
14
- /** 文件扩展名,不含点:"png" | "jpg" | "pdf" … */
15
35
  extension: string;
16
- /** 非致命告警(如超高截断),展示在结果列表 */
17
36
  warning?: string;
18
37
  }
38
+ interface Entitlement {
39
+ expiresAt: string;
40
+ [key: string]: unknown;
41
+ }
42
+ interface LicenseReply {
43
+ accepted: boolean;
44
+ /** Authoritative server rejection, NOT a proxy/network error. */
45
+ denied?: boolean;
46
+ entitlement?: unknown;
47
+ token?: string;
48
+ deactivated?: boolean;
49
+ }
19
50
  interface LicensingConfig {
20
- apiBase: string;
21
- purchaseUrl: string;
51
+ purchaseUrl?: string;
52
+ cacheTtlMs: number;
53
+ offlineGraceMs: number;
54
+ requestTimeoutMs: number;
55
+ retryDelayMs: number;
56
+ /** Consumer owns transport, endpoints, code normalization and envelope validation. */
57
+ request(operation: 'activate' | 'me' | 'deactivate', input: {
58
+ code?: string;
59
+ deviceId?: string;
60
+ brand?: string;
61
+ token?: string;
62
+ }, signal: AbortSignal): Promise<LicenseReply>;
63
+ /** Validate the consumer's actual grant/plan. The kit additionally checks expiry. */
64
+ normalizeEntitlement(value: unknown): Entitlement | null;
65
+ }
66
+ interface LicenseStatus {
67
+ state: 'free' | 'checking' | 'pro' | 'invalid' | 'unavailable';
68
+ entitlement?: Entitlement;
69
+ message?: string;
70
+ refreshing?: boolean;
71
+ }
72
+ interface LicenseStatusOptions {
73
+ cachedOnly?: boolean;
74
+ force?: boolean;
75
+ }
76
+ interface Licensing {
77
+ activate(code: string): Promise<Entitlement>;
78
+ getEntitlement(options?: LicenseStatusOptions): Promise<Entitlement | null>;
79
+ getStatus(options?: LicenseStatusOptions): Promise<LicenseStatus>;
80
+ /** Releases the device remotely before deleting local identity. */
81
+ deactivate(): Promise<void>;
82
+ purchaseUrl?: string;
83
+ }
84
+ interface DownloadOptions {
85
+ deadlineMs?: number;
86
+ /** Must exceed deadlineMs; offscreen reclaims URLs if the worker disappears. */
87
+ blobLeaseMs?: number;
88
+ pollMs?: number;
89
+ offscreenUrl?: string;
90
+ }
91
+ interface DownloadCheckpoint {
92
+ downloadId?: number;
93
+ downloadUrl?: string;
94
+ }
95
+ interface Downloader {
96
+ downloadViaBlob(base64: string, mime: string, filename: string, options?: {
97
+ signal?: AbortSignal;
98
+ onPrepared?(url: string): Promise<void>;
99
+ onCreated?(id: number): Promise<void>;
100
+ }): Promise<number>;
101
+ recover(item: DownloadCheckpoint, signal?: AbortSignal): Promise<DownloadRecord>;
102
+ }
103
+ interface ScrollCapture {
104
+ prepare(ctx: CaptureContext, waitForContent?: () => Promise<void>): Promise<void>;
105
+ restore(ctx: CaptureContext): Promise<void>;
22
106
  }
23
- /** 措辞(capture/convert 等动词差异);不配则用 capture 系默认值 */
24
107
  interface ExtTexts {
25
108
  alreadyRunning: string;
26
109
  cannotQuick: string;
@@ -28,20 +111,30 @@ interface ExtTexts {
28
111
  quickFolder: string;
29
112
  }
30
113
  interface ExtKitConfig {
31
- /** 消费项目提供的存储 key 命名空间;已发布产品应保持原值,以兼容既有安装 */
114
+ /** Keep existing storage namespace and message prefix on upgrades. */
32
115
  product: string;
33
- /** 品牌名:下载文件夹前缀、设备名 */
34
116
  brand: string;
35
- /** 消费项目提供的消息类型前缀,用于构造 START 等消息类型 */
36
117
  messagePrefix: string;
37
- freeDailyLimit?: number;
118
+ freeDailyLimit: number;
38
119
  badgeColor: string;
39
120
  defaultSettings: Settings;
40
121
  licensing: LicensingConfig;
122
+ downloads?: DownloadOptions;
123
+ sameHostGapMs?: number;
41
124
  texts?: Partial<ExtTexts>;
42
- /** 仅批量模式、autoScroll 之前调用(如固定视口宽度);quick 模式不调用(不能动用户的 tab) */
125
+ /** PDF/image settings validation and migration belong to the consumer. */
126
+ normalizeSettings?(defaults: Settings, input?: unknown): Settings;
127
+ migrateSettings?(saved: unknown): Settings;
128
+ captureScope?(options: Settings): 'full' | 'viewport';
129
+ scrollCapture?: ScrollCapture;
43
130
  beforeScroll?(ctx: CaptureContext): Promise<void>;
44
- /** 核心业务:页面已加载、已过验证、已滚动揭示,产出要下载的数据 */
131
+ beforeQuick?(ctx: CaptureContext, tab: BrowserTab): Promise<void>;
132
+ afterQuick?(ctx: CaptureContext): Promise<void>;
133
+ captureQuick?(input: {
134
+ tab: BrowserTab;
135
+ options: Settings;
136
+ signal: AbortSignal;
137
+ }): Promise<CaptureOutput | null | undefined>;
45
138
  capture(ctx: CaptureContext): Promise<CaptureOutput>;
46
139
  }
47
140
  interface PopupTexts {
@@ -52,16 +145,14 @@ interface PopupTexts {
52
145
  }
53
146
  interface PopupConfig {
54
147
  messagePrefix: string;
55
- /** 消费项目提供的 URL 队列存储 key;已发布产品应保持原值 */
56
148
  queueKey: string;
57
- /** 快速处理当前页的消息类型后缀:CAPTURE_CURRENT / CONVERT_CURRENT */
149
+ settingsKey?: string;
58
150
  quickType: string;
59
- /** 快速按钮的元素 id,默认 "captureCurrent",可由消费项目覆盖 */
60
151
  quickButtonId?: string;
61
152
  texts: PopupTexts;
62
- collectSettings(): Settings;
63
- collectQuickSettings(): Settings;
64
- /** 快速处理成功后的状态栏文案 */
153
+ onSettingsLoaded?(): void;
154
+ collectSettings(): Settings | Promise<Settings>;
155
+ collectQuickSettings(): Settings | Promise<Settings>;
65
156
  quickResult(result: {
66
157
  fileName: string;
67
158
  warning?: string;
@@ -71,19 +162,29 @@ interface PopupConfig {
71
162
  declare function initExtension(config: ExtKitConfig): void;
72
163
 
73
164
  declare function initPopup(config: PopupConfig): void;
165
+ declare function collectSameOriginLinks(options?: { phase?: 'links' | 'sitemap' | 'cancel'; id?: string }): Promise<{ urls: string[]; sitemapCount?: number; incomplete?: boolean; cancelled?: boolean }>;
74
166
 
75
- interface Entitlement {
76
- plan: string;
77
- expiresAt: string;
78
- }
79
- interface Licensing {
80
- activate(code: string): Promise<unknown>;
81
- getEntitlement(): Promise<Entitlement | null>;
82
- isPro(): Promise<boolean>;
83
- clear(): Promise<void>;
84
- purchaseUrl: string;
167
+ declare function createDownloader(justification: string, options?: DownloadOptions): Downloader;
168
+
169
+ declare function prepare(ctx: CaptureContext, waitForContent?: () => Promise<void>): Promise<void>;
170
+ declare function restore(ctx: CaptureContext): Promise<void>;
171
+
172
+ declare const scrollCapture_d_prepare: typeof prepare;
173
+ declare const scrollCapture_d_restore: typeof restore;
174
+ declare namespace scrollCapture_d {
175
+ export { scrollCapture_d_prepare as prepare, scrollCapture_d_restore as restore };
85
176
  }
86
- declare function createLicensing(product: string, brand: string, config: LicensingConfig): Licensing;
177
+
178
+ declare const CAPTURE_LIMITS: Readonly<{ maxEdgeDevicePx: number; maxDevicePixels: number }>;
179
+ declare function captureFits(width: number, height: number, dpr: number): boolean;
180
+ declare function assertCaptureFits(width: number, height: number, dpr: number, message: string): void;
181
+ declare function captureBudget(dpr: number): { maxEdge: number; maxArea: number };
182
+ declare function readDevicePixelRatio(ctx: CaptureContext): Promise<number>;
183
+
184
+ declare function hidePageCaptureDecorations(): void;
185
+ declare function showPageCaptureDecorations(): void;
186
+
187
+ declare function createLicensing(namespace: string, brand: string, config: LicensingConfig): Licensing;
87
188
 
88
189
  declare function sanitize(value: string): string;
89
190
  declare function hostOf(url: string): string;
@@ -99,4 +200,4 @@ declare function buildBatchFileName(folder: string, item: {
99
200
  }, extension: string): string;
100
201
  declare function buildQuickFileName(brand: string, quickFolder: string, pageUrl: string, extension: string): string;
101
202
 
102
- export { type CaptureContext, type CaptureOutput, type Entitlement, type ExtKitConfig, type ExtTexts, type Licensing, type LicensingConfig, type PopupConfig, type PopupTexts, type Settings, buildBatchFileName, buildQuickFileName, createLicensing, fileStamp, folderNameFor, hostOf, initExtension, initPopup, normalizeUrls, sanitize, sessionStamp, todayString, urlBaseName };
203
+ export { type BrowserTab, CAPTURE_LIMITS, type CaptureContext, type CaptureOutput, type DownloadCheckpoint, type DownloadOptions, type DownloadRecord, type Downloader, type Entitlement, type ExtKitConfig, type ExtTexts, type LicenseReply, type LicenseStatus, type LicenseStatusOptions, type Licensing, type LicensingConfig, type PopupConfig, type PopupTexts, type ScrollCapture, type Settings, assertCaptureFits, buildBatchFileName, buildQuickFileName, captureBudget, captureFits, collectSameOriginLinks, createDownloader, createLicensing, fileStamp, folderNameFor, hidePageCaptureDecorations, hostOf, initExtension, initPopup, normalizeUrls, readDevicePixelRatio, sanitize, scrollCapture_d as scrollCapture, sessionStamp, showPageCaptureDecorations, todayString, urlBaseName };