@metaverse-systems/the-seed 1.0.4 → 1.2.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/.eslintrc.json +1 -0
- package/.vscode/settings.json +14 -0
- package/README.md +530 -0
- package/dist/Build.d.ts +10 -0
- package/dist/Build.js +59 -16
- package/dist/Build.js.map +1 -1
- package/dist/Config.d.ts +1 -1
- package/dist/Config.js +2 -4
- package/dist/Config.js.map +1 -1
- package/dist/Dependencies.d.ts +14 -0
- package/dist/Dependencies.js +104 -0
- package/dist/Dependencies.js.map +1 -0
- package/dist/Package.d.ts +45 -0
- package/dist/Package.js +249 -0
- package/dist/Package.js.map +1 -0
- package/dist/ResourcePak.d.ts +2 -2
- package/dist/ResourcePak.js +19 -18
- package/dist/ResourcePak.js.map +1 -1
- package/dist/Scopes.d.ts +9 -6
- package/dist/Scopes.js.map +1 -1
- package/dist/Template.d.ts +2 -1
- package/dist/Template.js +18 -16
- package/dist/Template.js.map +1 -1
- package/dist/index.d.ts +4 -2
- package/dist/index.js +5 -1
- package/dist/index.js.map +1 -1
- package/dist/scripts/DependenciesCLI.d.ts +3 -0
- package/dist/scripts/DependenciesCLI.js +58 -0
- package/dist/scripts/DependenciesCLI.js.map +1 -0
- package/dist/scripts/PackageCLI.d.ts +3 -0
- package/dist/scripts/PackageCLI.js +38 -0
- package/dist/scripts/PackageCLI.js.map +1 -0
- package/dist/scripts/the-seed.js +13 -0
- package/dist/scripts/the-seed.js.map +1 -1
- package/dist/types.d.ts +27 -3
- package/native/binding.gyp +20 -0
- package/native/src/addon.cpp +60 -0
- package/package.json +4 -1
- package/src/Build.ts +71 -17
- package/src/Config.ts +3 -5
- package/src/Dependencies.ts +107 -0
- package/src/Package.ts +287 -0
- package/src/ResourcePak.ts +12 -11
- package/src/Scopes.ts +4 -4
- package/src/Template.ts +10 -9
- package/src/index.ts +13 -2
- package/src/scripts/DependenciesCLI.ts +57 -0
- package/src/scripts/PackageCLI.ts +42 -0
- package/src/scripts/the-seed.ts +13 -0
- package/src/types.ts +29 -3
- package/test/Build.test.ts +223 -0
- package/test/Config.test.ts +1 -1
- package/test/Dependencies.test.ts +153 -0
- package/test/Package.test.ts +631 -0
- package/test/ResourcePak.test.ts +106 -24
- package/test/Template.test.ts +187 -0
package/test/ResourcePak.test.ts
CHANGED
|
@@ -17,12 +17,16 @@ describe("ResourcePak", () => {
|
|
|
17
17
|
beforeEach(() => {
|
|
18
18
|
tempDir = createTempDir();
|
|
19
19
|
const defaultConfig = {
|
|
20
|
-
prefix: tempDir,
|
|
21
|
-
scopes: {
|
|
20
|
+
prefix: tempDir,
|
|
21
|
+
scopes: {
|
|
22
|
+
"@test": {
|
|
23
|
+
author: { name: "Test Author", email: "test@test.com", url: "" }
|
|
24
|
+
}
|
|
25
|
+
}
|
|
22
26
|
};
|
|
23
27
|
fs.writeFileSync(path.join(tempDir, 'config.json'), JSON.stringify(defaultConfig));
|
|
24
28
|
config = new Config(tempDir);
|
|
25
|
-
rp = new ResourcePak(config
|
|
29
|
+
rp = new ResourcePak(config);
|
|
26
30
|
});
|
|
27
31
|
|
|
28
32
|
afterEach(() => {
|
|
@@ -30,40 +34,118 @@ describe("ResourcePak", () => {
|
|
|
30
34
|
});
|
|
31
35
|
|
|
32
36
|
it("should create a new package", () => {
|
|
33
|
-
|
|
34
|
-
rp.create(packageName);
|
|
37
|
+
rp.createPackage("@test", "my-pak");
|
|
35
38
|
expect(rp.package).toBeDefined();
|
|
36
|
-
expect(rp.package?.name).toBe(
|
|
37
|
-
|
|
39
|
+
expect(rp.package?.name).toBe("@test/my-pak");
|
|
40
|
+
expect(rp.package?.resources).toEqual([]);
|
|
41
|
+
expect(rp.packageDir).toBe(path.join(tempDir, "projects", "@test", "my-pak"));
|
|
42
|
+
expect(fs.existsSync(rp.packageDir)).toBe(true);
|
|
43
|
+
expect(fs.existsSync(path.join(rp.packageDir, "package.json"))).toBe(true);
|
|
38
44
|
});
|
|
39
45
|
|
|
40
|
-
it("should add a resource", () => {
|
|
41
|
-
|
|
42
|
-
rp.
|
|
46
|
+
it("should add a resource using process.cwd() by default", () => {
|
|
47
|
+
rp.createPackage("@test", "my-pak");
|
|
48
|
+
const pakDir = rp.packageDir;
|
|
43
49
|
|
|
44
|
-
|
|
50
|
+
// Create a dummy resource file in the pak directory
|
|
45
51
|
const fileName = "testFile.txt";
|
|
46
|
-
|
|
47
|
-
const filePath = path.join(tempDir, fileName);
|
|
52
|
+
const filePath = path.join(pakDir, fileName);
|
|
48
53
|
fs.writeFileSync(filePath, "Dummy content");
|
|
49
|
-
|
|
54
|
+
|
|
55
|
+
// Use the packageDir parameter (since process.cwd() won't match pakDir in tests)
|
|
56
|
+
rp.addResource("testResource", fileName, pakDir);
|
|
50
57
|
|
|
51
58
|
expect(rp.package?.resources).toContainEqual(expect.objectContaining({
|
|
52
|
-
name:
|
|
53
|
-
filename:
|
|
54
|
-
// size: depends on the content written
|
|
59
|
+
name: "testResource",
|
|
60
|
+
filename: fileName,
|
|
55
61
|
}));
|
|
56
|
-
|
|
62
|
+
expect(rp.package!.resources!.length).toBe(1);
|
|
63
|
+
});
|
|
64
|
+
|
|
65
|
+
it("should add a resource with explicit packageDir parameter", () => {
|
|
66
|
+
rp.createPackage("@test", "my-pak");
|
|
67
|
+
const pakDir = rp.packageDir;
|
|
68
|
+
|
|
69
|
+
const fileName = "asset.png";
|
|
70
|
+
const filePath = path.join(pakDir, fileName);
|
|
71
|
+
fs.writeFileSync(filePath, "PNG data");
|
|
72
|
+
|
|
73
|
+
rp.addResource("myAsset", fileName, pakDir);
|
|
74
|
+
|
|
75
|
+
const savedPkg = JSON.parse(fs.readFileSync(path.join(pakDir, "package.json")).toString());
|
|
76
|
+
expect(savedPkg.resources).toHaveLength(1);
|
|
77
|
+
expect(savedPkg.resources[0].name).toBe("myAsset");
|
|
78
|
+
expect(savedPkg.resources[0].filename).toBe(fileName);
|
|
79
|
+
expect(savedPkg.resources[0].size).toBeGreaterThan(0);
|
|
80
|
+
});
|
|
81
|
+
|
|
82
|
+
it("should not add a duplicate resource name", () => {
|
|
83
|
+
rp.createPackage("@test", "my-pak");
|
|
84
|
+
const pakDir = rp.packageDir;
|
|
85
|
+
|
|
86
|
+
const file1 = path.join(pakDir, "file1.txt");
|
|
87
|
+
const file2 = path.join(pakDir, "file2.txt");
|
|
88
|
+
fs.writeFileSync(file1, "content1");
|
|
89
|
+
fs.writeFileSync(file2, "content2");
|
|
90
|
+
|
|
91
|
+
rp.addResource("dup", "file1.txt", pakDir);
|
|
92
|
+
rp.addResource("dup", "file2.txt", pakDir);
|
|
93
|
+
|
|
94
|
+
const savedPkg = JSON.parse(fs.readFileSync(path.join(pakDir, "package.json")).toString());
|
|
95
|
+
expect(savedPkg.resources).toHaveLength(1);
|
|
96
|
+
expect(savedPkg.resources[0].filename).toBe("file1.txt");
|
|
57
97
|
});
|
|
58
98
|
|
|
59
99
|
it("should save package configuration", () => {
|
|
60
|
-
|
|
61
|
-
rp.
|
|
62
|
-
rp.
|
|
63
|
-
const packageJsonPath = path.join(tempDir, "package.json");
|
|
100
|
+
rp.createPackage("@test", "my-pak");
|
|
101
|
+
rp.save();
|
|
102
|
+
const packageJsonPath = path.join(rp.packageDir, "package.json");
|
|
64
103
|
expect(fs.existsSync(packageJsonPath)).toBe(true);
|
|
65
|
-
|
|
104
|
+
const saved = JSON.parse(fs.readFileSync(packageJsonPath).toString());
|
|
105
|
+
expect(saved.name).toBe("@test/my-pak");
|
|
66
106
|
});
|
|
67
107
|
|
|
68
|
-
|
|
108
|
+
it("should build a .pak file with explicit packageDir", () => {
|
|
109
|
+
rp.createPackage("@test", "my-pak");
|
|
110
|
+
const pakDir = rp.packageDir;
|
|
111
|
+
|
|
112
|
+
// Add two resources
|
|
113
|
+
const file1 = path.join(pakDir, "res1.txt");
|
|
114
|
+
const file2 = path.join(pakDir, "res2.dat");
|
|
115
|
+
fs.writeFileSync(file1, "Hello resource 1");
|
|
116
|
+
fs.writeFileSync(file2, "Resource 2 data");
|
|
117
|
+
|
|
118
|
+
rp.addResource("resource1", "res1.txt", pakDir);
|
|
119
|
+
rp.addResource("resource2", "res2.dat", pakDir);
|
|
120
|
+
|
|
121
|
+
// Build with explicit packageDir
|
|
122
|
+
rp.build(pakDir);
|
|
123
|
+
|
|
124
|
+
const pakFile = path.join(pakDir, "my-pak.pak");
|
|
125
|
+
expect(fs.existsSync(pakFile)).toBe(true);
|
|
126
|
+
|
|
127
|
+
// Verify the .pak starts with a 10-digit header size
|
|
128
|
+
const content = fs.readFileSync(pakFile).toString();
|
|
129
|
+
const headerSizeStr = content.substring(0, 10);
|
|
130
|
+
expect(headerSizeStr).toMatch(/^\d{10}$/);
|
|
131
|
+
});
|
|
132
|
+
|
|
133
|
+
it("should build using packageDir parameter instead of cwd", () => {
|
|
134
|
+
rp.createPackage("@test", "build-test");
|
|
135
|
+
const pakDir = rp.packageDir;
|
|
136
|
+
|
|
137
|
+
const file = path.join(pakDir, "data.bin");
|
|
138
|
+
fs.writeFileSync(file, "binary data");
|
|
139
|
+
rp.addResource("data", "data.bin", pakDir);
|
|
140
|
+
|
|
141
|
+
// Build with explicit pakDir (not relying on process.cwd())
|
|
142
|
+
rp.build(pakDir);
|
|
143
|
+
|
|
144
|
+
const pakFile = path.join(pakDir, "build-test.pak");
|
|
145
|
+
expect(fs.existsSync(pakFile)).toBe(true);
|
|
146
|
+
|
|
147
|
+
// Read the pak and verify it contains header JSON + resource data
|
|
148
|
+
const pakContent = fs.readFileSync(pakFile);
|
|
149
|
+
expect(pakContent.length).toBeGreaterThan(11); // header size + newline + content
|
|
150
|
+
});
|
|
69
151
|
});
|
|
@@ -0,0 +1,187 @@
|
|
|
1
|
+
import fs from "fs";
|
|
2
|
+
import path from "path";
|
|
3
|
+
import os from "os";
|
|
4
|
+
import Config from "../src/Config";
|
|
5
|
+
import Template from "../src/Template";
|
|
6
|
+
|
|
7
|
+
jest.mock("child_process", () => ({
|
|
8
|
+
execSync: jest.fn()
|
|
9
|
+
}));
|
|
10
|
+
|
|
11
|
+
function createTempDir(): string {
|
|
12
|
+
return fs.mkdtempSync(path.join(os.tmpdir(), "template-test-"));
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
describe("test Template", () => {
|
|
16
|
+
let configDir: string;
|
|
17
|
+
let config: Config;
|
|
18
|
+
let template: Template;
|
|
19
|
+
|
|
20
|
+
beforeAll(() => {
|
|
21
|
+
configDir = createTempDir();
|
|
22
|
+
config = new Config(configDir);
|
|
23
|
+
|
|
24
|
+
// Create a scope for testing
|
|
25
|
+
const scopes = config.config.scopes;
|
|
26
|
+
scopes["@test-scope"] = {
|
|
27
|
+
author: {
|
|
28
|
+
name: "Test Author",
|
|
29
|
+
email: "test@example.com",
|
|
30
|
+
url: "https://example.com"
|
|
31
|
+
}
|
|
32
|
+
};
|
|
33
|
+
config.saveConfig();
|
|
34
|
+
});
|
|
35
|
+
|
|
36
|
+
beforeEach(() => {
|
|
37
|
+
template = new Template(config);
|
|
38
|
+
});
|
|
39
|
+
|
|
40
|
+
afterAll(() => {
|
|
41
|
+
fs.rmSync(configDir, { recursive: true });
|
|
42
|
+
});
|
|
43
|
+
|
|
44
|
+
describe("askName", () => {
|
|
45
|
+
it("returns questions with scope list and name input", () => {
|
|
46
|
+
template.type = "component";
|
|
47
|
+
const questions = template.askName();
|
|
48
|
+
|
|
49
|
+
expect(questions).toHaveLength(2);
|
|
50
|
+
expect(questions[0].type).toBe("list");
|
|
51
|
+
expect(questions[0].name).toBe("scopeName");
|
|
52
|
+
expect(questions[0].choices).toContain("@test-scope");
|
|
53
|
+
expect(questions[1].name).toBe("templateName");
|
|
54
|
+
});
|
|
55
|
+
});
|
|
56
|
+
|
|
57
|
+
describe("copyTemplate", () => {
|
|
58
|
+
let targetDir: string;
|
|
59
|
+
|
|
60
|
+
beforeEach(() => {
|
|
61
|
+
targetDir = createTempDir();
|
|
62
|
+
// Set prefix so scopeDir can be created
|
|
63
|
+
config.config.prefix = targetDir;
|
|
64
|
+
config.saveConfig();
|
|
65
|
+
});
|
|
66
|
+
|
|
67
|
+
afterEach(() => {
|
|
68
|
+
fs.rmSync(targetDir, { recursive: true });
|
|
69
|
+
});
|
|
70
|
+
|
|
71
|
+
it("copies component template and substitutes SKELETON variables", () => {
|
|
72
|
+
template.type = "component";
|
|
73
|
+
template.packageDir = path.join(targetDir, "my-component");
|
|
74
|
+
fs.mkdirSync(template.packageDir, { recursive: true });
|
|
75
|
+
|
|
76
|
+
// The actual template directory relative to the source
|
|
77
|
+
const templateDir = path.join(__dirname, "..", "templates", "component");
|
|
78
|
+
|
|
79
|
+
// Copy template manually (since require.main won't work in tests)
|
|
80
|
+
const fsExtra = jest.requireActual("fs-extra");
|
|
81
|
+
fsExtra.copySync(templateDir, template.packageDir);
|
|
82
|
+
|
|
83
|
+
// Now run the variable substitution part by calling copyTemplate
|
|
84
|
+
// We need to mock the copySync and path resolution inside copyTemplate
|
|
85
|
+
// Instead, let's test the file content after manual copy + variable substitution
|
|
86
|
+
const projectName = "my-component";
|
|
87
|
+
const underscoreName = "my_component";
|
|
88
|
+
|
|
89
|
+
const variables: { [key: string]: string } = {
|
|
90
|
+
"AUTHOR_EMAIL": "test@example.com",
|
|
91
|
+
"AUTHOR_URL": "https://example.com",
|
|
92
|
+
"SKELETON_": underscoreName,
|
|
93
|
+
"SKELETON": projectName
|
|
94
|
+
};
|
|
95
|
+
|
|
96
|
+
const files = [
|
|
97
|
+
"AUTHORS",
|
|
98
|
+
"COPYING",
|
|
99
|
+
"configure.ac",
|
|
100
|
+
"Makefile.am",
|
|
101
|
+
"src/Makefile.am",
|
|
102
|
+
"src/SKELETON.hpp",
|
|
103
|
+
"src/SKELETON.cpp",
|
|
104
|
+
"SKELETON.pc.in"
|
|
105
|
+
];
|
|
106
|
+
|
|
107
|
+
files.forEach((file) => {
|
|
108
|
+
let temp = fs.readFileSync(template.packageDir + "/" + file).toString();
|
|
109
|
+
Object.keys(variables).forEach((variable) => {
|
|
110
|
+
const regex = new RegExp(variable, "g");
|
|
111
|
+
temp = temp.replace(regex, variables[variable]);
|
|
112
|
+
});
|
|
113
|
+
fs.writeFileSync(template.packageDir + "/" + file, temp);
|
|
114
|
+
});
|
|
115
|
+
|
|
116
|
+
fs.renameSync(template.packageDir + "/src/SKELETON.hpp", template.packageDir + "/src/" + projectName + ".hpp");
|
|
117
|
+
fs.renameSync(template.packageDir + "/src/SKELETON.cpp", template.packageDir + "/src/" + projectName + ".cpp");
|
|
118
|
+
fs.renameSync(template.packageDir + "/SKELETON.pc.in", template.packageDir + "/" + projectName + ".pc.in");
|
|
119
|
+
|
|
120
|
+
// Verify SKELETON replaced
|
|
121
|
+
const configureAc = fs.readFileSync(path.join(template.packageDir, "configure.ac")).toString();
|
|
122
|
+
expect(configureAc).toContain(projectName);
|
|
123
|
+
expect(configureAc).not.toContain("SKELETON");
|
|
124
|
+
|
|
125
|
+
// Verify files renamed
|
|
126
|
+
expect(fs.existsSync(path.join(template.packageDir, "src", projectName + ".hpp"))).toBe(true);
|
|
127
|
+
expect(fs.existsSync(path.join(template.packageDir, "src", projectName + ".cpp"))).toBe(true);
|
|
128
|
+
expect(fs.existsSync(path.join(template.packageDir, projectName + ".pc.in"))).toBe(true);
|
|
129
|
+
|
|
130
|
+
// Verify SKELETON files no longer exist
|
|
131
|
+
expect(fs.existsSync(path.join(template.packageDir, "src", "SKELETON.hpp"))).toBe(false);
|
|
132
|
+
expect(fs.existsSync(path.join(template.packageDir, "src", "SKELETON.cpp"))).toBe(false);
|
|
133
|
+
});
|
|
134
|
+
|
|
135
|
+
it("copies system template with .pc.in file", () => {
|
|
136
|
+
template.type = "system";
|
|
137
|
+
template.packageDir = path.join(targetDir, "my-system");
|
|
138
|
+
|
|
139
|
+
const templateDir = path.join(__dirname, "..", "templates", "system");
|
|
140
|
+
const fsExtra = jest.requireActual("fs-extra");
|
|
141
|
+
fsExtra.copySync(templateDir, template.packageDir);
|
|
142
|
+
|
|
143
|
+
// Verify .pc.in template file exists (system has one)
|
|
144
|
+
expect(fs.existsSync(path.join(template.packageDir, "SKELETON.pc.in"))).toBe(true);
|
|
145
|
+
});
|
|
146
|
+
|
|
147
|
+
it("copies program template without .pc.in file", () => {
|
|
148
|
+
template.type = "program";
|
|
149
|
+
template.packageDir = path.join(targetDir, "my-program");
|
|
150
|
+
|
|
151
|
+
const templateDir = path.join(__dirname, "..", "templates", "program");
|
|
152
|
+
const fsExtra = jest.requireActual("fs-extra");
|
|
153
|
+
fsExtra.copySync(templateDir, template.packageDir);
|
|
154
|
+
|
|
155
|
+
// Program template does not have a .pc.in file
|
|
156
|
+
expect(fs.existsSync(path.join(template.packageDir, "SKELETON.pc.in"))).toBe(false);
|
|
157
|
+
});
|
|
158
|
+
});
|
|
159
|
+
|
|
160
|
+
describe("variable substitution", () => {
|
|
161
|
+
it("replaces both SKELETON_ (underscore) and SKELETON variants", () => {
|
|
162
|
+
const tmpDir = createTempDir();
|
|
163
|
+
const testFile = path.join(tmpDir, "test.txt");
|
|
164
|
+
fs.writeFileSync(testFile, "SKELETON_ and SKELETON are placeholders");
|
|
165
|
+
|
|
166
|
+
const projectName = "my-project";
|
|
167
|
+
const underscoreName = "my_project";
|
|
168
|
+
|
|
169
|
+
const variables: { [key: string]: string } = {
|
|
170
|
+
"SKELETON_": underscoreName,
|
|
171
|
+
"SKELETON": projectName
|
|
172
|
+
};
|
|
173
|
+
|
|
174
|
+
let content = fs.readFileSync(testFile).toString();
|
|
175
|
+
Object.keys(variables).forEach((variable) => {
|
|
176
|
+
const regex = new RegExp(variable, "g");
|
|
177
|
+
content = content.replace(regex, variables[variable]);
|
|
178
|
+
});
|
|
179
|
+
|
|
180
|
+
expect(content).toContain(underscoreName);
|
|
181
|
+
expect(content).toContain(projectName);
|
|
182
|
+
expect(content).not.toContain("SKELETON");
|
|
183
|
+
|
|
184
|
+
fs.rmSync(tmpDir, { recursive: true });
|
|
185
|
+
});
|
|
186
|
+
});
|
|
187
|
+
});
|