用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
直接命令不会经过审查 Prompt;运行前请先检查来源。
npx skills add https://github.com/carrot-foundation/schemas --skill create-schema命令会保持在同一行。复制前请横向滚动并检查完整内容。
想先保存到本地?可下载 SkillsMP 当前能够提供的文件。
正在显示 SKILL.md
基于 SOC 职业分类
| name | create-schema |
| description | Use when scaffolding a new schema type directory with data, attributes, tests, and index |
Scaffold a new IPFS schema type directory in the schemas package with all required files following project conventions.
For a new schema type called {type} (e.g., mass-id, credit-audit):
src/
{type}/
{type}.data.schema.ts # Type-specific data fields
{type}.attributes.ts # NFT attribute definitions
{type}.schema.ts # Main schema extending NftIpfsSchema
index.ts # Barrel exports
__tests__/
{type}.schema.spec.ts # Comprehensive tests
mkdir -p src/{type}/__tests__
{type}.data.schema.ts)Define the type-specific data payload using z.strictObject(). Every field MUST have .meta() with at least a description.
import { z } from 'zod';
export const {TypeName}DataSchema = z
.strictObject({
field_name: z
.string()
.meta({
description: 'Human-readable description of this field',
examples: ['example-value'],
}),
numeric_field: z
.number()
.positive()
.meta({
description: 'Description of the numeric field',
examples: [42],
}),
optional_field: z
.string()
.optional()
.meta({
description: 'Description of the optional field',
examples: ['optional-value'],
}),
})
.meta({
description: 'Type-specific data for {type} schema',
});
export type {TypeName}Data = z.infer<typeof {TypeName}DataSchema>;
Naming conventions:
PascalCase + DataSchema suffix (e.g., MassIdDataSchema)PascalCase + Data suffix (e.g., MassIdData)snake_case (e.g., batch_size, processing_date){type}.attributes.ts)Define NFT attributes as a typed array:
import type { NftAttribute } from '../shared/nft-attribute.schema';
export const {typeName}Attributes: NftAttribute[] = [
{
trait_type: 'Attribute Name',
value: 'default_value',
},
{
trait_type: 'Another Attribute',
value: 'another_value',
},
];
Conventions:
trait_type uses Title Case for user-facing labelsvalue matches the expected runtime value type{type}.schema.ts)Extend NftIpfsSchema using .safeExtend():
import { z } from 'zod';
import { NftIpfsSchema } from '../shared/nft-ipfs.schema';
import { NftAttributeSchema } from '../shared/nft-attribute.schema';
import { {TypeName}DataSchema } from './{type}.data.schema';
import { {typeName}Attributes } from './{type}.attributes';
export const {TypeName}Schema = NftIpfsSchema.safeExtend({
data: {TypeName}DataSchema.meta({
description: 'Type-specific data for {type}',
}),
attributes: z
.array(NftAttributeSchema)
.default({typeName}Attributes)
.meta({
description: 'NFT attributes for {type}',
}),
}).meta({
description: '{TypeName} IPFS schema for NFT metadata',
});
export type {TypeName} = z.infer<typeof {TypeName}>;
Important: Use .safeExtend() (not .extend()) to preserve strict object validation from the base schema.
index.ts)export { {TypeName}DataSchema, type {TypeName}Data } from './{type}.data.schema';
export { {typeName}Attributes } from './{type}.attributes';
export { {TypeName}Schema, type {TypeName} } from './{type}.schema';
__tests__/{type}.schema.spec.ts)Write comprehensive tests targeting 100% coverage:
import { describe, expect, it } from 'vitest';
import { {TypeName}Schema } from '../{type}.schema';
import { {TypeName}DataSchema } from '../{type}.data.schema';
describe('{TypeName}Schema', () => {
describe('valid inputs', () => {
it('should parse a complete valid input', () => {
const input = {
// ... all required fields with valid values
};
const result = {TypeName}Schema.safeParse(input);
expect(result.success).toBe(true);
});
it.each([
['scenario 1', { /* valid variation 1 */ }],
['scenario 2', { /* valid variation 2 */ }],
])('should parse valid input: %s', (_label, input) => {
const result = {TypeName}Schema.safeParse(input);
expect(result.success).toBe(true);
});
});
(, {
(, {
result = {}.({});
(result.).();
});
(, {
input = {
: ,
};
result = {}.(input);
(result.).();
});
(, {
input = {
: ,
};
result = {}.(input);
(result.).();
});
});
(, {
(, {
input = {
};
result = {}.(input);
(result.).();
});
});
});
(, {
});
Test patterns:
.safeParse() for all validation (never .parse() in tests)it.each for table-driven tests with multiple valid/invalid inputssrc/test-utils/fixtures/ when availableAdd the new type to src/index.ts:
export * from './{type}';
pnpm check
This will:
| Concept | Convention | Example |
|---|---|---|
| Directory | kebab-case | mass-id/ |
| File names | kebab-case with suffix | mass-id.data.schema.ts |
| Schema variables | PascalCase + Schema | MassIdDataSchema |
| Type exports | PascalCase | MassIdData |
| Properties | snake_case | batch_size |
| Attribute trait_type | Title Case | Batch Size |
| Enum values (user-facing) | Title Case | Recycling Center |
| Enum values (technical) | lowercase | pending |