talizen 0.0.4

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 ADDED
@@ -0,0 +1,80 @@
1
+ # talizen
2
+
3
+ Talizen 前端 SDK 类型仓库,统一提供:
4
+
5
+ - `talizen/core`
6
+ - `talizen/cms`
7
+ - `talizen/form`
8
+
9
+ 这个仓库的目标是把 Talizen 平台前端会直接使用的类型和最小运行时请求封装整理成一个可以独立发布到 GitHub 和 npm 的包。
10
+
11
+ ## 安装
12
+
13
+ ```bash
14
+ npm install talizen
15
+ ```
16
+
17
+ ## 使用
18
+
19
+ ```ts
20
+ import { setTalizenConfig } from "talizen/core"
21
+ import { ListContent, type BaseCmsItem } from "talizen/cms"
22
+
23
+ interface Blogs extends BaseCmsItem {
24
+ readonly __cmsKey: "blogs"
25
+ body: {
26
+ title?: string
27
+ content?: string
28
+ }
29
+ }
30
+
31
+ setTalizenConfig({
32
+ baseUrl: "https://www.talizen.com",
33
+ projectId: "demo-project",
34
+ })
35
+
36
+ const blogs = await ListContent<Blogs>("blogs", {
37
+ limit: 10,
38
+ })
39
+ ```
40
+
41
+ 表单提交:
42
+
43
+ ```ts
44
+ import { SubmitForm } from "talizen/form"
45
+
46
+ await SubmitForm(
47
+ {
48
+ token: "form-token",
49
+ data: {
50
+ email: "hi@talizen.com",
51
+ },
52
+ },
53
+ {
54
+ projectId: "demo-project",
55
+ },
56
+ )
57
+ ```
58
+
59
+ ## 类型设计
60
+
61
+ - `talizen/core`:通用基础类型,来自后端 `internal/model`。
62
+ - `talizen/cms`:CMS schema、content、筛选参数、获取内容 API。
63
+ - `talizen/form`:Form schema、提交参数、日志类型、提交 API。
64
+
65
+ 其中业务项目自己的 `types/cms.d.ts`、`types/form.d.ts` 依然建议由平台按项目 schema 动态生成;本仓库负责承载平台级公共类型和泛型 API。
66
+
67
+ ## 发布
68
+
69
+ ```bash
70
+ npm install
71
+ npm run build
72
+ npm publish
73
+ ```
74
+
75
+ GitHub Actions 工作流在 `.github/workflows/publish.yml`,按 tag 发布 npm 包:
76
+
77
+ ```bash
78
+ git tag v0.1.0
79
+ git push origin v0.1.0
80
+ ```
@@ -0,0 +1,77 @@
1
+ import { type ContentBodyField, type ContentSchema, type DBId, type TalizenRequestOptions } from "../core/index.js";
2
+ export interface BaseCmsItem {
3
+ readonly __cmsKey: string;
4
+ slug: string;
5
+ id: DBId;
6
+ body: Record<string, unknown>;
7
+ }
8
+ export interface CmsListItem<T extends BaseCmsItem = BaseCmsItem> {
9
+ key: T["__cmsKey"];
10
+ name: string;
11
+ Item: T;
12
+ }
13
+ export interface CmsApp<TSchema extends ContentSchema = ContentSchema> {
14
+ id: DBId;
15
+ project_id: DBId;
16
+ key: string;
17
+ user_id: number;
18
+ name: string;
19
+ desc: string;
20
+ schema: TSchema;
21
+ created_at: string;
22
+ updated_at: string;
23
+ visibility?: "private" | "public" | (string & {});
24
+ }
25
+ export type ContentStatus = "online" | "offline" | (string & {});
26
+ export interface CmsContent<TBody extends Record<string, unknown> = Record<string, unknown>> {
27
+ id: DBId;
28
+ slug: string;
29
+ content_app_id: DBId;
30
+ user_id: number;
31
+ schema: ContentSchema;
32
+ tags?: string[];
33
+ status?: ContentStatus;
34
+ body: {
35
+ [K in keyof TBody]?: ContentBodyField<TBody[K]>;
36
+ };
37
+ draft_body?: {
38
+ [K in keyof TBody]?: ContentBodyField<TBody[K]>;
39
+ };
40
+ created_at: string;
41
+ updated_at: string;
42
+ }
43
+ export interface GetContentListFilterCondition {
44
+ fieldId?: string;
45
+ operator?: string;
46
+ value?: unknown;
47
+ }
48
+ export interface GetContentListFilter {
49
+ match?: "any" | "all";
50
+ conditions?: GetContentListFilterCondition[];
51
+ }
52
+ export interface ListContentParams {
53
+ limit?: number;
54
+ offset?: number;
55
+ searchKey?: string;
56
+ orderBy?: string;
57
+ builtinRef?: boolean;
58
+ filter?: GetContentListFilter;
59
+ }
60
+ export interface GetContentParams {
61
+ builtinRef?: boolean;
62
+ }
63
+ export interface GetContentWithPrevNextParams extends GetContentParams {
64
+ prev?: boolean;
65
+ next?: boolean;
66
+ searchKey?: string;
67
+ orderBy?: string;
68
+ filter?: GetContentListFilter;
69
+ }
70
+ export interface ContentWithPrevNext<T extends BaseCmsItem> {
71
+ current?: T;
72
+ next?: T;
73
+ prev?: T;
74
+ }
75
+ export declare function ListContent<T extends BaseCmsItem>(key: T["__cmsKey"], params?: ListContentParams, options?: TalizenRequestOptions): Promise<T[]>;
76
+ export declare function GetContent<T extends BaseCmsItem>(key: T["__cmsKey"], slug: string, params?: GetContentParams, options?: TalizenRequestOptions): Promise<T>;
77
+ export declare function GetContentWithPrevNext<T extends BaseCmsItem>(key: T["__cmsKey"], slug: string, params?: GetContentWithPrevNextParams, options?: TalizenRequestOptions): Promise<ContentWithPrevNext<T>>;
@@ -0,0 +1,56 @@
1
+ import { requestJson, resolveTalizenConfig } from "../core/index.js";
2
+ export async function ListContent(key, params = {}, options) {
3
+ const projectId = requireProjectId(options);
4
+ const response = await requestJson(`/api/r/project/${projectId}/cms_by_key/${key}/content_list`, {
5
+ method: "POST",
6
+ body: JSON.stringify({
7
+ limit: params.limit,
8
+ offset: params.offset,
9
+ search_key: params.searchKey,
10
+ order_by: params.orderBy,
11
+ builtin_ref: params.builtinRef,
12
+ filter: params.filter,
13
+ }),
14
+ }, options);
15
+ return response.list ?? [];
16
+ }
17
+ export async function GetContent(key, slug, params, options) {
18
+ const projectId = requireProjectId(options);
19
+ const url = new URL(`/api/r/project/${projectId}/cms_by_key/${key}/content`, "https://talizen.local");
20
+ url.searchParams.set("slug", slug);
21
+ if (params?.builtinRef != null) {
22
+ url.searchParams.set("builtin_ref", String(params.builtinRef));
23
+ }
24
+ return requestJson(url.pathname + url.search, undefined, options);
25
+ }
26
+ export async function GetContentWithPrevNext(key, slug, params = {}, options) {
27
+ const projectId = requireProjectId(options);
28
+ const url = new URL(`/api/r/project/${projectId}/cms_by_key/${key}/content_with_prev_next`, "https://talizen.local");
29
+ url.searchParams.set("slug", slug);
30
+ if (params.prev != null) {
31
+ url.searchParams.set("prev", String(params.prev));
32
+ }
33
+ if (params.next != null) {
34
+ url.searchParams.set("next", String(params.next));
35
+ }
36
+ if (params.searchKey) {
37
+ url.searchParams.set("search_key", params.searchKey);
38
+ }
39
+ if (params.orderBy) {
40
+ url.searchParams.set("order_by", params.orderBy);
41
+ }
42
+ if (params.builtinRef != null) {
43
+ url.searchParams.set("builtin_ref", String(params.builtinRef));
44
+ }
45
+ if (params.filter) {
46
+ url.searchParams.set("filter", JSON.stringify(params.filter));
47
+ }
48
+ return requestJson(url.pathname + url.search, undefined, options);
49
+ }
50
+ function requireProjectId(options) {
51
+ const projectId = resolveTalizenConfig(options).projectId;
52
+ if (projectId) {
53
+ return projectId;
54
+ }
55
+ throw new Error("Talizen projectId is required. Pass options.projectId or call setTalizenConfig({ projectId }).");
56
+ }
@@ -0,0 +1,68 @@
1
+ export type DBId = string;
2
+ export type Variable = unknown;
3
+ export type Datatype = "array" | "string" | "int" | "float" | "bool" | "date" | "datetime" | "time" | "file" | "image" | "video" | "audio" | "text" | "cms";
4
+ export interface TV<T = unknown> {
5
+ type: Datatype | string;
6
+ value: T;
7
+ }
8
+ export interface ImgItem {
9
+ size?: number;
10
+ name?: string;
11
+ src: string;
12
+ alt?: string;
13
+ width?: number;
14
+ }
15
+ export type Image = ImgItem[] | ImgItem;
16
+ export type Link = string;
17
+ export type LinkType = "custom" | "system" | (string & {});
18
+ export interface LinkProps {
19
+ value?: string;
20
+ link?: string;
21
+ type?: LinkType;
22
+ linkType?: LinkType;
23
+ section?: string;
24
+ slug?: Variable;
25
+ }
26
+ export interface ContentBodyField<T = unknown> {
27
+ value?: T;
28
+ value_raw?: unknown;
29
+ type: Datatype | string;
30
+ type_ref?: string;
31
+ }
32
+ export interface SchemaControl {
33
+ path: string;
34
+ type: Datatype | string;
35
+ controls?: SchemaControl[];
36
+ }
37
+ export type ContentFieldOptionM = Record<string, TV>;
38
+ export interface ContentSchemaField {
39
+ key: string;
40
+ name: string;
41
+ desc?: string;
42
+ name_locales?: Record<string, string>;
43
+ datatype?: Datatype | string;
44
+ help_locales?: Record<string, string>;
45
+ enable_search?: boolean;
46
+ extension?: unknown;
47
+ options?: ContentFieldOptionM[];
48
+ controls?: SchemaControl[];
49
+ cms_id?: string;
50
+ cms_label_field?: string;
51
+ }
52
+ export interface ContentSchema {
53
+ fields?: ContentSchemaField[];
54
+ }
55
+ export interface TalizenClientConfig {
56
+ baseUrl?: string;
57
+ projectId?: string;
58
+ headers?: HeadersInit;
59
+ fetch?: typeof fetch;
60
+ }
61
+ export interface TalizenRequestOptions extends TalizenClientConfig {
62
+ signal?: AbortSignal;
63
+ }
64
+ export declare function setTalizenConfig(config: TalizenClientConfig): void;
65
+ export declare function getTalizenConfig(): TalizenClientConfig;
66
+ export declare function resolveTalizenConfig(config?: TalizenRequestOptions): Required<Pick<TalizenClientConfig, "baseUrl" | "projectId" | "fetch">> & TalizenRequestOptions;
67
+ export declare function buildTalizenUrl(path: string, config?: TalizenRequestOptions): string;
68
+ export declare function requestJson<T>(path: string, init?: RequestInit, config?: TalizenRequestOptions): Promise<T>;
@@ -0,0 +1,72 @@
1
+ let globalTalizenConfig = {};
2
+ export function setTalizenConfig(config) {
3
+ globalTalizenConfig = {
4
+ ...globalTalizenConfig,
5
+ ...config,
6
+ };
7
+ }
8
+ export function getTalizenConfig() {
9
+ return {
10
+ ...globalTalizenConfig,
11
+ };
12
+ }
13
+ export function resolveTalizenConfig(config) {
14
+ const merged = {
15
+ ...globalTalizenConfig,
16
+ ...config,
17
+ };
18
+ const baseUrl = merged.baseUrl ?? getDefaultBaseUrl();
19
+ const projectId = merged.projectId ?? "";
20
+ const fetchImpl = merged.fetch ?? getDefaultFetch();
21
+ return {
22
+ ...merged,
23
+ baseUrl,
24
+ projectId,
25
+ fetch: fetchImpl,
26
+ };
27
+ }
28
+ export function buildTalizenUrl(path, config) {
29
+ const resolved = resolveTalizenConfig(config);
30
+ return new URL(path.replace(/^\//, ""), ensureBaseUrl(resolved.baseUrl)).toString();
31
+ }
32
+ export async function requestJson(path, init, config) {
33
+ const resolved = resolveTalizenConfig(config);
34
+ const headers = new Headers(resolved.headers ?? {});
35
+ if (init?.headers) {
36
+ new Headers(init.headers).forEach((value, key) => {
37
+ headers.set(key, value);
38
+ });
39
+ }
40
+ if (init?.body != null && !headers.has("content-type")) {
41
+ headers.set("content-type", "application/json");
42
+ }
43
+ const response = await resolved.fetch(buildTalizenUrl(path, resolved), {
44
+ ...init,
45
+ headers,
46
+ signal: resolved.signal,
47
+ });
48
+ if (!response.ok) {
49
+ const text = await response.text();
50
+ throw new Error(`Talizen request failed: ${response.status} ${response.statusText} ${text}`.trim());
51
+ }
52
+ const text = await response.text();
53
+ if (text === "") {
54
+ return undefined;
55
+ }
56
+ return JSON.parse(text);
57
+ }
58
+ function ensureBaseUrl(baseUrl) {
59
+ return baseUrl.endsWith("/") ? baseUrl : `${baseUrl}/`;
60
+ }
61
+ function getDefaultBaseUrl() {
62
+ if (typeof window !== "undefined" && window.location?.origin) {
63
+ return window.location.origin;
64
+ }
65
+ throw new Error("Talizen baseUrl is required. Call setTalizenConfig({ baseUrl }) first.");
66
+ }
67
+ function getDefaultFetch() {
68
+ if (typeof fetch === "function") {
69
+ return fetch;
70
+ }
71
+ throw new Error("Talizen fetch implementation is required in the current runtime.");
72
+ }
@@ -0,0 +1,39 @@
1
+ import { type ContentBodyField, type ContentSchema, type DBId, type TalizenRequestOptions } from "../core/index.js";
2
+ export interface FormSetting {
3
+ }
4
+ export interface FormApp<TSchema extends ContentSchema = ContentSchema> {
5
+ id: DBId;
6
+ project_id: DBId;
7
+ key: string;
8
+ user_id: number;
9
+ name: string;
10
+ desc: string;
11
+ schema: TSchema;
12
+ setting: FormSetting;
13
+ created_at: string;
14
+ updated_at: string;
15
+ }
16
+ export type FormLogBody<TBody extends Record<string, unknown>> = {
17
+ [K in keyof TBody]?: ContentBodyField<TBody[K]>;
18
+ };
19
+ export interface FormLog<TBody extends Record<string, unknown> = Record<string, unknown>> {
20
+ id: DBId;
21
+ form_id: DBId;
22
+ uid: string;
23
+ ua: string;
24
+ ip: string;
25
+ form_url: string;
26
+ body: FormLogBody<TBody>;
27
+ created_at: string;
28
+ updated_at: string;
29
+ }
30
+ export interface SubmitFormParams<TBody extends Record<string, unknown> = Record<string, unknown>> {
31
+ token: string;
32
+ data: TBody;
33
+ ip?: string;
34
+ uid?: string;
35
+ ua?: string;
36
+ fromUrl?: string;
37
+ }
38
+ export declare function GetForm(formId: DBId, options?: TalizenRequestOptions): Promise<FormApp>;
39
+ export declare function SubmitForm<TBody extends Record<string, unknown> = Record<string, unknown>>(params: SubmitFormParams<TBody>, options?: TalizenRequestOptions): Promise<"ok">;
@@ -0,0 +1,26 @@
1
+ import { requestJson, resolveTalizenConfig } from "../core/index.js";
2
+ export async function GetForm(formId, options) {
3
+ const projectId = requireProjectId(options);
4
+ return requestJson(`/api/r/project/${projectId}/form/${formId}`, undefined, options);
5
+ }
6
+ export async function SubmitForm(params, options) {
7
+ const projectId = requireProjectId(options);
8
+ return requestJson(`/api/r/project/${projectId}/form`, {
9
+ method: "POST",
10
+ body: JSON.stringify({
11
+ token: params.token,
12
+ data: params.data,
13
+ ip: params.ip,
14
+ uid: params.uid,
15
+ ua: params.ua,
16
+ from_url: params.fromUrl,
17
+ }),
18
+ }, options);
19
+ }
20
+ function requireProjectId(options) {
21
+ const projectId = resolveTalizenConfig(options).projectId;
22
+ if (projectId) {
23
+ return projectId;
24
+ }
25
+ throw new Error("Talizen projectId is required. Pass options.projectId or call setTalizenConfig({ projectId }).");
26
+ }
@@ -0,0 +1,3 @@
1
+ export * from "./core/index.js";
2
+ export * from "./cms/index.js";
3
+ export * from "./form/index.js";
package/dist/index.js ADDED
@@ -0,0 +1,3 @@
1
+ export * from "./core/index.js";
2
+ export * from "./cms/index.js";
3
+ export * from "./form/index.js";
package/package.json ADDED
@@ -0,0 +1,38 @@
1
+ {
2
+ "name": "talizen",
3
+ "version": "0.0.4",
4
+ "description": "Talizen frontend SDK types for cms, form and core.",
5
+ "type": "module",
6
+ "license": "MIT",
7
+ "files": [
8
+ "dist",
9
+ "README.md"
10
+ ],
11
+ "sideEffects": false,
12
+ "types": "./dist/index.d.ts",
13
+ "exports": {
14
+ ".": {
15
+ "types": "./dist/index.d.ts",
16
+ "import": "./dist/index.js"
17
+ },
18
+ "./core": {
19
+ "types": "./dist/core/index.d.ts",
20
+ "import": "./dist/core/index.js"
21
+ },
22
+ "./cms": {
23
+ "types": "./dist/cms/index.d.ts",
24
+ "import": "./dist/cms/index.js"
25
+ },
26
+ "./form": {
27
+ "types": "./dist/form/index.d.ts",
28
+ "import": "./dist/form/index.js"
29
+ }
30
+ },
31
+ "scripts": {
32
+ "build": "tsc -p tsconfig.json",
33
+ "check": "tsc -p tsconfig.json --noEmit"
34
+ },
35
+ "devDependencies": {
36
+ "typescript": "^5.9.2"
37
+ }
38
+ }