@metaverse-systems/the-seed 1.0.2 → 1.2.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.
Files changed (69) hide show
  1. package/.aiignore +5 -0
  2. package/.eslintrc.json +3 -1
  3. package/.vscode/settings.json +14 -0
  4. package/README.md +530 -0
  5. package/dist/Build.d.ts +10 -0
  6. package/dist/Build.js +60 -21
  7. package/dist/Build.js.map +1 -1
  8. package/dist/Config.d.ts +2 -2
  9. package/dist/Config.js +7 -5
  10. package/dist/Config.js.map +1 -1
  11. package/dist/Dependencies.d.ts +7 -0
  12. package/dist/Dependencies.js +76 -0
  13. package/dist/Dependencies.js.map +1 -0
  14. package/dist/Package.d.ts +45 -0
  15. package/dist/Package.js +249 -0
  16. package/dist/Package.js.map +1 -0
  17. package/dist/ResourcePak.d.ts +26 -0
  18. package/dist/ResourcePak.js +110 -0
  19. package/dist/ResourcePak.js.map +1 -0
  20. package/dist/Scopes.d.ts +9 -6
  21. package/dist/Scopes.js.map +1 -1
  22. package/dist/Template.d.ts +2 -1
  23. package/dist/Template.js +28 -25
  24. package/dist/Template.js.map +1 -1
  25. package/dist/index.d.ts +4 -1
  26. package/dist/index.js +5 -1
  27. package/dist/index.js.map +1 -1
  28. package/dist/scripts/BuildCLI.js +8 -5
  29. package/dist/scripts/BuildCLI.js.map +1 -1
  30. package/dist/scripts/ConfigCLI.js +1 -1
  31. package/dist/scripts/ConfigCLI.js.map +1 -1
  32. package/dist/scripts/DependenciesCLI.d.ts +3 -0
  33. package/dist/scripts/DependenciesCLI.js +58 -0
  34. package/dist/scripts/DependenciesCLI.js.map +1 -0
  35. package/dist/scripts/PackageCLI.d.ts +3 -0
  36. package/dist/scripts/PackageCLI.js +38 -0
  37. package/dist/scripts/PackageCLI.js.map +1 -0
  38. package/dist/scripts/ResourcePakCLI.d.ts +3 -0
  39. package/dist/scripts/ResourcePakCLI.js +37 -0
  40. package/dist/scripts/ResourcePakCLI.js.map +1 -0
  41. package/dist/scripts/the-seed.js +19 -0
  42. package/dist/scripts/the-seed.js.map +1 -1
  43. package/dist/types.d.ts +42 -1
  44. package/native/binding.gyp +20 -0
  45. package/native/src/addon.cpp +60 -0
  46. package/package.json +4 -1
  47. package/src/Build.ts +73 -23
  48. package/src/Config.ts +9 -7
  49. package/src/Dependencies.ts +73 -0
  50. package/src/Package.ts +287 -0
  51. package/src/ResourcePak.ts +129 -0
  52. package/src/Scopes.ts +4 -4
  53. package/src/Template.ts +27 -25
  54. package/src/index.ts +16 -0
  55. package/src/scripts/BuildCLI.ts +8 -5
  56. package/src/scripts/ConfigCLI.ts +3 -3
  57. package/src/scripts/DependenciesCLI.ts +57 -0
  58. package/src/scripts/PackageCLI.ts +42 -0
  59. package/src/scripts/ResourcePakCLI.ts +38 -0
  60. package/src/scripts/the-seed.ts +19 -0
  61. package/src/types.ts +46 -1
  62. package/structure.md +0 -3
  63. package/test/Build.test.ts +223 -0
  64. package/test/Config.test.ts +11 -5
  65. package/test/Dependencies.test.ts +153 -0
  66. package/test/Package.test.ts +631 -0
  67. package/test/ResourcePak.test.ts +69 -0
  68. package/test/Scopes.test.ts +15 -7
  69. package/test/Template.test.ts +187 -0
package/dist/types.d.ts CHANGED
@@ -10,7 +10,6 @@ export interface ScopesType {
10
10
  [index: string]: ScopeType;
11
11
  }
12
12
  export interface ConfigType {
13
- [index: string]: any;
14
13
  prefix: string;
15
14
  scopes: ScopesType;
16
15
  }
@@ -19,3 +18,45 @@ export interface ScriptArgsType {
19
18
  args: string[];
20
19
  configDir: string;
21
20
  }
21
+ export interface ResourceType {
22
+ name: string;
23
+ filename: string;
24
+ size: number;
25
+ attributes?: {
26
+ [key: string]: string;
27
+ };
28
+ }
29
+ export interface PackageType {
30
+ author: AuthorType;
31
+ name: string;
32
+ license: string;
33
+ version: string;
34
+ scripts: {
35
+ [index: string]: string;
36
+ };
37
+ resources: ResourceType[];
38
+ main?: string;
39
+ }
40
+ export interface ScopeAnswersType {
41
+ scopeName: string;
42
+ authorName: string;
43
+ authorEmail: string;
44
+ authorURL: string;
45
+ }
46
+ export interface ScopeDefaultsType {
47
+ name?: string;
48
+ email?: string;
49
+ url?: string;
50
+ }
51
+ export interface DependencyResultType {
52
+ dependencies: Record<string, string[]>;
53
+ errors: Record<string, string>;
54
+ }
55
+ export interface BuildStep {
56
+ /** Human-readable step name (e.g., 'autogen', 'configure', 'compile', 'install') */
57
+ label: string;
58
+ /** Shell command to execute */
59
+ command: string;
60
+ /** If true, non-zero exit codes do not abort the build (used for 'make distclean') */
61
+ ignoreExitCode?: boolean;
62
+ }
@@ -0,0 +1,20 @@
1
+ {
2
+ "targets": [
3
+ {
4
+ "target_name": "dependency_lister",
5
+ "sources": ["src/addon.cpp"],
6
+ "include_dirs": [
7
+ "<!@(node -p \"require('node-addon-api').include\")",
8
+ "<!@(pkg-config --cflags-only-I the-seed | sed 's/-I//g')"
9
+ ],
10
+ "libraries": [
11
+ "<!@(pkg-config --libs the-seed)",
12
+ "<!@(pkg-config --libs-only-L the-seed | sed 's/-L/-Wl,-rpath,/g')"
13
+ ],
14
+ "cflags!": ["-fno-exceptions"],
15
+ "cflags_cc!": ["-fno-exceptions"],
16
+ "cflags_cc": ["-std=c++20"],
17
+ "defines": ["NAPI_DISABLE_CPP_EXCEPTIONS"]
18
+ }
19
+ ]
20
+ }
@@ -0,0 +1,60 @@
1
+ #include <napi.h>
2
+ #include <libthe-seed/DependencyLister.hpp>
3
+ #include <string>
4
+ #include <vector>
5
+ #include <map>
6
+
7
+ Napi::Value ListDependencies(const Napi::CallbackInfo& info) {
8
+ Napi::Env env = info.Env();
9
+
10
+ if (info.Length() < 2 || !info[0].IsArray() || !info[1].IsArray()) {
11
+ Napi::TypeError::New(env, "Expected two array arguments: binaryPaths, searchPaths")
12
+ .ThrowAsJavaScriptException();
13
+ return env.Null();
14
+ }
15
+
16
+ Napi::Array jsBinaryPaths = info[0].As<Napi::Array>();
17
+ Napi::Array jsSearchPaths = info[1].As<Napi::Array>();
18
+
19
+ std::vector<std::string> binaryPaths;
20
+ for (uint32_t i = 0; i < jsBinaryPaths.Length(); i++) {
21
+ binaryPaths.push_back(jsBinaryPaths.Get(i).As<Napi::String>().Utf8Value());
22
+ }
23
+
24
+ std::vector<std::string> searchPaths;
25
+ for (uint32_t i = 0; i < jsSearchPaths.Length(); i++) {
26
+ searchPaths.push_back(jsSearchPaths.Get(i).As<Napi::String>().Utf8Value());
27
+ }
28
+
29
+ DependencyLister lister;
30
+ auto result = lister.ListDependencies(binaryPaths, searchPaths);
31
+
32
+ Napi::Object jsResult = Napi::Object::New(env);
33
+
34
+ // Convert dependencies map: Record<string, string[]>
35
+ Napi::Object jsDeps = Napi::Object::New(env);
36
+ for (const auto& [libPath, dependents] : result.dependencies) {
37
+ Napi::Array jsDependents = Napi::Array::New(env, dependents.size());
38
+ for (size_t i = 0; i < dependents.size(); i++) {
39
+ jsDependents.Set(i, Napi::String::New(env, dependents[i]));
40
+ }
41
+ jsDeps.Set(libPath, jsDependents);
42
+ }
43
+ jsResult.Set("dependencies", jsDeps);
44
+
45
+ // Convert errors map: Record<string, string>
46
+ Napi::Object jsErrors = Napi::Object::New(env);
47
+ for (const auto& [binaryPath, errorMsg] : result.errors) {
48
+ jsErrors.Set(binaryPath, Napi::String::New(env, errorMsg));
49
+ }
50
+ jsResult.Set("errors", jsErrors);
51
+
52
+ return jsResult;
53
+ }
54
+
55
+ Napi::Object Init(Napi::Env env, Napi::Object exports) {
56
+ exports.Set("listDependencies", Napi::Function::New(env, ListDependencies));
57
+ return exports;
58
+ }
59
+
60
+ NODE_API_MODULE(dependency_lister, Init)
package/package.json CHANGED
@@ -1,12 +1,13 @@
1
1
  {
2
2
  "name": "@metaverse-systems/the-seed",
3
- "version": "1.0.2",
3
+ "version": "1.2.0",
4
4
  "description": "The Seed",
5
5
  "main": "dist/index.js",
6
6
  "scripts": {
7
7
  "lint": "./node_modules/eslint/bin/eslint.js src/*",
8
8
  "lint-fix": "./node_modules/eslint/bin/eslint.js src/* --fix",
9
9
  "build": "tsc",
10
+ "build-addon": "node-gyp rebuild --directory=native",
10
11
  "test": "./node_modules/jest/bin/jest.js"
11
12
  },
12
13
  "repository": {
@@ -22,6 +23,7 @@
22
23
  "dependencies": {
23
24
  "fs-extra": "^10.0.1",
24
25
  "inquirer": "^8.2.2",
26
+ "node-addon-api": "^5.0.0",
25
27
  "tslib": "^2.3.1",
26
28
  "typescript": "^4.6.2"
27
29
  },
@@ -30,6 +32,7 @@
30
32
  },
31
33
  "keywords": [],
32
34
  "devDependencies": {
35
+ "@types/fs-extra": "^11.0.4",
33
36
  "@types/inquirer": "^8.2.0",
34
37
  "@types/jest": "^27.4.1",
35
38
  "@types/node": "^17.0.21",
package/src/Build.ts CHANGED
@@ -1,19 +1,19 @@
1
1
  import Config from "./Config";
2
- const { execSync } = require('child_process');
2
+ import { execSync } from "child_process";
3
+ import { BuildStep } from "./types";
3
4
 
4
- const targets: {
5
- [key:string]: string;
5
+ export const targets: {
6
+ [key: string]: string;
6
7
  } = {
7
- "native": "x86_64-linux-gnu",
8
- "windows": "x86_64-w64-mingw32",
9
- "wasm": "wasm32-unknown-emscripten",
8
+ native: "x86_64-linux-gnu",
9
+ windows: "x86_64-w64-mingw32",
10
10
  };
11
11
 
12
- const execOptions = {stdio : 'pipe' };
12
+ const execOptions = { stdio: "pipe" as const };
13
13
 
14
14
  class Build {
15
15
  config: Config;
16
- target: string = "linux";
16
+ target = "linux";
17
17
 
18
18
  constructor(config: Config) {
19
19
  this.config = config;
@@ -29,22 +29,24 @@ class Build {
29
29
  }
30
30
 
31
31
  console.log("Completed " + autogen_command);
32
- }
32
+ };
33
33
 
34
34
  configure = () => {
35
35
  const newTarget = targets[this.target];
36
36
  const distclean_command = "make distclean";
37
37
  try {
38
38
  const result = execSync(distclean_command, execOptions).toString();
39
- } catch (e) {
40
- }
39
+ } catch (e) {}
41
40
 
42
41
  const prefix = this.config.config.prefix + "/" + newTarget;
43
42
 
44
- const configure_command = "PKG_CONFIG_PATH=" + prefix + "/lib/pkgconfig/ " +
45
- (this.target === "wasm" ? "emconfigure " : "") +
46
- "./configure --prefix=" + prefix +
47
- (this.target === "windows" ? " --host=" + targets["windows"] : "");
43
+ const configure_command =
44
+ "PKG_CONFIG_PATH=" +
45
+ prefix +
46
+ "/lib/pkgconfig/ " +
47
+ "./configure --prefix=" +
48
+ prefix +
49
+ (this.target === "windows" ? " --host=" + targets["windows"] : "");
48
50
 
49
51
  try {
50
52
  const result = execSync(configure_command, execOptions).toString();
@@ -54,18 +56,16 @@ class Build {
54
56
  }
55
57
 
56
58
  console.log("Configure complete");
57
- }
59
+ };
58
60
 
59
61
  reconfigure = (target: string) => {
60
62
  this.target = target;
61
63
  this.autogen();
62
64
  this.configure();
63
- }
65
+ };
64
66
 
65
67
  compile = () => {
66
- const make_command = this.target === "wasm" ?
67
- "emmake make" :
68
- "make -j";
68
+ const make_command = "make -j";
69
69
 
70
70
  try {
71
71
  const result = execSync(make_command).toString();
@@ -74,19 +74,69 @@ class Build {
74
74
  console.error(e);
75
75
  throw e;
76
76
  }
77
- }
77
+ };
78
78
 
79
79
  install = () => {
80
80
  const install_command = "make install";
81
81
 
82
- try {
82
+ try {
83
83
  const result = execSync(install_command).toString();
84
84
  console.log(result);
85
85
  } catch (e) {
86
86
  console.error(e);
87
87
  throw e;
88
88
  }
89
- }
89
+ };
90
+
91
+ /**
92
+ * Returns an ordered array of BuildStep objects for the given target and mode.
93
+ * @param target - 'native' or 'windows'
94
+ * @param fullReconfigure - if true, includes autogen/distclean/configure steps; if false, only compile+install
95
+ */
96
+ getSteps = (target: string, fullReconfigure: boolean): BuildStep[] => {
97
+ const newTarget = targets[target];
98
+ const prefix = this.config.config.prefix + "/" + newTarget;
99
+
100
+ const steps: BuildStep[] = [];
101
+
102
+ if (fullReconfigure) {
103
+ steps.push({
104
+ label: "autogen",
105
+ command: "./autogen.sh",
106
+ });
107
+
108
+ steps.push({
109
+ label: "distclean",
110
+ command: "make distclean",
111
+ ignoreExitCode: true,
112
+ });
113
+
114
+ const configureCommand =
115
+ "PKG_CONFIG_PATH=" +
116
+ prefix +
117
+ "/lib/pkgconfig/ " +
118
+ "./configure --prefix=" +
119
+ prefix +
120
+ (target === "windows" ? " --host=" + targets["windows"] : "");
121
+
122
+ steps.push({
123
+ label: "configure",
124
+ command: configureCommand,
125
+ });
126
+ }
127
+
128
+ steps.push({
129
+ label: "compile",
130
+ command: "make -j",
131
+ });
132
+
133
+ steps.push({
134
+ label: "install",
135
+ command: "make install",
136
+ });
137
+
138
+ return steps;
139
+ };
90
140
  }
91
141
 
92
142
  export default Build;
package/src/Config.ts CHANGED
@@ -10,13 +10,17 @@ class Config {
10
10
  scopes: {}
11
11
  };
12
12
 
13
- constructor(configDir: string | undefined) {
14
- this.configDir = configDir || os.homedir() + "/.the-seed";
13
+ constructor(configDir?: string) {
14
+ this.configDir = configDir || os.homedir() + "/the-seed";
15
15
  this.configFile = "/config.json";
16
16
  this.loadConfig();
17
17
  }
18
18
 
19
19
  loadConfig = () => {
20
+ // if file does not exist, create it
21
+ if (!fs.existsSync(this.configDir + this.configFile)) {
22
+ this.saveConfig();
23
+ }
20
24
  this.config = JSON.parse(fs.readFileSync(this.configDir + this.configFile).toString());
21
25
  };
22
26
 
@@ -29,15 +33,13 @@ class Config {
29
33
  {
30
34
  name: "prefix",
31
35
  message: "Installation prefix?",
32
- default: this.config["prefix"]
36
+ default: this.config.prefix
33
37
  }
34
38
  ];
35
39
  };
36
40
 
37
- parseAnswers = (answers: { [index:string]: any }) => {
38
- Object.keys(answers).forEach((k) => {
39
- this.config[k] = answers[k];
40
- });
41
+ parseAnswers = (answers: { prefix: string }) => {
42
+ this.config.prefix = answers.prefix;
41
43
  };
42
44
  }
43
45
 
@@ -0,0 +1,73 @@
1
+ import Config from "./Config";
2
+ import { execSync } from "child_process";
3
+ import { targets } from "./Build";
4
+
5
+ const execOptions = { stdio: "pipe" as const, shell: "/bin/bash", env: { ...process.env } };
6
+ const libEcsRepo = "https://github.com/metaverse-systems/libecs-cpp.git";
7
+ const libTheSeedRepo = "https://github.com/metaverse-systems/libthe-seed.git";
8
+
9
+ export const checkLib = (config: Config, library: string, target: string) => {
10
+ const targetPrefix = targets[target];
11
+ const prefix = config.config.prefix + "/" + targetPrefix;
12
+ const pkgConfigCommand =
13
+ "PKG_CONFIG_PATH=" +
14
+ prefix +
15
+ "/lib/pkgconfig/ " +
16
+ "pkg-config --cflags --libs " +
17
+ library;
18
+ try {
19
+ const result = execSync(pkgConfigCommand, execOptions).toString();
20
+ if (result.includes(library)) {
21
+ return true;
22
+ }
23
+ console.error("pkg-config did not find " + library);
24
+ } catch (e) {
25
+ return false;
26
+ }
27
+ return false;
28
+ };
29
+
30
+ export const checkLibEcs = (config: Config, target: string) => {
31
+ return checkLib(config, "ecs-cpp", target);
32
+ };
33
+
34
+ export const checkLibTheSeed = (config: Config, target: string) => {
35
+ return checkLib(config, "the-seed", target);
36
+ };
37
+
38
+ export const installLibEcs = (config: Config, target: string) => {
39
+ if(installLib(config, libEcsRepo, "libecs-cpp", target)) {
40
+ return true;
41
+ }
42
+ console.error("Failed to build libecs-cpp");
43
+ return false;
44
+ };
45
+
46
+ export const installLibTheSeed = (config: Config, target: string) => {
47
+ if(installLib(config, libTheSeedRepo, "libthe-seed", target)) {
48
+ return true;
49
+ }
50
+ console.error("Failed to build libthe-seed");
51
+ return false;
52
+ };
53
+
54
+ export const installLib = (config: Config, repo: string, installDir: string, target: string) => {
55
+ const targetDir = targets[target];
56
+ const prefix = config.config.prefix + "/" + targetDir;
57
+ const cloneCommand = "git clone " + repo;
58
+ try {
59
+ const result = execSync(cloneCommand, execOptions).toString();
60
+ } catch (e) {
61
+ console.error("Failed to clone " + repo);
62
+ }
63
+ const buildCommand =
64
+ "cd " + installDir + " && ./autogen.sh && ./configure --prefix=" +
65
+ prefix + (target != "native" ? " --host=" + targetDir : "") +
66
+ " && make && make install";
67
+ try {
68
+ const result = execSync(buildCommand, execOptions).toString();
69
+ } catch (e) {
70
+ return false;
71
+ }
72
+ return true;
73
+ };