@spwig/theme-cli 1.0.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 +278 -0
- package/dist/cli.d.ts +3 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +99 -0
- package/dist/cli.js.map +1 -0
- package/dist/commands/component.d.ts +13 -0
- package/dist/commands/component.d.ts.map +1 -0
- package/dist/commands/component.js +229 -0
- package/dist/commands/component.js.map +1 -0
- package/dist/commands/init.d.ts +13 -0
- package/dist/commands/init.d.ts.map +1 -0
- package/dist/commands/init.js +249 -0
- package/dist/commands/init.js.map +1 -0
- package/dist/commands/package.d.ts +12 -0
- package/dist/commands/package.d.ts.map +1 -0
- package/dist/commands/package.js +320 -0
- package/dist/commands/package.js.map +1 -0
- package/dist/commands/validate.d.ts +10 -0
- package/dist/commands/validate.d.ts.map +1 -0
- package/dist/commands/validate.js +204 -0
- package/dist/commands/validate.js.map +1 -0
- package/dist/index.d.ts +13 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +9 -0
- package/dist/index.js.map +1 -0
- package/dist/schemas/component_manifest_schema.json +221 -0
- package/dist/schemas/theme_manifest_schema.json +267 -0
- package/dist/templates/components/blank.template.html.template +4 -0
- package/dist/templates/components/footer.manifest.json.template +11 -0
- package/dist/templates/components/footer.template.html.template +36 -0
- package/dist/templates/components/header.manifest.json.template +11 -0
- package/dist/templates/components/header.schema.json.template +23 -0
- package/dist/templates/components/header.template.html.template +39 -0
- package/dist/templates/components/schema.json.template +15 -0
- package/dist/templates/components/section.manifest.json.template +11 -0
- package/dist/templates/components/section.template.html.template +13 -0
- package/dist/templates/components/utility.manifest.json.template +11 -0
- package/dist/templates/theme/README.md.template +64 -0
- package/dist/templates/theme/design_tokens.json.template +66 -0
- package/dist/templates/theme/manifest.json.template +40 -0
- package/dist/utils/file-system.d.ts +49 -0
- package/dist/utils/file-system.d.ts.map +1 -0
- package/dist/utils/file-system.js +115 -0
- package/dist/utils/file-system.js.map +1 -0
- package/dist/utils/validation.d.ts +40 -0
- package/dist/utils/validation.d.ts.map +1 -0
- package/dist/utils/validation.js +98 -0
- package/dist/utils/validation.js.map +1 -0
- package/package.json +62 -0
- package/schemas/component_manifest_schema.json +221 -0
- package/schemas/theme_manifest_schema.json +267 -0
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
import fs from 'fs-extra';
|
|
2
|
+
import path from 'path';
|
|
3
|
+
/**
|
|
4
|
+
* Check if a directory exists
|
|
5
|
+
*/
|
|
6
|
+
export async function directoryExists(dirPath) {
|
|
7
|
+
try {
|
|
8
|
+
const stats = await fs.stat(dirPath);
|
|
9
|
+
return stats.isDirectory();
|
|
10
|
+
}
|
|
11
|
+
catch {
|
|
12
|
+
return false;
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* Check if a file exists
|
|
17
|
+
*/
|
|
18
|
+
export async function fileExists(filePath) {
|
|
19
|
+
try {
|
|
20
|
+
const stats = await fs.stat(filePath);
|
|
21
|
+
return stats.isFile();
|
|
22
|
+
}
|
|
23
|
+
catch {
|
|
24
|
+
return false;
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* Ensure directory exists, create if it doesn't
|
|
29
|
+
*/
|
|
30
|
+
export async function ensureDirectory(dirPath) {
|
|
31
|
+
await fs.ensureDir(dirPath);
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* Read JSON file
|
|
35
|
+
*/
|
|
36
|
+
export async function readJSON(filePath) {
|
|
37
|
+
const content = await fs.readFile(filePath, 'utf-8');
|
|
38
|
+
return JSON.parse(content);
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* Write JSON file with formatting
|
|
42
|
+
*/
|
|
43
|
+
export async function writeJSON(filePath, data) {
|
|
44
|
+
await fs.writeJSON(filePath, data, { spaces: 2 });
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* Copy file
|
|
48
|
+
*/
|
|
49
|
+
export async function copyFile(source, destination) {
|
|
50
|
+
await fs.copy(source, destination);
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* Copy directory recursively
|
|
54
|
+
*/
|
|
55
|
+
export async function copyDirectory(source, destination) {
|
|
56
|
+
await fs.copy(source, destination);
|
|
57
|
+
}
|
|
58
|
+
/**
|
|
59
|
+
* Read template file and replace placeholders
|
|
60
|
+
*/
|
|
61
|
+
export async function readTemplate(templatePath, variables) {
|
|
62
|
+
let content = await fs.readFile(templatePath, 'utf-8');
|
|
63
|
+
// Replace {{variable}} placeholders
|
|
64
|
+
for (const [key, value] of Object.entries(variables)) {
|
|
65
|
+
const regex = new RegExp(`{{${key}}}`, 'g');
|
|
66
|
+
content = content.replace(regex, value);
|
|
67
|
+
}
|
|
68
|
+
return content;
|
|
69
|
+
}
|
|
70
|
+
/**
|
|
71
|
+
* Write file from template
|
|
72
|
+
*/
|
|
73
|
+
export async function writeFromTemplate(templatePath, outputPath, variables) {
|
|
74
|
+
const content = await readTemplate(templatePath, variables);
|
|
75
|
+
await fs.writeFile(outputPath, content, 'utf-8');
|
|
76
|
+
}
|
|
77
|
+
/**
|
|
78
|
+
* Get all files in directory recursively
|
|
79
|
+
*/
|
|
80
|
+
export async function getFilesRecursively(dirPath) {
|
|
81
|
+
const files = [];
|
|
82
|
+
async function scan(currentPath) {
|
|
83
|
+
const entries = await fs.readdir(currentPath, { withFileTypes: true });
|
|
84
|
+
for (const entry of entries) {
|
|
85
|
+
const fullPath = path.join(currentPath, entry.name);
|
|
86
|
+
if (entry.isDirectory()) {
|
|
87
|
+
await scan(fullPath);
|
|
88
|
+
}
|
|
89
|
+
else {
|
|
90
|
+
files.push(fullPath);
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
await scan(dirPath);
|
|
95
|
+
return files;
|
|
96
|
+
}
|
|
97
|
+
/**
|
|
98
|
+
* Calculate file size
|
|
99
|
+
*/
|
|
100
|
+
export async function getFileSize(filePath) {
|
|
101
|
+
const stats = await fs.stat(filePath);
|
|
102
|
+
return stats.size;
|
|
103
|
+
}
|
|
104
|
+
/**
|
|
105
|
+
* Calculate directory size
|
|
106
|
+
*/
|
|
107
|
+
export async function getDirectorySize(dirPath) {
|
|
108
|
+
const files = await getFilesRecursively(dirPath);
|
|
109
|
+
let totalSize = 0;
|
|
110
|
+
for (const file of files) {
|
|
111
|
+
totalSize += await getFileSize(file);
|
|
112
|
+
}
|
|
113
|
+
return totalSize;
|
|
114
|
+
}
|
|
115
|
+
//# sourceMappingURL=file-system.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"file-system.js","sourceRoot":"","sources":["../../src/utils/file-system.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Validation utilities for theme names, versions, etc.
|
|
3
|
+
*/
|
|
4
|
+
/**
|
|
5
|
+
* Validate theme name (lowercase, hyphens, alphanumeric)
|
|
6
|
+
*/
|
|
7
|
+
export declare function isValidThemeName(name: string): boolean;
|
|
8
|
+
/**
|
|
9
|
+
* Validate component name (lowercase, underscores/hyphens, alphanumeric)
|
|
10
|
+
*/
|
|
11
|
+
export declare function isValidComponentName(name: string): boolean;
|
|
12
|
+
/**
|
|
13
|
+
* Validate semantic version (x.y.z)
|
|
14
|
+
*/
|
|
15
|
+
export declare function isValidVersion(version: string): boolean;
|
|
16
|
+
/**
|
|
17
|
+
* Convert string to kebab-case (for theme names)
|
|
18
|
+
*/
|
|
19
|
+
export declare function toKebabCase(str: string): string;
|
|
20
|
+
/**
|
|
21
|
+
* Convert string to snake_case (for component names)
|
|
22
|
+
*/
|
|
23
|
+
export declare function toSnakeCase(str: string): string;
|
|
24
|
+
/**
|
|
25
|
+
* Convert kebab-case or snake_case to Title Case
|
|
26
|
+
*/
|
|
27
|
+
export declare function toTitleCase(str: string): string;
|
|
28
|
+
/**
|
|
29
|
+
* Validate email address
|
|
30
|
+
*/
|
|
31
|
+
export declare function isValidEmail(email: string): boolean;
|
|
32
|
+
/**
|
|
33
|
+
* Get error message for invalid theme name
|
|
34
|
+
*/
|
|
35
|
+
export declare function getThemeNameError(name: string): string | null;
|
|
36
|
+
/**
|
|
37
|
+
* Get error message for invalid component name
|
|
38
|
+
*/
|
|
39
|
+
export declare function getComponentNameError(name: string): string | null;
|
|
40
|
+
//# sourceMappingURL=validation.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"validation.d.ts","sourceRoot":"","sources":["../../src/utils/validation.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH;;GAEG;AACH,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAGtD;AAED;;GAEG;AACH,wBAAgB,oBAAoB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAG1D;AAED;;GAEG;AACH,wBAAgB,cAAc,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAGvD;AAED;;GAEG;AACH,wBAAgB,WAAW,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAM/C;AAED;;GAEG;AACH,wBAAgB,WAAW,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAM/C;AAED;;GAEG;AACH,wBAAgB,WAAW,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAM/C;AAED;;GAEG;AACH,wBAAgB,YAAY,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAGnD;AAED;;GAEG;AACH,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAc7D;AAED;;GAEG;AACH,wBAAgB,qBAAqB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAcjE"}
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Validation utilities for theme names, versions, etc.
|
|
3
|
+
*/
|
|
4
|
+
/**
|
|
5
|
+
* Validate theme name (lowercase, hyphens, alphanumeric)
|
|
6
|
+
*/
|
|
7
|
+
export function isValidThemeName(name) {
|
|
8
|
+
const pattern = /^[a-z][a-z0-9-]*$/;
|
|
9
|
+
return pattern.test(name) && name.length >= 2 && name.length <= 50;
|
|
10
|
+
}
|
|
11
|
+
/**
|
|
12
|
+
* Validate component name (lowercase, underscores/hyphens, alphanumeric)
|
|
13
|
+
*/
|
|
14
|
+
export function isValidComponentName(name) {
|
|
15
|
+
const pattern = /^[a-z][a-z0-9_-]*$/;
|
|
16
|
+
return pattern.test(name) && name.length >= 2 && name.length <= 50;
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* Validate semantic version (x.y.z)
|
|
20
|
+
*/
|
|
21
|
+
export function isValidVersion(version) {
|
|
22
|
+
const pattern = /^(0|[1-9]\d*)\.(0|[1-9]\d*)\.(0|[1-9]\d*)$/;
|
|
23
|
+
return pattern.test(version);
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* Convert string to kebab-case (for theme names)
|
|
27
|
+
*/
|
|
28
|
+
export function toKebabCase(str) {
|
|
29
|
+
return str
|
|
30
|
+
.toLowerCase()
|
|
31
|
+
.replace(/[^a-z0-9-]/g, '-')
|
|
32
|
+
.replace(/-+/g, '-')
|
|
33
|
+
.replace(/^-|-$/g, '');
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* Convert string to snake_case (for component names)
|
|
37
|
+
*/
|
|
38
|
+
export function toSnakeCase(str) {
|
|
39
|
+
return str
|
|
40
|
+
.toLowerCase()
|
|
41
|
+
.replace(/[^a-z0-9_]/g, '_')
|
|
42
|
+
.replace(/_+/g, '_')
|
|
43
|
+
.replace(/^_|_$/g, '');
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* Convert kebab-case or snake_case to Title Case
|
|
47
|
+
*/
|
|
48
|
+
export function toTitleCase(str) {
|
|
49
|
+
return str
|
|
50
|
+
.replace(/[-_]/g, ' ')
|
|
51
|
+
.split(' ')
|
|
52
|
+
.map(word => word.charAt(0).toUpperCase() + word.slice(1))
|
|
53
|
+
.join(' ');
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* Validate email address
|
|
57
|
+
*/
|
|
58
|
+
export function isValidEmail(email) {
|
|
59
|
+
const pattern = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
|
|
60
|
+
return pattern.test(email);
|
|
61
|
+
}
|
|
62
|
+
/**
|
|
63
|
+
* Get error message for invalid theme name
|
|
64
|
+
*/
|
|
65
|
+
export function getThemeNameError(name) {
|
|
66
|
+
if (name.length < 2) {
|
|
67
|
+
return 'Theme name must be at least 2 characters';
|
|
68
|
+
}
|
|
69
|
+
if (name.length > 50) {
|
|
70
|
+
return 'Theme name must be at most 50 characters';
|
|
71
|
+
}
|
|
72
|
+
if (!/^[a-z]/.test(name)) {
|
|
73
|
+
return 'Theme name must start with a lowercase letter';
|
|
74
|
+
}
|
|
75
|
+
if (!/^[a-z][a-z0-9-]*$/.test(name)) {
|
|
76
|
+
return 'Theme name can only contain lowercase letters, numbers, and hyphens';
|
|
77
|
+
}
|
|
78
|
+
return null;
|
|
79
|
+
}
|
|
80
|
+
/**
|
|
81
|
+
* Get error message for invalid component name
|
|
82
|
+
*/
|
|
83
|
+
export function getComponentNameError(name) {
|
|
84
|
+
if (name.length < 2) {
|
|
85
|
+
return 'Component name must be at least 2 characters';
|
|
86
|
+
}
|
|
87
|
+
if (name.length > 50) {
|
|
88
|
+
return 'Component name must be at most 50 characters';
|
|
89
|
+
}
|
|
90
|
+
if (!/^[a-z]/.test(name)) {
|
|
91
|
+
return 'Component name must start with a lowercase letter';
|
|
92
|
+
}
|
|
93
|
+
if (!/^[a-z][a-z0-9_-]*$/.test(name)) {
|
|
94
|
+
return 'Component name can only contain lowercase letters, numbers, underscores, and hyphens';
|
|
95
|
+
}
|
|
96
|
+
return null;
|
|
97
|
+
}
|
|
98
|
+
//# sourceMappingURL=validation.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"validation.js","sourceRoot":"","sources":["../../src/utils/validation.ts"],"names":[],"mappings":"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"}
|
package/package.json
ADDED
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@spwig/theme-cli",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"type": "module",
|
|
5
|
+
"description": "Spwig Theme SDK CLI",
|
|
6
|
+
"main": "dist/index.js",
|
|
7
|
+
"types": "dist/index.d.ts",
|
|
8
|
+
"bin": {
|
|
9
|
+
"spwig": "./dist/cli.js"
|
|
10
|
+
},
|
|
11
|
+
"files": [
|
|
12
|
+
"dist",
|
|
13
|
+
"schemas",
|
|
14
|
+
"README.md"
|
|
15
|
+
],
|
|
16
|
+
"scripts": {
|
|
17
|
+
"build": "tsc && chmod +x dist/cli.js && npm run copy-assets",
|
|
18
|
+
"copy-assets": "cp -r src/templates dist/ && cp -r schemas dist/",
|
|
19
|
+
"dev": "tsc --watch",
|
|
20
|
+
"test": "jest",
|
|
21
|
+
"test:watch": "jest --watch",
|
|
22
|
+
"lint": "eslint src --ext .ts",
|
|
23
|
+
"format": "prettier --write 'src/**/*.ts'",
|
|
24
|
+
"clean": "rm -rf dist"
|
|
25
|
+
},
|
|
26
|
+
"keywords": [
|
|
27
|
+
"spwig",
|
|
28
|
+
"theme",
|
|
29
|
+
"cli",
|
|
30
|
+
"ecommerce"
|
|
31
|
+
],
|
|
32
|
+
"repository": {
|
|
33
|
+
"type": "git",
|
|
34
|
+
"url": "https://github.com/spwig/theme-sdk.git",
|
|
35
|
+
"directory": "packages/cli"
|
|
36
|
+
},
|
|
37
|
+
"author": "Spwig",
|
|
38
|
+
"license": "Apache-2.0",
|
|
39
|
+
"dependencies": {
|
|
40
|
+
"@spwig/theme-validator": "^1.0.0",
|
|
41
|
+
"archiver": "^6.0.1",
|
|
42
|
+
"chalk": "^5.3.0",
|
|
43
|
+
"commander": "^11.1.0",
|
|
44
|
+
"express": "^4.18.2",
|
|
45
|
+
"fs-extra": "^11.2.0",
|
|
46
|
+
"inquirer": "^9.2.12",
|
|
47
|
+
"ora": "^7.0.1"
|
|
48
|
+
},
|
|
49
|
+
"devDependencies": {
|
|
50
|
+
"@types/archiver": "^6.0.2",
|
|
51
|
+
"@types/express": "^4.17.21",
|
|
52
|
+
"@types/fs-extra": "^11.0.4",
|
|
53
|
+
"@types/inquirer": "^9.0.7",
|
|
54
|
+
"@types/node": "^20.10.0",
|
|
55
|
+
"jest": "^29.7.0",
|
|
56
|
+
"ts-jest": "^29.1.1",
|
|
57
|
+
"typescript": "^5.3.0"
|
|
58
|
+
},
|
|
59
|
+
"engines": {
|
|
60
|
+
"node": ">=18.0.0"
|
|
61
|
+
}
|
|
62
|
+
}
|
|
@@ -0,0 +1,221 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "http://json-schema.org/draft-07/schema#",
|
|
3
|
+
"title": "Component Manifest Schema",
|
|
4
|
+
"description": "Schema for Spwig component package manifests",
|
|
5
|
+
"type": "object",
|
|
6
|
+
"required": [
|
|
7
|
+
"name",
|
|
8
|
+
"version",
|
|
9
|
+
"display_name",
|
|
10
|
+
"description",
|
|
11
|
+
"author",
|
|
12
|
+
"tier_compatibility",
|
|
13
|
+
"regions"
|
|
14
|
+
],
|
|
15
|
+
"properties": {
|
|
16
|
+
"name": {
|
|
17
|
+
"type": "string",
|
|
18
|
+
"pattern": "^[a-z][a-z0-9_]*$",
|
|
19
|
+
"minLength": 2,
|
|
20
|
+
"maxLength": 50,
|
|
21
|
+
"description": "Component identifier (lowercase, alphanumeric with underscores)"
|
|
22
|
+
},
|
|
23
|
+
"version": {
|
|
24
|
+
"type": "string",
|
|
25
|
+
"pattern": "^(0|[1-9]\\d*)\\.(0|[1-9]\\d*)\\.(0|[1-9]\\d*)$",
|
|
26
|
+
"description": "Semantic version (e.g., 1.0.0)"
|
|
27
|
+
},
|
|
28
|
+
"display_name": {
|
|
29
|
+
"type": "string",
|
|
30
|
+
"minLength": 1,
|
|
31
|
+
"maxLength": 100,
|
|
32
|
+
"description": "Human-readable component name"
|
|
33
|
+
},
|
|
34
|
+
"description": {
|
|
35
|
+
"type": "string",
|
|
36
|
+
"minLength": 10,
|
|
37
|
+
"maxLength": 500,
|
|
38
|
+
"description": "Component description for marketplace listing"
|
|
39
|
+
},
|
|
40
|
+
"author": {
|
|
41
|
+
"type": "string",
|
|
42
|
+
"minLength": 1,
|
|
43
|
+
"maxLength": 100,
|
|
44
|
+
"description": "Component author/vendor name"
|
|
45
|
+
},
|
|
46
|
+
"tier_compatibility": {
|
|
47
|
+
"type": "array",
|
|
48
|
+
"minItems": 1,
|
|
49
|
+
"uniqueItems": true,
|
|
50
|
+
"items": {
|
|
51
|
+
"type": "string",
|
|
52
|
+
"enum": ["A", "B", "C"]
|
|
53
|
+
},
|
|
54
|
+
"description": "Security tiers this component is compatible with"
|
|
55
|
+
},
|
|
56
|
+
"regions": {
|
|
57
|
+
"type": "array",
|
|
58
|
+
"minItems": 1,
|
|
59
|
+
"uniqueItems": true,
|
|
60
|
+
"items": {
|
|
61
|
+
"type": "string",
|
|
62
|
+
"pattern": "^[a-z][a-z0-9_]*$"
|
|
63
|
+
},
|
|
64
|
+
"description": "Page regions this component can be placed in"
|
|
65
|
+
},
|
|
66
|
+
"props_schema": {
|
|
67
|
+
"type": "object",
|
|
68
|
+
"description": "JSON Schema defining component properties",
|
|
69
|
+
"required": ["type", "properties"],
|
|
70
|
+
"properties": {
|
|
71
|
+
"type": {
|
|
72
|
+
"const": "object"
|
|
73
|
+
},
|
|
74
|
+
"properties": {
|
|
75
|
+
"type": "object"
|
|
76
|
+
},
|
|
77
|
+
"required": {
|
|
78
|
+
"type": "array",
|
|
79
|
+
"items": {
|
|
80
|
+
"type": "string"
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
},
|
|
85
|
+
"assets": {
|
|
86
|
+
"type": "object",
|
|
87
|
+
"properties": {
|
|
88
|
+
"css": {
|
|
89
|
+
"type": "array",
|
|
90
|
+
"items": {
|
|
91
|
+
"type": "string",
|
|
92
|
+
"pattern": "^assets/.*\\.css$"
|
|
93
|
+
},
|
|
94
|
+
"description": "CSS files relative to component root"
|
|
95
|
+
},
|
|
96
|
+
"js": {
|
|
97
|
+
"type": "array",
|
|
98
|
+
"items": {
|
|
99
|
+
"type": "string",
|
|
100
|
+
"pattern": "^assets/.*\\.js$"
|
|
101
|
+
},
|
|
102
|
+
"description": "JavaScript files relative to component root"
|
|
103
|
+
},
|
|
104
|
+
"images": {
|
|
105
|
+
"type": "array",
|
|
106
|
+
"items": {
|
|
107
|
+
"type": "string",
|
|
108
|
+
"pattern": "^assets/.*\\.(png|jpg|jpeg|svg|gif|webp)$"
|
|
109
|
+
},
|
|
110
|
+
"description": "Image files relative to component root"
|
|
111
|
+
}
|
|
112
|
+
},
|
|
113
|
+
"additionalProperties": false
|
|
114
|
+
},
|
|
115
|
+
"dependencies": {
|
|
116
|
+
"type": "array",
|
|
117
|
+
"items": {
|
|
118
|
+
"type": "object",
|
|
119
|
+
"required": ["name", "min_version"],
|
|
120
|
+
"properties": {
|
|
121
|
+
"name": {
|
|
122
|
+
"type": "string",
|
|
123
|
+
"pattern": "^[a-z][a-z0-9_]*$"
|
|
124
|
+
},
|
|
125
|
+
"min_version": {
|
|
126
|
+
"type": "string",
|
|
127
|
+
"pattern": "^(0|[1-9]\\d*)\\.(0|[1-9]\\d*)\\.(0|[1-9]\\d*)$"
|
|
128
|
+
},
|
|
129
|
+
"max_version": {
|
|
130
|
+
"type": "string",
|
|
131
|
+
"pattern": "^(0|[1-9]\\d*)\\.(0|[1-9]\\d*)\\.(0|[1-9]\\d*)$"
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
},
|
|
135
|
+
"description": "Component dependencies on other components"
|
|
136
|
+
},
|
|
137
|
+
"locales": {
|
|
138
|
+
"type": "array",
|
|
139
|
+
"items": {
|
|
140
|
+
"type": "string",
|
|
141
|
+
"pattern": "^[a-z]{2}(_[A-Z]{2})?$"
|
|
142
|
+
},
|
|
143
|
+
"description": "Supported locale codes (e.g., en, es, fr, en_US)"
|
|
144
|
+
},
|
|
145
|
+
"preview": {
|
|
146
|
+
"type": "string",
|
|
147
|
+
"pattern": "^preview\\.(png|jpg|jpeg|webp)$",
|
|
148
|
+
"description": "Preview image filename (recommended: 600x800px, max 5MB)"
|
|
149
|
+
},
|
|
150
|
+
"category": {
|
|
151
|
+
"type": "string",
|
|
152
|
+
"enum": [
|
|
153
|
+
"hero",
|
|
154
|
+
"header",
|
|
155
|
+
"footer",
|
|
156
|
+
"content",
|
|
157
|
+
"product",
|
|
158
|
+
"collection",
|
|
159
|
+
"cart",
|
|
160
|
+
"checkout",
|
|
161
|
+
"marketing",
|
|
162
|
+
"social",
|
|
163
|
+
"navigation",
|
|
164
|
+
"utility"
|
|
165
|
+
],
|
|
166
|
+
"description": "Component category for marketplace organization"
|
|
167
|
+
},
|
|
168
|
+
"tags": {
|
|
169
|
+
"type": "array",
|
|
170
|
+
"maxItems": 10,
|
|
171
|
+
"items": {
|
|
172
|
+
"type": "string",
|
|
173
|
+
"pattern": "^[a-z][a-z0-9-]*$",
|
|
174
|
+
"maxLength": 30
|
|
175
|
+
},
|
|
176
|
+
"description": "Searchable tags for marketplace"
|
|
177
|
+
},
|
|
178
|
+
"license": {
|
|
179
|
+
"type": "string",
|
|
180
|
+
"enum": ["MIT", "Apache-2.0", "GPL-3.0", "Proprietary"],
|
|
181
|
+
"default": "Proprietary",
|
|
182
|
+
"description": "Component license type"
|
|
183
|
+
},
|
|
184
|
+
"changelog": {
|
|
185
|
+
"type": "array",
|
|
186
|
+
"items": {
|
|
187
|
+
"type": "object",
|
|
188
|
+
"required": ["version", "date", "changes"],
|
|
189
|
+
"properties": {
|
|
190
|
+
"version": {
|
|
191
|
+
"type": "string",
|
|
192
|
+
"pattern": "^(0|[1-9]\\d*)\\.(0|[1-9]\\d*)\\.(0|[1-9]\\d*)$"
|
|
193
|
+
},
|
|
194
|
+
"date": {
|
|
195
|
+
"type": "string",
|
|
196
|
+
"pattern": "^\\d{4}-\\d{2}-\\d{2}$"
|
|
197
|
+
},
|
|
198
|
+
"changes": {
|
|
199
|
+
"type": "array",
|
|
200
|
+
"minItems": 1,
|
|
201
|
+
"items": {
|
|
202
|
+
"type": "string"
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
},
|
|
207
|
+
"description": "Version history and changes"
|
|
208
|
+
},
|
|
209
|
+
"min_platform_version": {
|
|
210
|
+
"type": "string",
|
|
211
|
+
"pattern": "^(0|[1-9]\\d*)\\.(0|[1-9]\\d*)\\.(0|[1-9]\\d*)$",
|
|
212
|
+
"description": "Minimum platform version required"
|
|
213
|
+
},
|
|
214
|
+
"max_platform_version": {
|
|
215
|
+
"type": "string",
|
|
216
|
+
"pattern": "^(0|[1-9]\\d*)\\.(0|[1-9]\\d*)\\.(0|[1-9]\\d*)$",
|
|
217
|
+
"description": "Maximum platform version supported"
|
|
218
|
+
}
|
|
219
|
+
},
|
|
220
|
+
"additionalProperties": false
|
|
221
|
+
}
|