@blocklet/pages-kit-core 0.0.1
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/LICENSE +13 -0
- package/lib/cjs/block.d.ts +11 -0
- package/lib/cjs/block.js +91 -0
- package/lib/cjs/core.d.ts +12 -0
- package/lib/cjs/core.js +43 -0
- package/lib/cjs/dataset.d.ts +8 -0
- package/lib/cjs/dataset.js +34 -0
- package/lib/cjs/index.d.ts +3 -0
- package/lib/cjs/index.js +19 -0
- package/lib/cjs/page.d.ts +11 -0
- package/lib/cjs/page.js +77 -0
- package/lib/cjs/renderable.d.ts +6 -0
- package/lib/cjs/renderable.js +6 -0
- package/lib/cjs/tsconfig.tsbuildinfo +1 -0
- package/lib/cjs/types/block.d.ts +4 -0
- package/lib/cjs/types/block.js +2 -0
- package/lib/cjs/types/core.d.ts +22 -0
- package/lib/cjs/types/core.js +2 -0
- package/lib/cjs/types/dataset.d.ts +16 -0
- package/lib/cjs/types/dataset.js +2 -0
- package/lib/cjs/types/env.d.ts +6 -0
- package/lib/cjs/types/env.js +3 -0
- package/lib/cjs/types/index.d.ts +6 -0
- package/lib/cjs/types/index.js +22 -0
- package/lib/cjs/types/page.d.ts +28 -0
- package/lib/cjs/types/page.js +2 -0
- package/lib/cjs/types/renderable.d.ts +11 -0
- package/lib/cjs/types/renderable.js +2 -0
- package/lib/esm/block.d.ts +11 -0
- package/lib/esm/block.js +64 -0
- package/lib/esm/core.d.ts +12 -0
- package/lib/esm/core.js +39 -0
- package/lib/esm/dataset.d.ts +8 -0
- package/lib/esm/dataset.js +30 -0
- package/lib/esm/index.d.ts +3 -0
- package/lib/esm/index.js +3 -0
- package/lib/esm/page.d.ts +11 -0
- package/lib/esm/page.js +73 -0
- package/lib/esm/renderable.d.ts +6 -0
- package/lib/esm/renderable.js +2 -0
- package/lib/esm/tsconfig.tsbuildinfo +1 -0
- package/lib/esm/types/block.d.ts +4 -0
- package/lib/esm/types/block.js +1 -0
- package/lib/esm/types/core.d.ts +22 -0
- package/lib/esm/types/core.js +1 -0
- package/lib/esm/types/dataset.d.ts +16 -0
- package/lib/esm/types/dataset.js +1 -0
- package/lib/esm/types/env.d.ts +6 -0
- package/lib/esm/types/env.js +2 -0
- package/lib/esm/types/index.d.ts +6 -0
- package/lib/esm/types/index.js +6 -0
- package/lib/esm/types/page.d.ts +28 -0
- package/lib/esm/types/page.js +1 -0
- package/lib/esm/types/renderable.d.ts +11 -0
- package/lib/esm/types/renderable.js +1 -0
- package/lib/types/block.d.ts +11 -0
- package/lib/types/core.d.ts +12 -0
- package/lib/types/dataset.d.ts +8 -0
- package/lib/types/index.d.ts +3 -0
- package/lib/types/page.d.ts +11 -0
- package/lib/types/renderable.d.ts +6 -0
- package/lib/types/tsconfig.tsbuildinfo +1 -0
- package/lib/types/types/block.d.ts +4 -0
- package/lib/types/types/core.d.ts +22 -0
- package/lib/types/types/dataset.d.ts +16 -0
- package/lib/types/types/env.d.ts +6 -0
- package/lib/types/types/index.d.ts +6 -0
- package/lib/types/types/page.d.ts +28 -0
- package/lib/types/types/renderable.d.ts +11 -0
- package/package.json +75 -0
- package/tsconfig.json +16 -0
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
export interface PageMetadata {
|
|
2
|
+
id: string;
|
|
3
|
+
title?: string;
|
|
4
|
+
ogImage?: string;
|
|
5
|
+
description?: string;
|
|
6
|
+
slug: string;
|
|
7
|
+
[key: string]: any;
|
|
8
|
+
}
|
|
9
|
+
export interface DatasetStructure {
|
|
10
|
+
[pageId: string]: DatasetStructure;
|
|
11
|
+
}
|
|
12
|
+
export interface IDataset<T = any> {
|
|
13
|
+
get(key: string): Promise<T | null>;
|
|
14
|
+
set(key: string, value: T): Promise<T | null>;
|
|
15
|
+
clear(): Promise<void>;
|
|
16
|
+
}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
14
|
+
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
15
|
+
};
|
|
16
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
|
+
__exportStar(require("./renderable"), exports);
|
|
18
|
+
__exportStar(require("./block"), exports);
|
|
19
|
+
__exportStar(require("./page"), exports);
|
|
20
|
+
__exportStar(require("./dataset"), exports);
|
|
21
|
+
__exportStar(require("./core"), exports);
|
|
22
|
+
__exportStar(require("./env"), exports);
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { Block } from './block';
|
|
2
|
+
import { Renderable } from './renderable';
|
|
3
|
+
export interface PageBlocks extends Map<string, Block> {
|
|
4
|
+
}
|
|
5
|
+
export interface PageStructure {
|
|
6
|
+
[pageId: string]: PageBlocks;
|
|
7
|
+
}
|
|
8
|
+
export interface Page extends Renderable {
|
|
9
|
+
blocks?: PageBlocks;
|
|
10
|
+
}
|
|
11
|
+
export interface PageSection {
|
|
12
|
+
id: string;
|
|
13
|
+
component: string;
|
|
14
|
+
name?: string;
|
|
15
|
+
config?: Record<string, any>;
|
|
16
|
+
properties?: Record<string, any>;
|
|
17
|
+
code?: string;
|
|
18
|
+
}
|
|
19
|
+
export interface PageMeta {
|
|
20
|
+
backgroundColor?: string;
|
|
21
|
+
}
|
|
22
|
+
export interface PageData {
|
|
23
|
+
id: string;
|
|
24
|
+
createdAt: string;
|
|
25
|
+
updatedAt: string;
|
|
26
|
+
meta: PageMeta;
|
|
27
|
+
sections: PageSection[];
|
|
28
|
+
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
export interface CacheOptions {
|
|
2
|
+
key: string;
|
|
3
|
+
ttl?: number;
|
|
4
|
+
}
|
|
5
|
+
export interface RenderOptions {
|
|
6
|
+
locale?: string;
|
|
7
|
+
cacheOptions?: CacheOptions;
|
|
8
|
+
}
|
|
9
|
+
export interface Renderable<I = any, O = any> {
|
|
10
|
+
render(input: I, options?: RenderOptions): Promise<O>;
|
|
11
|
+
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { Block as BlockType } from '@types';
|
|
2
|
+
import { ReactElement } from 'react';
|
|
3
|
+
import { Renderable, RenderOptions } from './types/renderable';
|
|
4
|
+
export declare class Block implements BlockType, Renderable<Record<string, any>, ReactElement | null> {
|
|
5
|
+
code?: string | undefined;
|
|
6
|
+
private ESM_IMPORT_REGEX;
|
|
7
|
+
private ESM_KEYWORDS;
|
|
8
|
+
constructor(code?: string | undefined);
|
|
9
|
+
setData(code: string): void;
|
|
10
|
+
render(input?: Record<string, any>, _options?: RenderOptions): Promise<ReactElement | null>;
|
|
11
|
+
}
|
package/lib/esm/block.js
ADDED
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
2
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
3
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
4
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
5
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
6
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
7
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
8
|
+
});
|
|
9
|
+
};
|
|
10
|
+
export class Block {
|
|
11
|
+
constructor(code) {
|
|
12
|
+
this.code = code;
|
|
13
|
+
// 预编译正则表达式
|
|
14
|
+
this.ESM_IMPORT_REGEX = /import\s+\w+\s+from/;
|
|
15
|
+
this.ESM_KEYWORDS = ['export {', 'export default', 'import {', 'import *'];
|
|
16
|
+
}
|
|
17
|
+
setData(code) {
|
|
18
|
+
this.code = code;
|
|
19
|
+
}
|
|
20
|
+
render(input, _options) {
|
|
21
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
22
|
+
var _a, _b;
|
|
23
|
+
if (!this.code) {
|
|
24
|
+
return null;
|
|
25
|
+
}
|
|
26
|
+
try {
|
|
27
|
+
const isESM = this.ESM_KEYWORDS.some((keyword) => { var _a; return (_a = this.code) === null || _a === void 0 ? void 0 : _a.includes(keyword); }) ||
|
|
28
|
+
this.ESM_IMPORT_REGEX.test(this.code || '');
|
|
29
|
+
if (!isESM) {
|
|
30
|
+
// UMD 格式处理
|
|
31
|
+
if (!((_a = this.code) === null || _a === void 0 ? void 0 : _a.includes('function(')) && !((_b = this.code) === null || _b === void 0 ? void 0 : _b.includes('function ('))) {
|
|
32
|
+
throw new Error('Invalid code format: UMD wrapper not found');
|
|
33
|
+
}
|
|
34
|
+
if (!this.code.includes('Component')) {
|
|
35
|
+
throw new Error('Invalid UMD format: Component export not found');
|
|
36
|
+
}
|
|
37
|
+
const Component = new Function(`${this.code}; return Component;`)();
|
|
38
|
+
if (typeof Component !== 'function') {
|
|
39
|
+
throw new Error('Invalid UMD format: Component is not a function');
|
|
40
|
+
}
|
|
41
|
+
return Component(Object.assign({}, input));
|
|
42
|
+
}
|
|
43
|
+
// ESM 格式处理
|
|
44
|
+
const blob = new Blob([this.code], { type: 'application/javascript' });
|
|
45
|
+
const url = URL.createObjectURL(blob);
|
|
46
|
+
try {
|
|
47
|
+
const module = yield import(/* @vite-ignore */ url);
|
|
48
|
+
const Component = module.default;
|
|
49
|
+
if (typeof Component !== 'function') {
|
|
50
|
+
throw new Error('Invalid ESM format: default export is not a function');
|
|
51
|
+
}
|
|
52
|
+
return Component(Object.assign({}, input));
|
|
53
|
+
}
|
|
54
|
+
finally {
|
|
55
|
+
URL.revokeObjectURL(url);
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
catch (error) {
|
|
59
|
+
console.error('Failed to render block:', error);
|
|
60
|
+
throw new Error(`Failed to execute code: ${error.message}`);
|
|
61
|
+
}
|
|
62
|
+
});
|
|
63
|
+
}
|
|
64
|
+
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { Block, CoreConstructor, CoreOptions, ICore, Page } from '@types';
|
|
2
|
+
import { Dataset } from './dataset';
|
|
3
|
+
export declare class Core<B extends Block = Block, D extends Dataset = Dataset, P extends Page = Page> implements ICore<B, D, P> {
|
|
4
|
+
readonly blocks: Map<string, B>;
|
|
5
|
+
readonly datasets: Map<string, D>;
|
|
6
|
+
readonly pages: Map<string, P>;
|
|
7
|
+
readonly options: CoreOptions;
|
|
8
|
+
constructor({ blocks, datasets, pages, options, }?: CoreConstructor<B, D, P>);
|
|
9
|
+
readonly block: Block;
|
|
10
|
+
readonly page: Page;
|
|
11
|
+
private mergeRenderOptions;
|
|
12
|
+
}
|
package/lib/esm/core.js
ADDED
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
2
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
3
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
4
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
5
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
6
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
7
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
8
|
+
});
|
|
9
|
+
};
|
|
10
|
+
import { merge } from 'lodash';
|
|
11
|
+
export class Core {
|
|
12
|
+
constructor({ blocks = new Map(), datasets = new Map(), pages = new Map(), options = {}, } = {}) {
|
|
13
|
+
this.block = {
|
|
14
|
+
render: (_input, _options) => __awaiter(this, void 0, void 0, function* () {
|
|
15
|
+
const options = this.mergeRenderOptions(_options);
|
|
16
|
+
// eslint-disable-next-line no-console
|
|
17
|
+
console.log('options', options);
|
|
18
|
+
// Implementation here
|
|
19
|
+
return Promise.resolve();
|
|
20
|
+
}),
|
|
21
|
+
};
|
|
22
|
+
this.page = {
|
|
23
|
+
render: (_input, _options) => __awaiter(this, void 0, void 0, function* () {
|
|
24
|
+
const options = this.mergeRenderOptions(_options);
|
|
25
|
+
// eslint-disable-next-line no-console
|
|
26
|
+
console.log('options', options);
|
|
27
|
+
// Implementation here
|
|
28
|
+
return Promise.resolve();
|
|
29
|
+
}),
|
|
30
|
+
};
|
|
31
|
+
this.blocks = blocks;
|
|
32
|
+
this.datasets = datasets;
|
|
33
|
+
this.pages = pages;
|
|
34
|
+
this.options = options;
|
|
35
|
+
}
|
|
36
|
+
mergeRenderOptions(renderOptions) {
|
|
37
|
+
return merge({}, this.options, renderOptions);
|
|
38
|
+
}
|
|
39
|
+
}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { DatasetStructure, IDataset } from '@types';
|
|
2
|
+
export declare class Dataset implements IDataset<DatasetStructure> {
|
|
3
|
+
private store;
|
|
4
|
+
constructor(initialData?: DatasetStructure);
|
|
5
|
+
get(key: string): Promise<DatasetStructure | null>;
|
|
6
|
+
set(key: string, value: DatasetStructure): Promise<DatasetStructure | null>;
|
|
7
|
+
clear(): Promise<void>;
|
|
8
|
+
}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
2
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
3
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
4
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
5
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
6
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
7
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
8
|
+
});
|
|
9
|
+
};
|
|
10
|
+
export class Dataset {
|
|
11
|
+
constructor(initialData = {}) {
|
|
12
|
+
this.store = initialData;
|
|
13
|
+
}
|
|
14
|
+
get(key) {
|
|
15
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
16
|
+
return this.store[key] || null;
|
|
17
|
+
});
|
|
18
|
+
}
|
|
19
|
+
set(key, value) {
|
|
20
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
21
|
+
this.store[key] = value;
|
|
22
|
+
return this.store[key];
|
|
23
|
+
});
|
|
24
|
+
}
|
|
25
|
+
clear() {
|
|
26
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
27
|
+
this.store = {};
|
|
28
|
+
});
|
|
29
|
+
}
|
|
30
|
+
}
|
package/lib/esm/index.js
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { Page as PageType, PageData, PageBlocks, RenderOptions } from '@types';
|
|
2
|
+
import { ReactElement } from 'react';
|
|
3
|
+
export declare class Page implements PageType {
|
|
4
|
+
private data?;
|
|
5
|
+
blocks: PageBlocks;
|
|
6
|
+
constructor(data?: PageData);
|
|
7
|
+
private initBlocks;
|
|
8
|
+
private createPageElement;
|
|
9
|
+
setData(data: PageData): void;
|
|
10
|
+
render(input?: Record<string, any>, options?: RenderOptions): Promise<ReactElement | null>;
|
|
11
|
+
}
|
package/lib/esm/page.js
ADDED
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
2
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
3
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
4
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
5
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
6
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
7
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
8
|
+
});
|
|
9
|
+
};
|
|
10
|
+
import { Block } from './block';
|
|
11
|
+
export class Page {
|
|
12
|
+
constructor(data) {
|
|
13
|
+
this.blocks = new Map();
|
|
14
|
+
this.data = data;
|
|
15
|
+
if (data) {
|
|
16
|
+
this.initBlocks(data.sections);
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
initBlocks(sections) {
|
|
20
|
+
sections.forEach((section) => {
|
|
21
|
+
if (section.code) {
|
|
22
|
+
const block = new Block(section.code);
|
|
23
|
+
this.blocks.set(section.id, block);
|
|
24
|
+
}
|
|
25
|
+
});
|
|
26
|
+
}
|
|
27
|
+
createPageElement(props, children) {
|
|
28
|
+
// 这里实现页面容器组件的创建逻辑
|
|
29
|
+
return {
|
|
30
|
+
type: 'div',
|
|
31
|
+
props: Object.assign(Object.assign({}, props), { children }),
|
|
32
|
+
};
|
|
33
|
+
}
|
|
34
|
+
setData(data) {
|
|
35
|
+
this.data = data;
|
|
36
|
+
this.blocks.clear();
|
|
37
|
+
this.initBlocks(data.sections);
|
|
38
|
+
}
|
|
39
|
+
render(input, options) {
|
|
40
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
41
|
+
if (!this.data) {
|
|
42
|
+
return null;
|
|
43
|
+
}
|
|
44
|
+
try {
|
|
45
|
+
// 1. 处理页面级别的配置
|
|
46
|
+
const pageProps = Object.assign({ id: this.data.id, backgroundColor: this.data.meta.backgroundColor }, input);
|
|
47
|
+
// @FIXME: 这个 map 应该是不需要的
|
|
48
|
+
// 使用 Block 实例渲染 sections
|
|
49
|
+
const sections = yield Promise.all(this.data.sections.map((section) => __awaiter(this, void 0, void 0, function* () {
|
|
50
|
+
try {
|
|
51
|
+
const block = this.blocks.get(section.id);
|
|
52
|
+
if (!block) {
|
|
53
|
+
throw new Error(`Block not found for section ${section.id}`);
|
|
54
|
+
}
|
|
55
|
+
// 合并配置传入 Block
|
|
56
|
+
const sectionProps = Object.assign(Object.assign({ key: section.id, id: section.id }, section.config), section.properties);
|
|
57
|
+
return block.render(sectionProps, options);
|
|
58
|
+
}
|
|
59
|
+
catch (error) {
|
|
60
|
+
console.error(`Failed to render section ${section.id}:`, error);
|
|
61
|
+
return null;
|
|
62
|
+
}
|
|
63
|
+
})));
|
|
64
|
+
// 3. 返回页面组件
|
|
65
|
+
return this.createPageElement(pageProps, sections.filter(Boolean));
|
|
66
|
+
}
|
|
67
|
+
catch (error) {
|
|
68
|
+
console.error('Failed to render page:', error);
|
|
69
|
+
throw new Error(`Failed to render page: ${error.message}`);
|
|
70
|
+
}
|
|
71
|
+
});
|
|
72
|
+
}
|
|
73
|
+
}
|