@james_sww/metaform-asset-distribution 0.1.0 → 0.1.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/README.md CHANGED
@@ -7,7 +7,7 @@
7
7
  发布版本使用 Node 24.18.0、pnpm 10.18.2。CLI 自带固定版本模板与源码 Registry,无需平台仓库或本机桌面目录。私有包需有下载权限;沙箱凭据由运行环境注入,不写入应用源码。
8
8
 
9
9
  ```sh
10
- npm install -g @james_sww/metaform-asset-distribution@0.1.0
10
+ npm install -g @james_sww/metaform-asset-distribution@0.1.1
11
11
  metaform-assets init --project ./my-app
12
12
  cd my-app
13
13
  corepack pnpm install --frozen-lockfile
@@ -16,7 +16,7 @@ corepack pnpm install --frozen-lockfile
16
16
  不安装全局工具也可运行:
17
17
 
18
18
  ```sh
19
- npm exec --yes --package=@james_sww/metaform-asset-distribution@0.1.0 -- metaform-assets init --project ./my-app
19
+ npm exec --yes --package=@james_sww/metaform-asset-distribution@0.1.1 -- metaform-assets init --project ./my-app
20
20
  ```
21
21
 
22
22
  Agent 根据应用本体和 skill 形成 `ApplicationDesign` JSON 后,在已初始化的应用目录执行:
@@ -31,7 +31,7 @@ corepack pnpm dev
31
31
 
32
32
  CLI 负责按底稿确定性装配;读取线上本体并作语义转译由 Agent 完成。匹配组件安装为应用内源码,未匹配区域保留语义骨架。模板初始化、安装成功不代表真实业务数据已绑定或平台 S7 已自动接通。
33
33
 
34
- 基础模板也单独按 `@james_sww/metaform-codebase-template@0.1.0` 分发,可安装到工具目录后用 `--codebase /path/to/node_modules/@james_sww/metaform-codebase-template` 指定。初始化底稿的完整类型随 CLI 发布在 `dist/application-design.d.ts`,语义区域类型在 `dist/generated/semantic-region-contract.d.ts`。固定 CLI、模板和 Registry 版本用于沙箱重放;初始化后的源码和基线存入项目快照。
34
+ 基础模板也单独按 `@james_sww/metaform-codebase-template@0.1.1` 分发,可安装到工具目录后用 `--codebase /path/to/node_modules/@james_sww/metaform-codebase-template` 指定。初始化底稿的完整类型随 CLI 发布在 `dist/application-design.d.ts`,语义区域类型在 `dist/generated/semantic-region-contract.d.ts`。固定 CLI、模板和 Registry 版本用于沙箱重放;初始化后的源码和基线存入项目快照。
35
35
 
36
36
  ## 维护仓库
37
37
 
@@ -1,10 +1,10 @@
1
1
  {
2
2
  "schemaVersion": 1,
3
3
  "name": "@james_sww/metaform-codebase-template",
4
- "version": "0.1.0",
4
+ "version": "0.1.1",
5
5
  "files": {
6
6
  "_gitignore": "184ad45835c68a6d3fd5100366678797c5fe4d2a2aa6548749039912376faf54",
7
- ".env.example": "5c15c4f0187d52019398f42ced14c7e6d54211ddb554c2142c4b8a9d250573c0",
7
+ ".env.example": "602ae0c89a09593ef560b5d1f7010439e228c7fb0dd7bbc69c9655cf82a8944f",
8
8
  ".metaform/asset-baselines/0551d7ee067550cd2757cf693414c5e180adbb5efe3af4f5f9b1242aa9cd788e": "0551d7ee067550cd2757cf693414c5e180adbb5efe3af4f5f9b1242aa9cd788e",
9
9
  ".metaform/asset-baselines/0e7bb494140c2c4118b919496a4246b26935367453282bd654fedecd2b16f1a5": "0e7bb494140c2c4118b919496a4246b26935367453282bd654fedecd2b16f1a5",
10
10
  ".metaform/asset-baselines/3d1a9a8a1f7ed83eaf3422d1497cac02b643fe1c470b5c5f357f3bd26c585a0f": "3d1a9a8a1f7ed83eaf3422d1497cac02b643fe1c470b5c5f357f3bd26c585a0f",
@@ -33,10 +33,11 @@
33
33
  "pnpm-lock.yaml": "46912c695ef4a2f351a7469aa26ab1312ccf6347b4d0aa2b075bf3a96632782b",
34
34
  "README.md": "d738a1bfbe9e9221f15e2bdcb46af9fae112afd0c1354bd9d45bdf3ae5205e38",
35
35
  "role-targets.json": "37517e5f3dc66819f61f5a7bb8ace1921282415f10551d2defa5c3eb0985b570",
36
- "src/components/common/error-boundary.tsx": "990d7a72a5634dc854f3acbe9b9d4aac8f13540ca0901be8dbc2f27d77a76f3e",
36
+ "src/components/common/empty-state.tsx": "6008a3193b715c5453eee3dba6ee20608fca3e6cf8bba9af774ba898a1890fea",
37
+ "src/components/common/error-boundary.tsx": "1fef1c92e27d8206448cb0e1840bfe81826a95fc58b1ec4c1e2f14462293bf5b",
37
38
  "src/components/common/semantic-region/contract.ts": "92cd18a919b549b4827f611c3a4157652c4a6ae034850da1254ca422693c759d",
38
39
  "src/components/common/semantic-region/semantic-region-scaffold.tsx": "567f039384fb23a20a4cd5e1d4fda56255abda6fc04d80b36c4bb6f6c040691b",
39
- "src/components/ui/alert.tsx": "d03dcae5cdb63c381c1144ca9a0c49ba0e46466967d7deb94662034042acb034",
40
+ "src/components/ui/alert.tsx": "9c380bb1703ba96fe873d5b3094153fa3402d305719e60aa733e4ab202ffddaa",
40
41
  "src/components/ui/avatar.tsx": "e9d4784c2ad5bceccdc4f2f19f367fdc37537a10e3f99f510e42c0226adfbf8f",
41
42
  "src/components/ui/badge.tsx": "bf9e1bbb252c1fa5da20a17eeee1ac163c7d3a0b6deff817d30ba04b766fb8a1",
42
43
  "src/components/ui/breadcrumb.tsx": "c75fcd3d9e8470188bc0dd4b27a2b26fff3ad42b9c9c534a953dc090ae2cba33",
@@ -59,16 +60,16 @@
59
60
  "src/components/ui/tabs.tsx": "e1df6e2f95ece373ca909c1d54b8ba8cf4c47dd425c1784bbb9a01c38dd0936b",
60
61
  "src/components/ui/tooltip.tsx": "5f56cd15afc07567f7b80b8b4d9e89da405e070a562583bbbc2414fd981af324",
61
62
  "src/contexts/toast-context.tsx": "a3af91f8915d7753ef15888997ba941d07459d4df3e3e6d58e25365143bf336f",
62
- "src/hooks/index.ts": "31e5708e471dbeb44413632535b8f846686de9be28c8ad18e2d930761de8b73b",
63
- "src/integrations/platform.ts": "2deb59e0f2938342cb66600b7310da0a67f8754ed291330a18034e819b448c4e",
63
+ "src/hooks/index.ts": "ddfe80f0fc8b0b49c0b31f27d9aadc4a54715b5ccee40996a205ecec36958b79",
64
+ "src/integrations/platform.ts": "6edb9755c91f6bf1f16815911739f64c4f45405948eaf0d7bbd5cd2fa939dbe9",
64
65
  "src/layouts/role-workspace-account.tsx": "3d1a9a8a1f7ed83eaf3422d1497cac02b643fe1c470b5c5f357f3bd26c585a0f",
65
66
  "src/layouts/role-workspace-icons.tsx": "4b8ea69ef28a9699c0c3b28e12590a7521f91aa1a4a3d618fc0778455d39cbcc",
66
67
  "src/layouts/role-workspace-routes.ts": "0551d7ee067550cd2757cf693414c5e180adbb5efe3af4f5f9b1242aa9cd788e",
67
68
  "src/layouts/role-workspace-shell.tsx": "bcc48c05cd912dad5373242ff699cdbec032c8ebb2de45a9df5de79a6daec59c",
68
69
  "src/layouts/role-workspace-types.ts": "b9e31158082ce71a2b3bdb904d9462619e3690735e73e138b1ce57f8f036347f",
69
- "src/lib/http-client.ts": "da19f0a16d8be3672573346d59c7242aa87440fc8b97b68a35867291f4da6af7",
70
+ "src/lib/http-client.ts": "a284532dd0bcc18aaf444b92e883ec77750515c1ba01626d8fa96c3e540d2e37",
70
71
  "src/lib/utils.ts": "4acbc7165a8d54738ff62b51414e772c08fe78434e524e6d8770180d3ba2925f",
71
- "src/main.tsx": "60221d67b63e9e685f2669f8deea9e4e56d5f285ea248d399e87fa69134b191f",
72
+ "src/main.tsx": "6fa2b2eb510ef94ca04b894c573a041419191f6896043f227eb160ab49bd6efa",
72
73
  "src/styles/index.css": "72f8f255c56d117bab6f2aaa53ce5a37aa9b2d5d085b321b9fcb4b4b983e15eb",
73
74
  "src/styles/styles.css": "b48c73f51ff3e148f20ad2c9dbd2847235e4fdf1cdb304d5e2feec9c2febd65e",
74
75
  "src/styles/theme-tokens.css": "0e7bb494140c2c4118b919496a4246b26935367453282bd654fedecd2b16f1a5",
@@ -1 +1,11 @@
1
- # 在打造前完成基础能力接入设计后填写;默认不配置业务服务地址。
1
+ # 应用配置
2
+ VITE_APP_TITLE=Metaform 应用
3
+
4
+ # API 配置
5
+ VITE_API_BASE_URL=/api
6
+
7
+ # 开发模式配置
8
+ VITE_USE_MOCK_API=true
9
+
10
+ # 环境标识
11
+ VITE_ENV=development
@@ -0,0 +1,52 @@
1
+ import { type ReactNode } from 'react';
2
+ import { InboxIcon } from 'lucide-react';
3
+
4
+ import { cn } from '../../lib/utils';
5
+ import { Button } from '../ui/button';
6
+
7
+ export interface EmptyStateProps {
8
+ icon?: ReactNode;
9
+ title: string;
10
+ description?: string;
11
+ action?: {
12
+ label: string;
13
+ onClick: () => void;
14
+ };
15
+ className?: string;
16
+ }
17
+
18
+ /**
19
+ * 空状态组件
20
+ * 当列表、表格或其他数据容器没有内容时显示
21
+ */
22
+ export function EmptyState({
23
+ icon,
24
+ title,
25
+ description,
26
+ action,
27
+ className,
28
+ }: EmptyStateProps) {
29
+ return (
30
+ <div
31
+ className={cn(
32
+ 'flex min-h-[400px] flex-col items-center justify-center gap-4 rounded-lg border border-dashed border-border bg-muted/30 p-8 text-center',
33
+ className,
34
+ )}
35
+ >
36
+ <div className="flex size-20 items-center justify-center rounded-full bg-muted text-muted-foreground">
37
+ {icon || <InboxIcon className="size-10" />}
38
+ </div>
39
+ <div className="space-y-2">
40
+ <h3 className="text-lg font-semibold text-foreground">{title}</h3>
41
+ {description && (
42
+ <p className="max-w-md text-sm text-muted-foreground">{description}</p>
43
+ )}
44
+ </div>
45
+ {action && (
46
+ <Button onClick={action.onClick} className="mt-2">
47
+ {action.label}
48
+ </Button>
49
+ )}
50
+ </div>
51
+ );
52
+ }
@@ -1,7 +1,7 @@
1
1
  import React, { Component, type ErrorInfo, type ReactNode } from 'react';
2
2
 
3
- import { Button } from '../components/ui/button';
4
- import { Card, CardContent, CardDescription, CardFooter, CardHeader, CardTitle } from '../components/ui/card';
3
+ import { Button } from '../ui/button';
4
+ import { Card, CardContent, CardDescription, CardFooter, CardHeader, CardTitle } from '../ui/card';
5
5
 
6
6
  interface ErrorBoundaryProps {
7
7
  children: ReactNode;
@@ -1,65 +1,63 @@
1
- import * as React from "react"
2
- import { cva, type VariantProps } from "class-variance-authority"
3
- import { cn } from "cn"
1
+ import * as React from "react";
2
+ import { cva, type VariantProps } from "class-variance-authority";
3
+
4
+ import { cn } from "../../lib/utils";
4
5
 
5
6
  const alertVariants = cva(
6
- "relative grid w-full grid-cols-[0_1fr] items-start gap-y-0.5 rounded-lg border px-4 py-3 text-sm has-[>svg]:grid-cols-[calc(var(--spacing)*4)_1fr] has-[>svg]:gap-x-3 [&>svg]:size-4 [&>svg]:translate-y-0.5 [&>svg]:text-current",
7
+ "relative w-full rounded-lg border p-4 [&>svg~*]:pl-7 [&>svg+div]:translate-y-[-3px] [&>svg]:absolute [&>svg]:left-4 [&>svg]:top-4 [&>svg]:text-foreground",
7
8
  {
8
9
  variants: {
9
10
  variant: {
10
- default: "bg-card text-card-foreground",
11
+ default: "bg-background text-foreground",
12
+ success:
13
+ "border-semantic-success/50 bg-semantic-success-soft text-semantic-success-foreground [&>svg]:text-semantic-success",
14
+ warning:
15
+ "border-semantic-warning/50 bg-semantic-warning-soft text-semantic-warning-foreground [&>svg]:text-semantic-warning",
11
16
  destructive:
12
- "bg-card text-destructive *:data-[slot=alert-description]:text-destructive/90 [&>svg]:text-current",
17
+ "border-semantic-danger/50 bg-semantic-danger-soft text-semantic-danger-foreground [&>svg]:text-semantic-danger",
13
18
  },
14
19
  },
15
20
  defaultVariants: {
16
21
  variant: "default",
17
22
  },
18
- }
19
- )
23
+ },
24
+ );
20
25
 
21
- function Alert({
22
- className,
23
- variant,
24
- ...props
25
- }: React.ComponentProps<"div"> & VariantProps<typeof alertVariants>) {
26
- return (
27
- <div
28
- data-slot="alert"
29
- role="alert"
30
- className={cn(alertVariants({ variant }), className)}
31
- {...props}
32
- />
33
- )
34
- }
26
+ const Alert = React.forwardRef<
27
+ HTMLDivElement,
28
+ React.HTMLAttributes<HTMLDivElement> & VariantProps<typeof alertVariants>
29
+ >(({ className, variant, ...props }, ref) => (
30
+ <div
31
+ ref={ref}
32
+ role="alert"
33
+ className={cn(alertVariants({ variant }), className)}
34
+ {...props}
35
+ />
36
+ ));
37
+ Alert.displayName = "Alert";
35
38
 
36
- function AlertTitle({ className, ...props }: React.ComponentProps<"div">) {
37
- return (
38
- <div
39
- data-slot="alert-title"
40
- className={cn(
41
- "col-start-2 line-clamp-1 min-h-4 font-medium tracking-tight",
42
- className
43
- )}
44
- {...props}
45
- />
46
- )
47
- }
39
+ const AlertTitle = React.forwardRef<
40
+ HTMLParagraphElement,
41
+ React.HTMLAttributes<HTMLHeadingElement>
42
+ >(({ className, ...props }, ref) => (
43
+ <h5
44
+ ref={ref}
45
+ className={cn("mb-1 font-medium leading-none tracking-tight", className)}
46
+ {...props}
47
+ />
48
+ ));
49
+ AlertTitle.displayName = "AlertTitle";
48
50
 
49
- function AlertDescription({
50
- className,
51
- ...props
52
- }: React.ComponentProps<"div">) {
53
- return (
54
- <div
55
- data-slot="alert-description"
56
- className={cn(
57
- "col-start-2 grid justify-items-start gap-1 text-sm text-muted-foreground [&_p]:leading-relaxed",
58
- className
59
- )}
60
- {...props}
61
- />
62
- )
63
- }
51
+ const AlertDescription = React.forwardRef<
52
+ HTMLParagraphElement,
53
+ React.HTMLAttributes<HTMLParagraphElement>
54
+ >(({ className, ...props }, ref) => (
55
+ <div
56
+ ref={ref}
57
+ className={cn("text-sm [&_p]:leading-relaxed", className)}
58
+ {...props}
59
+ />
60
+ ));
61
+ AlertDescription.displayName = "AlertDescription";
64
62
 
65
- export { Alert, AlertTitle, AlertDescription }
63
+ export { Alert, AlertTitle, AlertDescription };
@@ -166,8 +166,8 @@ export function useMediaQuery(query: string): boolean {
166
166
  */
167
167
  export function useClickOutside<T extends HTMLElement = HTMLElement>(
168
168
  handler: () => void,
169
- ): React.RefObject<T> {
170
- const ref = useRef<T>(null);
169
+ ): React.RefObject<T | null> {
170
+ const ref = useRef<T | null>(null);
171
171
 
172
172
  useEffect(() => {
173
173
  const listener = (event: MouseEvent | TouchEvent) => {
@@ -1,6 +1,70 @@
1
- // 基础能力设计的扩展点;不提供默认登录流程或虚构 API。
1
+ import { httpClient } from '../lib/http-client';
2
+
3
+ /**
4
+ * 平台集成接口
5
+ * 提供统一的认证、查询和操作能力
6
+ */
2
7
  export interface PlatformIntegration {
3
8
  getSession(): Promise<{ actorId: string } | null>;
4
9
  query<T>(operation: string, input: unknown): Promise<T>;
5
10
  execute<T>(operation: string, input: unknown): Promise<T>;
6
11
  }
12
+
13
+ /**
14
+ * 默认平台集成实现
15
+ * 使用 HTTP 客户端与后端通信
16
+ */
17
+ class DefaultPlatformIntegration implements PlatformIntegration {
18
+ async getSession(): Promise<{ actorId: string } | null> {
19
+ try {
20
+ const response = await httpClient.get<{ actorId: string }>('/auth/session');
21
+ return response.data;
22
+ } catch (error) {
23
+ console.warn('Failed to get session:', error);
24
+ return null;
25
+ }
26
+ }
27
+
28
+ async query<T>(operation: string, input: unknown): Promise<T> {
29
+ const response = await httpClient.post<T>('/query', {
30
+ operation,
31
+ input,
32
+ });
33
+ return response.data;
34
+ }
35
+
36
+ async execute<T>(operation: string, input: unknown): Promise<T> {
37
+ const response = await httpClient.post<T>('/execute', {
38
+ operation,
39
+ input,
40
+ });
41
+ return response.data;
42
+ }
43
+ }
44
+
45
+ /**
46
+ * Mock 平台集成(用于开发和测试)
47
+ */
48
+ class MockPlatformIntegration implements PlatformIntegration {
49
+ async getSession(): Promise<{ actorId: string } | null> {
50
+ // 模拟已登录用户
51
+ return { actorId: 'mock-user-001' };
52
+ }
53
+
54
+ async query<T>(operation: string, input: unknown): Promise<T> {
55
+ console.log('[Mock Query]', operation, input);
56
+ // 返回模拟数据
57
+ return {} as T;
58
+ }
59
+
60
+ async execute<T>(operation: string, input: unknown): Promise<T> {
61
+ console.log('[Mock Execute]', operation, input);
62
+ return {} as T;
63
+ }
64
+ }
65
+
66
+ // 根据环境变量选择实现
67
+ const useMock = (import.meta as { env?: { VITE_USE_MOCK_API?: string } }).env?.VITE_USE_MOCK_API === 'true';
68
+ export const platform: PlatformIntegration = useMock
69
+ ? new MockPlatformIntegration()
70
+ : new DefaultPlatformIntegration();
@@ -228,7 +228,7 @@ export class HttpClient {
228
228
 
229
229
  // 创建默认实例
230
230
  export const httpClient = new HttpClient({
231
- baseURL: import.meta.env.VITE_API_BASE_URL || '/api',
231
+ baseURL: (import.meta as { env?: { VITE_API_BASE_URL?: string } }).env?.VITE_API_BASE_URL || '/api',
232
232
  onRequest: async (config) => {
233
233
  // 自动添加认证 token
234
234
  const token = localStorage.getItem('auth_token');
@@ -1,6 +1,16 @@
1
1
  import { createRoot } from "react-dom/client";
2
+ import { Toaster } from "sonner";
2
3
 
4
+ import { ErrorBoundary } from "./components/common/error-boundary";
5
+ import { ToastProvider } from "./contexts/toast-context";
3
6
  import { DefaultWorkspace } from "./workspace/default-workspace";
4
7
  import "./styles/index.css";
5
8
 
6
- createRoot(document.getElementById("root")!).render(<DefaultWorkspace />);
9
+ createRoot(document.getElementById("root")!).render(
10
+ <ErrorBoundary>
11
+ <ToastProvider>
12
+ <DefaultWorkspace />
13
+ <Toaster position="top-right" richColors closeButton />
14
+ </ToastProvider>
15
+ </ErrorBoundary>,
16
+ );
package/dist/cli.js CHANGED
@@ -96,7 +96,7 @@ export async function runCLI(argv, io) {
96
96
  else if (cmd === 'init')
97
97
  output = await initProject({
98
98
  projectRoot: root,
99
- templateVersion: options.get('template') ?? '0.1.0',
99
+ templateVersion: options.get('template'),
100
100
  codebaseRoot: options.get('codebase'),
101
101
  });
102
102
  else if (cmd === 'reconcile')
@@ -2,7 +2,7 @@ import { type RegistryRelease } from './contracts.js';
2
2
  export declare function initProject(input: {
3
3
  projectRoot: string;
4
4
  release?: RegistryRelease;
5
- templateVersion: string;
5
+ templateVersion?: string;
6
6
  codebaseRoot?: string;
7
7
  }): Promise<{
8
8
  codebase: {
package/dist/template.js CHANGED
@@ -22,7 +22,7 @@ export async function initProject(input) {
22
22
  Array.isArray(manifest.files) ||
23
23
  typeof manifest.files !== 'object')
24
24
  throw new DistributionError('invalid_codebase');
25
- if (manifest.version !== input.templateVersion)
25
+ if (input.templateVersion && manifest.version !== input.templateVersion)
26
26
  throw new DistributionError('template_version');
27
27
  const template = validateTargetPath(packageRoot, 'template');
28
28
  const actual = await projectFiles(template);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@james_sww/metaform-asset-distribution",
3
- "version": "0.1.0",
3
+ "version": "0.1.1",
4
4
  "type": "module",
5
5
  "bin": {
6
6
  "metaform-assets": "./dist/bin.js"