@wovoon/polaris 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.
- package/README.md +30 -0
- package/dist/client.d.ts +87 -0
- package/dist/client.js +176 -0
- package/dist/index.d.ts +8 -0
- package/dist/index.js +6 -0
- package/dist/protocol.d.ts +95 -0
- package/dist/protocol.js +23 -0
- package/package.json +37 -0
package/README.md
ADDED
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
# @wovoon/polaris
|
|
2
|
+
|
|
3
|
+
wovoon 平台官方 SDK(协议 1):身份(每作品稳定 playerId)、数据集合(云存档/排行榜/用户数据)、云函数调用、房间实时通道。
|
|
4
|
+
|
|
5
|
+
```bash
|
|
6
|
+
npm i @wovoon/polaris
|
|
7
|
+
```
|
|
8
|
+
|
|
9
|
+
```ts
|
|
10
|
+
import { PolarisClient, parseData } from "@wovoon/polaris";
|
|
11
|
+
|
|
12
|
+
const polaris = new PolarisClient(); // 平台运行时同源自动识别作品
|
|
13
|
+
const session = await polaris.ready(); // { appId, playerId, loggedIn, ... }
|
|
14
|
+
|
|
15
|
+
const scores = polaris.collection("scores");
|
|
16
|
+
await scores.add({ score: 42 });
|
|
17
|
+
const top = await scores.query({ orderBy: "score", order: "desc", limit: 10,
|
|
18
|
+
where: { score: { gte: 10 } } });
|
|
19
|
+
|
|
20
|
+
await polaris.call("settle", { score: 99 }); // 云函数(服务端权威结算)
|
|
21
|
+
|
|
22
|
+
const room = polaris.room("lobby"); // 房间实时通道
|
|
23
|
+
room.onMessage(m => console.log(m.from, m.data));
|
|
24
|
+
room.send({ text: "你好" });
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
零构建页面可直接用平台同源下发的全局版:`<script src="/api/cloud/sdk.js"></script>` → `WovoonCloud.*`。
|
|
28
|
+
|
|
29
|
+
- 协议正典与完整能力说明见仓库 [PROTOCOL.md](https://gitea/wujiwanjie/wovoon-polaris-sdk) 与 [llms.txt](./llms.txt)
|
|
30
|
+
- 本地开发与校验:`npx @wovoon/cli init / dev / validate`
|
package/dist/client.d.ts
ADDED
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @wovoon/polaris 运行时客户端(协议 1)。
|
|
3
|
+
* 在作品内通过 <script> 引入平台下发的 /api/cloud/sdk.js(全局 WovoonCloud)即可使用,
|
|
4
|
+
* 本模块提供同一 API 的 TypeScript 实现,供构建型项目以模块方式引入。
|
|
5
|
+
*/
|
|
6
|
+
export interface PolarisRequestInit {
|
|
7
|
+
/** 覆盖 API 基址(本地模拟器/自建环境用),默认同源。 */
|
|
8
|
+
baseUrl?: string;
|
|
9
|
+
}
|
|
10
|
+
export declare class PolarisError extends Error {
|
|
11
|
+
readonly code: string;
|
|
12
|
+
constructor(message: string, code?: string);
|
|
13
|
+
}
|
|
14
|
+
export interface PolarisSessionView {
|
|
15
|
+
appId: string;
|
|
16
|
+
playerId: string;
|
|
17
|
+
loggedIn: boolean;
|
|
18
|
+
displayName?: string | null;
|
|
19
|
+
avatarUrl?: string | null;
|
|
20
|
+
}
|
|
21
|
+
export interface PolarisDocumentView {
|
|
22
|
+
id: string;
|
|
23
|
+
ownerPlayerId: string | null;
|
|
24
|
+
/** 文档内容(JSON 字符串,与平台下发版一致;用 parse() 得到对象)。 */
|
|
25
|
+
data: string;
|
|
26
|
+
seq: number;
|
|
27
|
+
createdAt: string;
|
|
28
|
+
updatedAt: string;
|
|
29
|
+
}
|
|
30
|
+
export interface PolarisQueryOptions {
|
|
31
|
+
limit?: number;
|
|
32
|
+
orderBy?: string;
|
|
33
|
+
order?: "asc" | "desc";
|
|
34
|
+
ownerOnly?: boolean;
|
|
35
|
+
where?: import("./protocol.js").WovoonWhereClause;
|
|
36
|
+
/**
|
|
37
|
+
* join 嵌入连接(最多 2 个):
|
|
38
|
+
* - 单值 `{"author": "users.authorId"}` —— 主文档 authorId 字段的值 = users 集合文档 id,嵌入拍平对象或 null;
|
|
39
|
+
* - 多值 `{"comments": ["comments", "postId"]}` —— comments 集合 postId 字段的值 = 主文档 id,嵌入数组(每侧最多 200 条)。
|
|
40
|
+
*/
|
|
41
|
+
join?: import("./protocol.js").WovoonJoinClause;
|
|
42
|
+
}
|
|
43
|
+
declare function parseData<T = Record<string, unknown>>(raw: string): T;
|
|
44
|
+
export declare class PolarisClient {
|
|
45
|
+
private readonly baseUrl;
|
|
46
|
+
private sessionPromise;
|
|
47
|
+
private target;
|
|
48
|
+
constructor(init?: PolarisRequestInit);
|
|
49
|
+
/** 指定作品目标:deploymentId(运行地址自动识别)或 appId。 */
|
|
50
|
+
configure(options: {
|
|
51
|
+
deploymentId?: string;
|
|
52
|
+
appId?: string;
|
|
53
|
+
}): this;
|
|
54
|
+
private request;
|
|
55
|
+
private detectTarget;
|
|
56
|
+
session(): Promise<PolarisSessionView>;
|
|
57
|
+
identity(): Promise<{
|
|
58
|
+
playerId: string;
|
|
59
|
+
loggedIn: boolean;
|
|
60
|
+
displayName: string | null | undefined;
|
|
61
|
+
avatarUrl: string | null | undefined;
|
|
62
|
+
}>;
|
|
63
|
+
/** 云函数(function 能力):call("settle", {score: 99}) → Promise<函数返回值>。 */
|
|
64
|
+
call<T = unknown>(name: string, event?: Record<string, unknown>): Promise<T>;
|
|
65
|
+
/**
|
|
66
|
+
* 房间实时通道(room 能力)。浏览器同源 WebSocket;返回的句柄与平台下发 SDK 行为一致:
|
|
67
|
+
* send 广播、onMessage 收 {from, data}、onPresence 收 joined/join/leave、onClose 断开。
|
|
68
|
+
*/
|
|
69
|
+
room(roomId: string): {
|
|
70
|
+
send: (data: unknown) => void;
|
|
71
|
+
leave: () => void;
|
|
72
|
+
onMessage: (callback: (payload: {
|
|
73
|
+
from: string;
|
|
74
|
+
data: unknown;
|
|
75
|
+
}) => void) => void;
|
|
76
|
+
onPresence: (callback: (frame: unknown) => void) => void;
|
|
77
|
+
onClose: (callback: (payload: unknown) => void) => void;
|
|
78
|
+
};
|
|
79
|
+
collection<T = Record<string, unknown>>(name: string): {
|
|
80
|
+
query: (options?: PolarisQueryOptions) => Promise<PolarisDocumentView[]>;
|
|
81
|
+
get: (id: string) => Promise<PolarisDocumentView>;
|
|
82
|
+
add: (data: T) => Promise<PolarisDocumentView>;
|
|
83
|
+
set: (id: string, data: T) => Promise<PolarisDocumentView>;
|
|
84
|
+
remove: (id: string) => Promise<unknown>;
|
|
85
|
+
};
|
|
86
|
+
}
|
|
87
|
+
export { parseData };
|
package/dist/client.js
ADDED
|
@@ -0,0 +1,176 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @wovoon/polaris 运行时客户端(协议 1)。
|
|
3
|
+
* 在作品内通过 <script> 引入平台下发的 /api/cloud/sdk.js(全局 WovoonCloud)即可使用,
|
|
4
|
+
* 本模块提供同一 API 的 TypeScript 实现,供构建型项目以模块方式引入。
|
|
5
|
+
*/
|
|
6
|
+
export class PolarisError extends Error {
|
|
7
|
+
constructor(message, code = "WOVOON_CLOUD_ERROR") {
|
|
8
|
+
super(message);
|
|
9
|
+
this.code = code;
|
|
10
|
+
this.name = "PolarisError";
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
function parseData(raw) {
|
|
14
|
+
try {
|
|
15
|
+
return JSON.parse(raw);
|
|
16
|
+
}
|
|
17
|
+
catch {
|
|
18
|
+
return {};
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
export class PolarisClient {
|
|
22
|
+
constructor(init = {}) {
|
|
23
|
+
this.sessionPromise = null;
|
|
24
|
+
this.target = "";
|
|
25
|
+
this.baseUrl = (init.baseUrl ?? "").replace(/\/$/, "");
|
|
26
|
+
}
|
|
27
|
+
/** 指定作品目标:deploymentId(运行地址自动识别)或 appId。 */
|
|
28
|
+
configure(options) {
|
|
29
|
+
this.target = options.deploymentId ?? options.appId ?? this.target;
|
|
30
|
+
this.sessionPromise = null;
|
|
31
|
+
return this;
|
|
32
|
+
}
|
|
33
|
+
request(method, path, body) {
|
|
34
|
+
return fetch(this.baseUrl + path, {
|
|
35
|
+
method,
|
|
36
|
+
credentials: "include",
|
|
37
|
+
headers: body === undefined ? undefined : { "Content-Type": "application/json" },
|
|
38
|
+
body: body === undefined ? undefined : JSON.stringify(body),
|
|
39
|
+
}).then(async (response) => {
|
|
40
|
+
const payload = await response.json().catch(() => null);
|
|
41
|
+
if (!response.ok || (payload && payload.success === false)) {
|
|
42
|
+
throw new PolarisError((payload && payload.message) || `HTTP ${response.status}`, (payload && payload.code) || "WOVOON_CLOUD_ERROR");
|
|
43
|
+
}
|
|
44
|
+
return (payload && payload.data);
|
|
45
|
+
});
|
|
46
|
+
}
|
|
47
|
+
detectTarget() {
|
|
48
|
+
if (this.target)
|
|
49
|
+
return this.target;
|
|
50
|
+
const match = /\/api\/public\/static\/([0-9a-fA-F-]{36})/.exec(typeof location === "undefined" ? "" : location.pathname);
|
|
51
|
+
return match ? match[1] : "";
|
|
52
|
+
}
|
|
53
|
+
session() {
|
|
54
|
+
if (this.sessionPromise)
|
|
55
|
+
return this.sessionPromise;
|
|
56
|
+
const target = this.detectTarget();
|
|
57
|
+
if (!target) {
|
|
58
|
+
this.sessionPromise = Promise.reject(new PolarisError("未识别作品:请通过 wovoon 平台运行,或 configure({deploymentId})", "WOVOON_TARGET_MISSING"));
|
|
59
|
+
return this.sessionPromise;
|
|
60
|
+
}
|
|
61
|
+
this.sessionPromise = this.request("POST", "/api/cloud/session", {
|
|
62
|
+
deploymentId: target,
|
|
63
|
+
appId: target,
|
|
64
|
+
});
|
|
65
|
+
return this.sessionPromise;
|
|
66
|
+
}
|
|
67
|
+
identity() {
|
|
68
|
+
return this.session().then((data) => ({
|
|
69
|
+
playerId: data.playerId,
|
|
70
|
+
loggedIn: data.loggedIn,
|
|
71
|
+
displayName: data.displayName,
|
|
72
|
+
avatarUrl: data.avatarUrl,
|
|
73
|
+
}));
|
|
74
|
+
}
|
|
75
|
+
/** 云函数(function 能力):call("settle", {score: 99}) → Promise<函数返回值>。 */
|
|
76
|
+
call(name, event) {
|
|
77
|
+
if (!name)
|
|
78
|
+
throw new PolarisError("call(name) 需要函数名", "WOVOON_ARGUMENT");
|
|
79
|
+
return this.session().then((data) => this.request("POST", `/api/cloud/${data.appId}/functions/${encodeURIComponent(name)}`, {
|
|
80
|
+
event: event ?? {},
|
|
81
|
+
}));
|
|
82
|
+
}
|
|
83
|
+
/**
|
|
84
|
+
* 房间实时通道(room 能力)。浏览器同源 WebSocket;返回的句柄与平台下发 SDK 行为一致:
|
|
85
|
+
* send 广播、onMessage 收 {from, data}、onPresence 收 joined/join/leave、onClose 断开。
|
|
86
|
+
*/
|
|
87
|
+
room(roomId) {
|
|
88
|
+
if (!roomId)
|
|
89
|
+
throw new PolarisError("room(roomId) 需要房间号", "WOVOON_ARGUMENT");
|
|
90
|
+
const listeners = {
|
|
91
|
+
message: [], presence: [], close: [],
|
|
92
|
+
};
|
|
93
|
+
let socket = null;
|
|
94
|
+
let left = false;
|
|
95
|
+
const emit = (kind, payload) => {
|
|
96
|
+
for (const callback of listeners[kind]) {
|
|
97
|
+
try {
|
|
98
|
+
callback(payload);
|
|
99
|
+
}
|
|
100
|
+
catch { /* 监听器异常不中断通道 */ }
|
|
101
|
+
}
|
|
102
|
+
};
|
|
103
|
+
this.session().then((data) => {
|
|
104
|
+
if (left || typeof WebSocket === "undefined") {
|
|
105
|
+
if (!left)
|
|
106
|
+
emit("close", { error: "当前环境不支持 WebSocket" });
|
|
107
|
+
return;
|
|
108
|
+
}
|
|
109
|
+
const origin = this.baseUrl || `${location.protocol}//${location.host}`;
|
|
110
|
+
const scheme = origin.startsWith("https") ? "wss" : "ws";
|
|
111
|
+
socket = new WebSocket(`${scheme}://${origin.replace(/^https?:\/\//, "")}/api/cloud/rooms/${data.appId}/${encodeURIComponent(roomId)}`);
|
|
112
|
+
socket.onmessage = (event) => {
|
|
113
|
+
let frame = null;
|
|
114
|
+
try {
|
|
115
|
+
frame = JSON.parse(String(event.data));
|
|
116
|
+
}
|
|
117
|
+
catch {
|
|
118
|
+
return;
|
|
119
|
+
}
|
|
120
|
+
if (!frame || !("type" in frame))
|
|
121
|
+
return;
|
|
122
|
+
if (frame.type === "msg")
|
|
123
|
+
emit("message", { from: frame.from, data: frame.data });
|
|
124
|
+
else if (frame.type === "joined" || frame.type === "join" || frame.type === "leave")
|
|
125
|
+
emit("presence", frame);
|
|
126
|
+
else if (frame.type === "error")
|
|
127
|
+
emit("message", { error: frame.message });
|
|
128
|
+
};
|
|
129
|
+
socket.onclose = () => emit("close", {});
|
|
130
|
+
socket.onerror = () => emit("close", {});
|
|
131
|
+
}).catch((error) => emit("close", { error: error.message }));
|
|
132
|
+
return {
|
|
133
|
+
send: (data) => {
|
|
134
|
+
if (socket && socket.readyState === 1)
|
|
135
|
+
socket.send(JSON.stringify({ type: "msg", data }));
|
|
136
|
+
},
|
|
137
|
+
leave: () => {
|
|
138
|
+
left = true;
|
|
139
|
+
try {
|
|
140
|
+
socket?.close();
|
|
141
|
+
}
|
|
142
|
+
catch { /* 已关闭 */ }
|
|
143
|
+
},
|
|
144
|
+
onMessage: (callback) => { listeners.message.push(callback); },
|
|
145
|
+
onPresence: (callback) => { listeners.presence.push(callback); },
|
|
146
|
+
onClose: (callback) => { listeners.close.push(callback); },
|
|
147
|
+
};
|
|
148
|
+
}
|
|
149
|
+
collection(name) {
|
|
150
|
+
if (!name)
|
|
151
|
+
throw new PolarisError("collection(name) 需要集合名", "WOVOON_ARGUMENT");
|
|
152
|
+
const ready = this.session().then((data) => data.appId);
|
|
153
|
+
const docUrl = (id) => ready.then((appId) => `/api/cloud/${appId}/collections/${encodeURIComponent(name)}/docs${id ? "/" + id : ""}`);
|
|
154
|
+
const client = this;
|
|
155
|
+
return {
|
|
156
|
+
query: (options = {}) => {
|
|
157
|
+
const params = [`limit=${options.limit ?? 20}`];
|
|
158
|
+
if (options.orderBy)
|
|
159
|
+
params.push(`orderBy=${encodeURIComponent(options.orderBy)}`);
|
|
160
|
+
params.push(`order=${options.order === "asc" ? "asc" : "desc"}`);
|
|
161
|
+
if (options.ownerOnly)
|
|
162
|
+
params.push("ownerOnly=true");
|
|
163
|
+
if (options.where)
|
|
164
|
+
params.push(`where=${encodeURIComponent(JSON.stringify(options.where))}`);
|
|
165
|
+
if (options.join)
|
|
166
|
+
params.push(`join=${encodeURIComponent(JSON.stringify(options.join))}`);
|
|
167
|
+
return docUrl().then((url) => client.request("GET", `${url}?${params.join("&")}`));
|
|
168
|
+
},
|
|
169
|
+
get: (id) => docUrl(id).then((url) => client.request("GET", url)),
|
|
170
|
+
add: (data) => docUrl().then((url) => client.request("POST", url, { data: JSON.stringify(data ?? {}) })),
|
|
171
|
+
set: (id, data) => docUrl(id).then((url) => client.request("PUT", url, { data: JSON.stringify(data ?? {}) })),
|
|
172
|
+
remove: (id) => docUrl(id).then((url) => client.request("DELETE", url)),
|
|
173
|
+
};
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
export { parseData };
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @wovoon/polaris SDK 入口(v0.1 协议层)。
|
|
3
|
+
* 当前导出协议 1 的冻结类型与常量;运行时客户端(identity/collection 等)在 M1 第 2~3 步落地。
|
|
4
|
+
*/
|
|
5
|
+
export { WOVOON_PROTOCOL_VERSION, COLLECTION_NAME_PATTERN, isValidCollectionName, CAPABILITY_PATTERN, isValidCapability, WovoonProtocolError, } from "./protocol.js";
|
|
6
|
+
export { PolarisClient, PolarisError, parseData } from "./client.js";
|
|
7
|
+
export type { WovoonCapability, WovoonCollectionName, WovoonManifest, WovoonSession, WovoonDocument, WovoonQueryOptions, WovoonFunctionEvent, WovoonFunctionResult, WovoonRoomFrame, } from "./protocol.js";
|
|
8
|
+
export type { PolarisRequestInit, PolarisSessionView, PolarisDocumentView, PolarisQueryOptions } from "./client.js";
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @wovoon/polaris SDK 入口(v0.1 协议层)。
|
|
3
|
+
* 当前导出协议 1 的冻结类型与常量;运行时客户端(identity/collection 等)在 M1 第 2~3 步落地。
|
|
4
|
+
*/
|
|
5
|
+
export { WOVOON_PROTOCOL_VERSION, COLLECTION_NAME_PATTERN, isValidCollectionName, CAPABILITY_PATTERN, isValidCapability, WovoonProtocolError, } from "./protocol.js";
|
|
6
|
+
export { PolarisClient, PolarisError, parseData } from "./client.js";
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* wovoon 平台协议 v1 类型定义(与 PROTOCOL.md 逐字对应)。
|
|
3
|
+
* 这些类型是冻结的公共 API:只加不改不删。任何 AI coding 工具以本文件为准确理解协议。
|
|
4
|
+
*/
|
|
5
|
+
/** 协议版本。协议 1 是当前唯一支持的版本。 */
|
|
6
|
+
export declare const WOVOON_PROTOCOL_VERSION: 1;
|
|
7
|
+
/** 协议 1 冻结的能力名。集合能力形如 `collection:${WovoonCollectionName}`。 */
|
|
8
|
+
export type WovoonCapability = "identity" | `collection:${WovoonCollectionName}` | "function" | "room";
|
|
9
|
+
/** 集合名:2-32 位,小写字母开头,仅小写字母/数字/下划线。运行时校验用下方正则。 */
|
|
10
|
+
export type WovoonCollectionName = string;
|
|
11
|
+
export declare const COLLECTION_NAME_PATTERN: RegExp;
|
|
12
|
+
export declare function isValidCollectionName(name: string): name is WovoonCollectionName;
|
|
13
|
+
/** manifest 里单个能力名的完整合法形态(与平台 AssetSecurityScanner.parseContract 的校验一致)。 */
|
|
14
|
+
export declare const CAPABILITY_PATTERN: RegExp;
|
|
15
|
+
export declare function isValidCapability(value: string): boolean;
|
|
16
|
+
/** `.wovoon` 清单文件内容。空文件等价于 `{ protocol: 1 }`。 */
|
|
17
|
+
export interface WovoonManifest {
|
|
18
|
+
/** 协议版本,当前仅支持 1,缺省为 1。 */
|
|
19
|
+
protocol?: typeof WOVOON_PROTOCOL_VERSION;
|
|
20
|
+
/** 声明使用的能力;未声明的能力在对应服务上线后不可调用。 */
|
|
21
|
+
capabilities?: WovoonCapability[];
|
|
22
|
+
}
|
|
23
|
+
/** 云函数事件与返回(function 能力):任意 JSON 值;沙箱限时 3s/限内存 64MB,出入参 ≤32KB。 */
|
|
24
|
+
export type WovoonFunctionEvent = Record<string, unknown>;
|
|
25
|
+
export type WovoonFunctionResult = unknown;
|
|
26
|
+
/** 房间帧(room 能力):msg=消息、joined/join/leave=在线状态。 */
|
|
27
|
+
export type WovoonRoomFrame = {
|
|
28
|
+
type: "joined";
|
|
29
|
+
roomId: string;
|
|
30
|
+
you: string;
|
|
31
|
+
players: string[];
|
|
32
|
+
} | {
|
|
33
|
+
type: "join" | "leave";
|
|
34
|
+
playerId: string;
|
|
35
|
+
} | {
|
|
36
|
+
type: "msg";
|
|
37
|
+
from: string;
|
|
38
|
+
data: unknown;
|
|
39
|
+
} | {
|
|
40
|
+
type: "error";
|
|
41
|
+
message: string;
|
|
42
|
+
};
|
|
43
|
+
/** 运行会话身份(identity 能力)。playerId 对“账号×作品”稳定,跨作品不可关联。 */
|
|
44
|
+
export interface WovoonSession {
|
|
45
|
+
appId: string;
|
|
46
|
+
playerId: string;
|
|
47
|
+
loggedIn: boolean;
|
|
48
|
+
displayName?: string | null;
|
|
49
|
+
avatarUrl?: string | null;
|
|
50
|
+
}
|
|
51
|
+
/** 集合中的文档视图(collection 能力)。ownerPlayerId 为作品内玩家 ID,不暴露平台账号。 */
|
|
52
|
+
export interface WovoonDocument {
|
|
53
|
+
id: string;
|
|
54
|
+
ownerPlayerId: string | null;
|
|
55
|
+
data: Record<string, unknown>;
|
|
56
|
+
seq: number;
|
|
57
|
+
createdAt: string;
|
|
58
|
+
updatedAt: string;
|
|
59
|
+
}
|
|
60
|
+
/** where 条件:字段等值,或 {gte,lte,gt,lt,ne,in} 范围(数值/字符串比较)。 */
|
|
61
|
+
export interface WovoonWhereClause {
|
|
62
|
+
[field: string]: unknown | {
|
|
63
|
+
gte?: number;
|
|
64
|
+
lte?: number;
|
|
65
|
+
gt?: number;
|
|
66
|
+
lt?: number;
|
|
67
|
+
ne?: unknown;
|
|
68
|
+
in?: unknown[];
|
|
69
|
+
};
|
|
70
|
+
}
|
|
71
|
+
/**
|
|
72
|
+
* join 嵌入连接声明(查询最多 2 个):
|
|
73
|
+
* - 单值:`"集合.字段"` —— 主文档该字段的值 = 目标集合文档 id,结果嵌入拍平对象或 null;
|
|
74
|
+
* - 多值:`["集合", "字段"]` —— 目标集合该字段的值 = 主文档 id,结果嵌入数组(每侧最多 200 条)。
|
|
75
|
+
* 被连接集合必须同样在 .wovoon manifest 的 capabilities 中声明;嵌入按目标集合读规则逐文档过滤。
|
|
76
|
+
*/
|
|
77
|
+
export type WovoonJoinValue = string | [collection: string, on: string];
|
|
78
|
+
export interface WovoonJoinClause {
|
|
79
|
+
[alias: string]: WovoonJoinValue;
|
|
80
|
+
}
|
|
81
|
+
/** 集合查询参数。orderBy 按文档字段数值排序(排行榜场景)。 */
|
|
82
|
+
export interface WovoonQueryOptions {
|
|
83
|
+
limit?: number;
|
|
84
|
+
orderBy?: string;
|
|
85
|
+
order?: "asc" | "desc";
|
|
86
|
+
ownerOnly?: boolean;
|
|
87
|
+
afterSeq?: number;
|
|
88
|
+
where?: WovoonWhereClause;
|
|
89
|
+
join?: WovoonJoinClause;
|
|
90
|
+
}
|
|
91
|
+
/** 平台协议类错误:message 必含“缺什么 + 怎么修”。 */
|
|
92
|
+
export declare class WovoonProtocolError extends Error {
|
|
93
|
+
readonly code: string;
|
|
94
|
+
constructor(message: string, code?: string);
|
|
95
|
+
}
|
package/dist/protocol.js
ADDED
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* wovoon 平台协议 v1 类型定义(与 PROTOCOL.md 逐字对应)。
|
|
3
|
+
* 这些类型是冻结的公共 API:只加不改不删。任何 AI coding 工具以本文件为准确理解协议。
|
|
4
|
+
*/
|
|
5
|
+
/** 协议版本。协议 1 是当前唯一支持的版本。 */
|
|
6
|
+
export const WOVOON_PROTOCOL_VERSION = 1;
|
|
7
|
+
export const COLLECTION_NAME_PATTERN = /^[a-z][a-z0-9_]{1,31}$/;
|
|
8
|
+
export function isValidCollectionName(name) {
|
|
9
|
+
return COLLECTION_NAME_PATTERN.test(name);
|
|
10
|
+
}
|
|
11
|
+
/** manifest 里单个能力名的完整合法形态(与平台 AssetSecurityScanner.parseContract 的校验一致)。 */
|
|
12
|
+
export const CAPABILITY_PATTERN = /^(identity|function|room|collection:[a-z][a-z0-9_]{1,31})$/;
|
|
13
|
+
export function isValidCapability(value) {
|
|
14
|
+
return CAPABILITY_PATTERN.test(value);
|
|
15
|
+
}
|
|
16
|
+
/** 平台协议类错误:message 必含“缺什么 + 怎么修”。 */
|
|
17
|
+
export class WovoonProtocolError extends Error {
|
|
18
|
+
constructor(message, code = "WOVOON_PROTOCOL") {
|
|
19
|
+
super(message);
|
|
20
|
+
this.code = code;
|
|
21
|
+
this.name = "WovoonProtocolError";
|
|
22
|
+
}
|
|
23
|
+
}
|
package/package.json
ADDED
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@wovoon/polaris",
|
|
3
|
+
"version": "0.3.0",
|
|
4
|
+
"description": "wovoon Polaris SDK——wovoon 大后台云能力客户端(身份/数据集合/云函数/房间实时),协议 1",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "dist/index.js",
|
|
7
|
+
"types": "dist/index.d.ts",
|
|
8
|
+
"files": [
|
|
9
|
+
"dist",
|
|
10
|
+
"PROTOCOL.md",
|
|
11
|
+
"README.md"
|
|
12
|
+
],
|
|
13
|
+
"scripts": {
|
|
14
|
+
"build": "tsc -p tsconfig.json",
|
|
15
|
+
"check": "tsc --noEmit"
|
|
16
|
+
},
|
|
17
|
+
"keywords": [
|
|
18
|
+
"wovoon",
|
|
19
|
+
"polaris",
|
|
20
|
+
"sdk",
|
|
21
|
+
"cloud",
|
|
22
|
+
"baas",
|
|
23
|
+
"game"
|
|
24
|
+
],
|
|
25
|
+
"license": "MIT",
|
|
26
|
+
"devDependencies": {
|
|
27
|
+
"@types/node": "^26.5.1",
|
|
28
|
+
"typescript": "^7.0.2"
|
|
29
|
+
},
|
|
30
|
+
"repository": {
|
|
31
|
+
"type": "git"
|
|
32
|
+
},
|
|
33
|
+
"publishConfig": {
|
|
34
|
+
"access": "public",
|
|
35
|
+
"registry": "https://registry.npmjs.org/"
|
|
36
|
+
}
|
|
37
|
+
}
|