@orbit-work/block-sdk 0.0.0-stage → 0.1.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/README.md +32 -2
- package/dist/index.d.ts +16 -0
- package/dist/index.js +60 -0
- package/dist/index.js.map +1 -0
- package/package.json +31 -4
package/README.md
CHANGED
|
@@ -1,3 +1,33 @@
|
|
|
1
|
-
#
|
|
1
|
+
# JSON block SDK
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
`@orbit-work/block-sdk` is an independent, publishable npm package with an ESM
|
|
4
|
+
entry and TypeScript declarations. It has no runtime dependencies or knowledge,
|
|
5
|
+
identity, UI or React behavior.
|
|
6
|
+
|
|
7
|
+
```ts
|
|
8
|
+
import { getBlockData } from "@orbit-work/block-sdk"
|
|
9
|
+
|
|
10
|
+
const data = await getBlockData<unknown>("my-config", {
|
|
11
|
+
env: "pre", // uat | pre | prod
|
|
12
|
+
signal: controller.signal,
|
|
13
|
+
timeoutMs: 3000,
|
|
14
|
+
})
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
The key is a standalone path identifier, unrelated to app IDs. Requests read
|
|
18
|
+
`https://s.fzcdn1.com/cdn/h5-data/<configKey>/<env>/data.json` with anonymous GET,
|
|
19
|
+
`credentials: "omit"`, `cache: "no-store"`, and no redirects. The default timeout
|
|
20
|
+
is three seconds and covers the response body. There is no persistent cache or
|
|
21
|
+
offline fallback. `BlockDataError.code` distinguishes `invalid-options`, `network`,
|
|
22
|
+
`http` (with `status`), `timeout`, `cancelled`, and `json` failures.
|
|
23
|
+
|
|
24
|
+
The generic is a TypeScript return type, not runtime validation. Each consumer
|
|
25
|
+
validates its own JSON fields and handles failures.
|
|
26
|
+
|
|
27
|
+
Public exports: `getBlockData`, `BlockDataError`, `BlockEnvironment`,
|
|
28
|
+
`GetBlockDataOptions`, and `BlockErrorCode`. The browser and Node.js 20+ use their
|
|
29
|
+
native Fetch API.
|
|
30
|
+
|
|
31
|
+
Build and test with `pnpm --filter @orbit-work/block-sdk test`.
|
|
32
|
+
`pnpm --filter @orbit-work/block-sdk pack` builds an installable tarball; it does
|
|
33
|
+
not publish to the registry.
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
type BlockEnvironment = "uat" | "pre" | "prod";
|
|
2
|
+
type GetBlockDataOptions = {
|
|
3
|
+
env: BlockEnvironment;
|
|
4
|
+
signal?: AbortSignal;
|
|
5
|
+
timeoutMs?: number;
|
|
6
|
+
};
|
|
7
|
+
type BlockErrorCode = "invalid-options" | "network" | "http" | "timeout" | "cancelled" | "json";
|
|
8
|
+
declare class BlockDataError extends Error {
|
|
9
|
+
readonly code: BlockErrorCode;
|
|
10
|
+
readonly status?: number;
|
|
11
|
+
constructor(code: BlockErrorCode, status?: number);
|
|
12
|
+
}
|
|
13
|
+
/** Dora's config key identifies a block, independently of any application ID. */
|
|
14
|
+
declare function getBlockData<T = unknown>(configKey: string, options: GetBlockDataOptions): Promise<T>;
|
|
15
|
+
|
|
16
|
+
export { BlockDataError, type BlockEnvironment, type BlockErrorCode, type GetBlockDataOptions, getBlockData };
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
// src/index.ts
|
|
2
|
+
var BlockDataError = class extends Error {
|
|
3
|
+
code;
|
|
4
|
+
status;
|
|
5
|
+
constructor(code, status) {
|
|
6
|
+
super(`Block data request failed: ${code}`);
|
|
7
|
+
this.name = "BlockDataError";
|
|
8
|
+
this.code = code;
|
|
9
|
+
this.status = status;
|
|
10
|
+
}
|
|
11
|
+
};
|
|
12
|
+
async function getBlockData(configKey, options) {
|
|
13
|
+
const timeoutMs = options.timeoutMs ?? 3e3;
|
|
14
|
+
if (typeof configKey !== "string" || !/^[A-Za-z0-9][A-Za-z0-9_-]*$/.test(configKey) || !["uat", "pre", "prod"].includes(options.env) || !Number.isFinite(timeoutMs) || timeoutMs <= 0)
|
|
15
|
+
throw new BlockDataError("invalid-options");
|
|
16
|
+
const controller = new AbortController();
|
|
17
|
+
let timedOut = false;
|
|
18
|
+
const cancel = () => controller.abort();
|
|
19
|
+
if (options.signal?.aborted) throw new BlockDataError("cancelled");
|
|
20
|
+
options.signal?.addEventListener("abort", cancel, { once: true });
|
|
21
|
+
const timer = setTimeout(() => {
|
|
22
|
+
timedOut = true;
|
|
23
|
+
controller.abort();
|
|
24
|
+
}, timeoutMs);
|
|
25
|
+
try {
|
|
26
|
+
let response;
|
|
27
|
+
try {
|
|
28
|
+
response = await fetch(`https://s.fzcdn1.com/cdn/h5-data/${configKey}/${options.env}/data.json`, {
|
|
29
|
+
method: "GET",
|
|
30
|
+
credentials: "omit",
|
|
31
|
+
cache: "no-store",
|
|
32
|
+
redirect: "error",
|
|
33
|
+
referrerPolicy: "no-referrer",
|
|
34
|
+
signal: controller.signal
|
|
35
|
+
});
|
|
36
|
+
} catch {
|
|
37
|
+
throw new BlockDataError("network");
|
|
38
|
+
}
|
|
39
|
+
if (!response.ok) throw new BlockDataError("http", response.status);
|
|
40
|
+
try {
|
|
41
|
+
const data = await response.json();
|
|
42
|
+
if (controller.signal.aborted) throw new BlockDataError("cancelled");
|
|
43
|
+
return data;
|
|
44
|
+
} catch {
|
|
45
|
+
throw new BlockDataError("json");
|
|
46
|
+
}
|
|
47
|
+
} catch (error) {
|
|
48
|
+
if (options.signal?.aborted) throw new BlockDataError("cancelled");
|
|
49
|
+
if (timedOut) throw new BlockDataError("timeout");
|
|
50
|
+
throw error instanceof BlockDataError ? error : new BlockDataError("network");
|
|
51
|
+
} finally {
|
|
52
|
+
clearTimeout(timer);
|
|
53
|
+
options.signal?.removeEventListener("abort", cancel);
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
export {
|
|
57
|
+
BlockDataError,
|
|
58
|
+
getBlockData
|
|
59
|
+
};
|
|
60
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/index.ts"],"sourcesContent":["export type BlockEnvironment = \"uat\" | \"pre\" | \"prod\"\n\nexport type GetBlockDataOptions = { env: BlockEnvironment; signal?: AbortSignal; timeoutMs?: number }\n\nexport type BlockErrorCode = \"invalid-options\" | \"network\" | \"http\" | \"timeout\" | \"cancelled\" | \"json\"\n\nexport class BlockDataError extends Error {\n readonly code: BlockErrorCode\n readonly status?: number\n constructor(code: BlockErrorCode, status?: number) {\n super(`Block data request failed: ${code}`)\n this.name = \"BlockDataError\"\n this.code = code\n this.status = status\n }\n}\n\n/** Dora's config key identifies a block, independently of any application ID. */\nexport async function getBlockData<T = unknown>(configKey: string, options: GetBlockDataOptions): Promise<T> {\n const timeoutMs = options.timeoutMs ?? 3000\n if (\n typeof configKey !== \"string\" ||\n !/^[A-Za-z0-9][A-Za-z0-9_-]*$/.test(configKey) ||\n ![\"uat\", \"pre\", \"prod\"].includes(options.env) ||\n !Number.isFinite(timeoutMs) ||\n timeoutMs <= 0\n )\n throw new BlockDataError(\"invalid-options\")\n\n const controller = new AbortController()\n let timedOut = false\n const cancel = () => controller.abort()\n if (options.signal?.aborted) throw new BlockDataError(\"cancelled\")\n options.signal?.addEventListener(\"abort\", cancel, { once: true })\n const timer = setTimeout(() => {\n timedOut = true\n controller.abort()\n }, timeoutMs)\n try {\n let response: Response\n try {\n response = await fetch(`https://s.fzcdn1.com/cdn/h5-data/${configKey}/${options.env}/data.json`, {\n method: \"GET\",\n credentials: \"omit\",\n cache: \"no-store\",\n redirect: \"error\",\n referrerPolicy: \"no-referrer\",\n signal: controller.signal,\n })\n } catch {\n throw new BlockDataError(\"network\")\n }\n if (!response.ok) throw new BlockDataError(\"http\", response.status)\n try {\n const data = (await response.json()) as T\n if (controller.signal.aborted) throw new BlockDataError(\"cancelled\")\n return data\n } catch {\n throw new BlockDataError(\"json\")\n }\n } catch (error) {\n if (options.signal?.aborted) throw new BlockDataError(\"cancelled\")\n if (timedOut) throw new BlockDataError(\"timeout\")\n throw error instanceof BlockDataError ? error : new BlockDataError(\"network\")\n } finally {\n clearTimeout(timer)\n options.signal?.removeEventListener(\"abort\", cancel)\n }\n}\n"],"mappings":";AAMO,IAAM,iBAAN,cAA6B,MAAM;AAAA,EAC/B;AAAA,EACA;AAAA,EACT,YAAY,MAAsB,QAAiB;AACjD,UAAM,8BAA8B,IAAI,EAAE;AAC1C,SAAK,OAAO;AACZ,SAAK,OAAO;AACZ,SAAK,SAAS;AAAA,EAChB;AACF;AAGA,eAAsB,aAA0B,WAAmB,SAA0C;AAC3G,QAAM,YAAY,QAAQ,aAAa;AACvC,MACE,OAAO,cAAc,YACrB,CAAC,8BAA8B,KAAK,SAAS,KAC7C,CAAC,CAAC,OAAO,OAAO,MAAM,EAAE,SAAS,QAAQ,GAAG,KAC5C,CAAC,OAAO,SAAS,SAAS,KAC1B,aAAa;AAEb,UAAM,IAAI,eAAe,iBAAiB;AAE5C,QAAM,aAAa,IAAI,gBAAgB;AACvC,MAAI,WAAW;AACf,QAAM,SAAS,MAAM,WAAW,MAAM;AACtC,MAAI,QAAQ,QAAQ,QAAS,OAAM,IAAI,eAAe,WAAW;AACjE,UAAQ,QAAQ,iBAAiB,SAAS,QAAQ,EAAE,MAAM,KAAK,CAAC;AAChE,QAAM,QAAQ,WAAW,MAAM;AAC7B,eAAW;AACX,eAAW,MAAM;AAAA,EACnB,GAAG,SAAS;AACZ,MAAI;AACF,QAAI;AACJ,QAAI;AACF,iBAAW,MAAM,MAAM,oCAAoC,SAAS,IAAI,QAAQ,GAAG,cAAc;AAAA,QAC/F,QAAQ;AAAA,QACR,aAAa;AAAA,QACb,OAAO;AAAA,QACP,UAAU;AAAA,QACV,gBAAgB;AAAA,QAChB,QAAQ,WAAW;AAAA,MACrB,CAAC;AAAA,IACH,QAAQ;AACN,YAAM,IAAI,eAAe,SAAS;AAAA,IACpC;AACA,QAAI,CAAC,SAAS,GAAI,OAAM,IAAI,eAAe,QAAQ,SAAS,MAAM;AAClE,QAAI;AACF,YAAM,OAAQ,MAAM,SAAS,KAAK;AAClC,UAAI,WAAW,OAAO,QAAS,OAAM,IAAI,eAAe,WAAW;AACnE,aAAO;AAAA,IACT,QAAQ;AACN,YAAM,IAAI,eAAe,MAAM;AAAA,IACjC;AAAA,EACF,SAAS,OAAO;AACd,QAAI,QAAQ,QAAQ,QAAS,OAAM,IAAI,eAAe,WAAW;AACjE,QAAI,SAAU,OAAM,IAAI,eAAe,SAAS;AAChD,UAAM,iBAAiB,iBAAiB,QAAQ,IAAI,eAAe,SAAS;AAAA,EAC9E,UAAE;AACA,iBAAa,KAAK;AAClB,YAAQ,QAAQ,oBAAoB,SAAS,MAAM;AAAA,EACrD;AACF;","names":[]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,33 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@orbit-work/block-sdk",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"
|
|
5
|
-
"
|
|
6
|
-
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "Anonymous JSON block client for CDN-published Dora data.",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"publishConfig": {
|
|
7
|
+
"access": "public",
|
|
8
|
+
"registry": "https://registry.npmjs.org/"
|
|
9
|
+
},
|
|
10
|
+
"main": "./dist/index.js",
|
|
11
|
+
"types": "./dist/index.d.ts",
|
|
12
|
+
"exports": {
|
|
13
|
+
".": {
|
|
14
|
+
"types": "./dist/index.d.ts",
|
|
15
|
+
"import": "./dist/index.js"
|
|
16
|
+
}
|
|
17
|
+
},
|
|
18
|
+
"files": ["dist"],
|
|
19
|
+
"sideEffects": false,
|
|
20
|
+
"scripts": {
|
|
21
|
+
"build": "tsup",
|
|
22
|
+
"prepack": "npm run build",
|
|
23
|
+
"typecheck": "tsc --noEmit",
|
|
24
|
+
"test": "pnpm run build && node --test \"src/**/*.test.mjs\""
|
|
25
|
+
},
|
|
26
|
+
"devDependencies": {
|
|
27
|
+
"tsup": "^8.5.1",
|
|
28
|
+
"typescript": "^5.6.3"
|
|
29
|
+
},
|
|
30
|
+
"engines": {
|
|
31
|
+
"node": ">=20.0.0"
|
|
32
|
+
}
|
|
33
|
+
}
|