tickdb-ts 0.0.0-stage → 0.3.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.
@@ -0,0 +1,61 @@
1
+ /** manifest FileEntry 字段与线上 JSON 完全一致(snake_case)。 */
2
+ export interface FileEntry {
3
+ path: string;
4
+ sha256: string;
5
+ size: number;
6
+ row_count: number;
7
+ symbol: string;
8
+ cycle: string;
9
+ ts_min: string;
10
+ ts_max: string;
11
+ year?: number;
12
+ symbols_count?: number;
13
+ /** v1.2:文件已冻结上云(内容永不再变,可从镜像下载)。 */
14
+ frozen?: boolean;
15
+ }
16
+ /** 支持的 manifest 版本字面量(parseManifest 收窄到这个联合;新增版本
17
+ * 时同步 SUPPORTED_VERSIONS 与 sync.ts 的版本门判定)。 */
18
+ export type ManifestVersion = 'v1' | 'v1.1' | 'v1.2' | 'v1.3' | 'v1.4';
19
+ export interface Manifest {
20
+ version: ManifestVersion;
21
+ schema: string;
22
+ generatedAt: string;
23
+ files: FileEntry[];
24
+ /** v1.2:对象存储公开基底 URL(未启用 mirror 时缺省)。 */
25
+ mirror_base_url?: string;
26
+ /** v1.3:服务端 compacted 文件 (symbol, ts) 互斥(重分区完成)。 */
27
+ disjoint?: boolean;
28
+ }
29
+ export interface InitOptions {
30
+ dataDir?: string;
31
+ token?: string;
32
+ serverUrl?: string;
33
+ autoSync?: boolean;
34
+ syncIntervalSecs?: number;
35
+ downloadConcurrency?: number;
36
+ }
37
+ export interface SyncReport {
38
+ notModified: boolean;
39
+ filesTotal: number;
40
+ filesFetched: number;
41
+ filesUnchanged: number;
42
+ rowsUpserted: number;
43
+ staleDeleted: number;
44
+ mirrorFetched: number;
45
+ mirrorFallbacks: number;
46
+ errors: string[];
47
+ }
48
+ export interface SyncStatus {
49
+ running: boolean;
50
+ startedAt: number;
51
+ finishedAt: number;
52
+ filesTotal: number;
53
+ filesFetched: number;
54
+ filesUnchanged: number;
55
+ rowsUpserted: number;
56
+ staleDeleted: number;
57
+ errorsCount: number;
58
+ daemonIntervalSecs: number;
59
+ daemonRunning: boolean;
60
+ lastError: string | null;
61
+ }
package/dist/types.js ADDED
@@ -0,0 +1 @@
1
+ export {};
package/dist/util.d.ts ADDED
@@ -0,0 +1,14 @@
1
+ /** 固定并发工作池:items 逐个领取,任何 fn 抛错由 fn 自身捕获(调用方负责 per-item try/catch)。 */
2
+ export declare function runPool<T>(items: readonly T[], limit: number, fn: (item: T) => Promise<void>): Promise<void>;
3
+ export declare function parseCycleYear(path: string): {
4
+ cycle: string;
5
+ year: number;
6
+ };
7
+ /** extra/ 前缀 = 聚合数据集文件(manifest v1.4):恒 direct 分流——
8
+ * 落盘 + view 直读,不进 kline upsert / 按 cycle-year 删行逻辑
9
+ * (对齐 Rust is_extra_file)。 */
10
+ export declare function isExtraFile(p: string): boolean;
11
+ export declare function yearBounds(year: number): [string, string];
12
+ export declare function expandHome(p: string): string;
13
+ export declare const nowSec: () => number;
14
+ export declare const sleep: (ms: number) => Promise<void>;
package/dist/util.js ADDED
@@ -0,0 +1,38 @@
1
+ import { homedir } from 'node:os';
2
+ import { join } from 'node:path';
3
+ /** 固定并发工作池:items 逐个领取,任何 fn 抛错由 fn 自身捕获(调用方负责 per-item try/catch)。 */
4
+ export async function runPool(items, limit, fn) {
5
+ let i = 0;
6
+ const n = Math.max(1, Math.min(limit, items.length));
7
+ const workers = Array.from({ length: n }, async () => {
8
+ while (i < items.length) {
9
+ const idx = i++;
10
+ await fn(items[idx]);
11
+ }
12
+ });
13
+ await Promise.all(workers);
14
+ }
15
+ export function parseCycleYear(path) {
16
+ const m = /cycle=([^/]+)\/year=(\d{4})(?:-month=\d{2})?\.parquet$/.exec(path);
17
+ if (!m)
18
+ throw new Error(`cannot parse cycle/year from manifest path: ${path}`);
19
+ return { cycle: m[1], year: Number(m[2]) };
20
+ }
21
+ /** extra/ 前缀 = 聚合数据集文件(manifest v1.4):恒 direct 分流——
22
+ * 落盘 + view 直读,不进 kline upsert / 按 cycle-year 删行逻辑
23
+ * (对齐 Rust is_extra_file)。 */
24
+ export function isExtraFile(p) {
25
+ return p.startsWith('extra/');
26
+ }
27
+ export function yearBounds(year) {
28
+ return [`${year}-01-01 00:00:00`, `${year}-12-31 23:59:59`];
29
+ }
30
+ export function expandHome(p) {
31
+ if (p === '~')
32
+ return homedir();
33
+ if (p.startsWith('~/'))
34
+ return join(homedir(), p.slice(2));
35
+ return p;
36
+ }
37
+ export const nowSec = () => Math.floor(Date.now() / 1000);
38
+ export const sleep = (ms) => new Promise((r) => setTimeout(r, ms));
package/package.json CHANGED
@@ -1,6 +1,29 @@
1
1
  {
2
2
  "name": "tickdb-ts",
3
- "version": "0.0.0-stage",
4
- "stub": true,
5
- "description": "Temporary package placeholder for staged publishing"
6
- }
3
+ "version": "0.3.0",
4
+ "description": "offline-first TypeScript client for tickdb (A-share market data): manifest sync + local DuckDB",
5
+ "type": "module",
6
+ "main": "dist/index.js",
7
+ "types": "dist/index.d.ts",
8
+ "exports": { ".": { "import": "./dist/index.js", "types": "./dist/index.d.ts" } },
9
+ "files": ["dist", "README.md"],
10
+ "engines": { "node": ">=18" },
11
+ "scripts": {
12
+ "build": "tsc",
13
+ "typecheck": "tsc --noEmit",
14
+ "test": "tsx --test test/*.test.ts",
15
+ "prepublishOnly": "npm run build && npm test"
16
+ },
17
+ "repository": {
18
+ "type": "git",
19
+ "url": "git+https://github.com/chuanlei-coding/growinpublic.git",
20
+ "directory": "tickdb/clients/tickdb-ts"
21
+ },
22
+ "license": "MIT",
23
+ "dependencies": { "@duckdb/node-api": "^2.0.0-r.1" },
24
+ "devDependencies": {
25
+ "@types/node": "^22",
26
+ "tsx": "^4",
27
+ "typescript": "^5"
28
+ }
29
+ }