titanpl 6.0.0 → 7.0.0-beta
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/package.json +1 -1
- package/packages/cli/index.js +25 -11
- package/packages/cli/package.json +4 -4
- package/packages/cli/src/commands/build-ext.js +157 -0
- package/packages/cli/src/commands/build.js +12 -0
- package/packages/cli/src/commands/create.js +160 -0
- package/packages/cli/src/commands/init.js +5 -11
- package/packages/cli/src/commands/run-ext.js +104 -0
- package/packages/engine-darwin-arm64/README.md +0 -2
- package/packages/engine-darwin-arm64/package.json +1 -1
- package/packages/engine-linux-x64/README.md +0 -2
- package/packages/engine-linux-x64/package.json +1 -1
- package/packages/engine-win32-x64/README.md +0 -1
- package/packages/engine-win32-x64/package.json +1 -1
- package/packages/native/README.md +0 -1
- package/packages/native/index.d.ts +10 -4
- package/packages/native/index.js +1 -0
- package/packages/native/package.json +1 -1
- package/packages/native/t.native.d.ts +90 -2
- package/packages/packet/index.js +19 -2
- package/packages/packet/package.json +1 -1
- package/packages/route/package.json +1 -1
- package/packages/sdk/index.js +2 -0
- package/packages/sdk/package.json +18 -0
- package/packages/sdk/test/index.js +120 -0
- package/templates/common/_tanfig.json +17 -13
- package/templates/extension/index.d.ts +26 -22
- package/templates/extension/index.js +15 -15
- package/templates/extension/native/Cargo.toml +5 -3
- package/templates/extension/native/src/lib.rs +2 -3
- package/templates/extension/package.json +10 -20
- package/templates/extension/titan.json +5 -16
- package/templates/extension/utils/registerExtension.js +44 -0
- package/templates/js/package.json +7 -7
- package/templates/rust-js/package.json +4 -4
- package/templates/rust-ts/package.json +4 -4
- package/templates/ts/package.json +7 -7
- package/titanpl-sdk/LICENSE +0 -15
- package/titanpl-sdk/README.md +0 -111
- package/titanpl-sdk/assets/titanpl-sdk.png +0 -0
- package/titanpl-sdk/bin/run.js +0 -274
- package/titanpl-sdk/index.js +0 -5
- package/titanpl-sdk/package-lock.json +0 -28
- package/titanpl-sdk/package.json +0 -40
- package/titanpl-sdk/templates/app/actions/hello.js +0 -5
- package/titanpl-sdk/templates/app/app.js +0 -7
- package/titanpl-sdk/templates/jsconfig.json +0 -19
- package/titanpl-sdk/templates/server/Cargo.toml +0 -52
- package/titanpl-sdk/templates/server/src/action_management.rs +0 -175
- package/titanpl-sdk/templates/server/src/errors.rs +0 -12
- package/titanpl-sdk/templates/server/src/extensions/builtin.rs +0 -1060
- package/titanpl-sdk/templates/server/src/extensions/external.rs +0 -338
- package/titanpl-sdk/templates/server/src/extensions/mod.rs +0 -580
- package/titanpl-sdk/templates/server/src/extensions/titan_core.js +0 -249
- package/titanpl-sdk/templates/server/src/fast_path.rs +0 -719
- package/titanpl-sdk/templates/server/src/main.rs +0 -607
- package/titanpl-sdk/templates/server/src/runtime.rs +0 -284
- package/titanpl-sdk/templates/server/src/utils.rs +0 -33
- package/titanpl-sdk/templates/titan/bundle.js +0 -259
- package/titanpl-sdk/templates/titan/dev.js +0 -390
- package/titanpl-sdk/templates/titan/error-box.js +0 -277
- package/titanpl-sdk/templates/titan/titan.js +0 -129
|
@@ -297,6 +297,14 @@ export const session: typeof t.session;
|
|
|
297
297
|
*/
|
|
298
298
|
export const cookies: typeof t.cookies;
|
|
299
299
|
|
|
300
|
+
/**
|
|
301
|
+
* Titan Shared Context (Shared In-Memory State) shorthand.
|
|
302
|
+
*
|
|
303
|
+
* Re-exported from the `t` global for module-style imports.
|
|
304
|
+
* @see {@link TitanCore.ShareContext} for full documentation.
|
|
305
|
+
*/
|
|
306
|
+
export const shareContext: typeof t.shareContext;
|
|
307
|
+
|
|
300
308
|
/**
|
|
301
309
|
* Operating system information (platform, CPU count, memory).
|
|
302
310
|
*
|
|
@@ -647,12 +655,12 @@ declare global {
|
|
|
647
655
|
*
|
|
648
656
|
* @example
|
|
649
657
|
* ```js
|
|
650
|
-
* export default
|
|
658
|
+
* export default function chat(req) {
|
|
651
659
|
* if (req.event === "open") {
|
|
652
660
|
* t.ws.send(req.socketId, "Welcome!");
|
|
653
661
|
* t.ws.broadcast("Someone joined.");
|
|
654
662
|
* }
|
|
655
|
-
* }
|
|
663
|
+
* }
|
|
656
664
|
* ```
|
|
657
665
|
*/
|
|
658
666
|
ws: {
|
|
@@ -1012,6 +1020,19 @@ declare global {
|
|
|
1012
1020
|
*/
|
|
1013
1021
|
session: TitanCore.Session;
|
|
1014
1022
|
|
|
1023
|
+
/**
|
|
1024
|
+
* Titan Shared Context — Cross-isolate Shared In-Memory State.
|
|
1025
|
+
*
|
|
1026
|
+
* Provides a mechanism for sharing data across different isolates (requests)
|
|
1027
|
+
* and broadcasting events within the same server process.
|
|
1028
|
+
*
|
|
1029
|
+
* Data in `shareContext` is volatile and lost when the server exits.
|
|
1030
|
+
*
|
|
1031
|
+
* @see {@link TitanCore.ShareContext} for method signatures.
|
|
1032
|
+
* @see https://titanpl.vercel.app/docs/knowledge/05-titan-core — TitanCore Runtime APIs (t.shareContext)
|
|
1033
|
+
*/
|
|
1034
|
+
shareContext: TitanCore.ShareContext;
|
|
1035
|
+
|
|
1015
1036
|
/**
|
|
1016
1037
|
* HTTP cookie utilities for reading, setting, and deleting cookies.
|
|
1017
1038
|
*
|
|
@@ -1731,6 +1752,73 @@ declare global {
|
|
|
1731
1752
|
clear(sessionId: string): void;
|
|
1732
1753
|
}
|
|
1733
1754
|
|
|
1755
|
+
/**
|
|
1756
|
+
* Titan Shared Context — Cross-isolate Shared In-Memory State.
|
|
1757
|
+
*
|
|
1758
|
+
* Provides a mechanism for sharing data across different isolates (requests)
|
|
1759
|
+
* and broadcasting events within the same server process.
|
|
1760
|
+
*
|
|
1761
|
+
* Data in `shareContext` is in-memory only and is lost when the server process exits.
|
|
1762
|
+
*
|
|
1763
|
+
* @example
|
|
1764
|
+
* ```js
|
|
1765
|
+
* export function getStats(req) {
|
|
1766
|
+
* // Store a value common to all requests
|
|
1767
|
+
* t.shareContext.set("last_login", t.time.now());
|
|
1768
|
+
*
|
|
1769
|
+
* // Retrieve a value
|
|
1770
|
+
* const users = t.shareContext.get("active_users");
|
|
1771
|
+
*
|
|
1772
|
+
* // Broadcast a message to other workers
|
|
1773
|
+
* t.shareContext.broadcast("user_login", { user: "Titan" });
|
|
1774
|
+
* }
|
|
1775
|
+
* ```
|
|
1776
|
+
*
|
|
1777
|
+
* @see https://titanpl.vercel.app/docs/knowledge/05-titan-core — TitanCore Runtime APIs (t.shareContext)
|
|
1778
|
+
*/
|
|
1779
|
+
interface ShareContext {
|
|
1780
|
+
/**
|
|
1781
|
+
* Retrieve a value from the shared context.
|
|
1782
|
+
*
|
|
1783
|
+
* @param key - The key of the value to retrieve.
|
|
1784
|
+
* @returns The parsed value, or `null` if the key does not exist.
|
|
1785
|
+
*/
|
|
1786
|
+
get(key: string): any;
|
|
1787
|
+
|
|
1788
|
+
/**
|
|
1789
|
+
* Store a value in the shared context.
|
|
1790
|
+
*
|
|
1791
|
+
* Values are serialized as JSON and must be serializable.
|
|
1792
|
+
*
|
|
1793
|
+
* @param key - The key to store under.
|
|
1794
|
+
* @param value - The JSON-serializable value to store.
|
|
1795
|
+
*/
|
|
1796
|
+
set(key: string, value: any): void;
|
|
1797
|
+
|
|
1798
|
+
/**
|
|
1799
|
+
* Remove a key and its value from the shared context.
|
|
1800
|
+
*
|
|
1801
|
+
* @param key - The key to remove.
|
|
1802
|
+
*/
|
|
1803
|
+
delete(key: string): void;
|
|
1804
|
+
|
|
1805
|
+
/**
|
|
1806
|
+
* Get a list of all keys currently in the shared context.
|
|
1807
|
+
*
|
|
1808
|
+
* @returns An array of string keys.
|
|
1809
|
+
*/
|
|
1810
|
+
keys(): string[];
|
|
1811
|
+
|
|
1812
|
+
/**
|
|
1813
|
+
* Broadcast an event and payload to other active isolates (requests)
|
|
1814
|
+
* and workers in this server process.
|
|
1815
|
+
*
|
|
1816
|
+
* @param event - The name of the event to broadcast.
|
|
1817
|
+
* @param payload - The payload of the event.
|
|
1818
|
+
*/
|
|
1819
|
+
broadcast(event: string, payload: any): void;
|
|
1820
|
+
}
|
|
1821
|
+
|
|
1734
1822
|
/**
|
|
1735
1823
|
* HTTP cookie management utilities.
|
|
1736
1824
|
*
|
package/packages/packet/index.js
CHANGED
|
@@ -67,6 +67,15 @@ export async function build(root = process.cwd()) {
|
|
|
67
67
|
outDir: dist,
|
|
68
68
|
});
|
|
69
69
|
|
|
70
|
+
const tanfigPath = path.join(root, "tanfig.json");
|
|
71
|
+
if (fs.existsSync(tanfigPath)) {
|
|
72
|
+
fs.copyFileSync(tanfigPath, path.join(dist, "tanfig.json"));
|
|
73
|
+
}
|
|
74
|
+
const titanExtPath = path.join(root, "titan.json");
|
|
75
|
+
if (fs.existsSync(titanExtPath)) {
|
|
76
|
+
fs.copyFileSync(titanExtPath, path.join(dist, "titan.json"));
|
|
77
|
+
}
|
|
78
|
+
|
|
70
79
|
return dist;
|
|
71
80
|
}
|
|
72
81
|
|
|
@@ -91,7 +100,7 @@ export async function release(root = process.cwd()) {
|
|
|
91
100
|
} catch (e) { }
|
|
92
101
|
}
|
|
93
102
|
|
|
94
|
-
const filesToCopy = config.build && config.build.files ? config.build.files : ["public", "static", "db", "config"];
|
|
103
|
+
const filesToCopy = config.build && config.build.files ? config.build.files : ["public", "static", "db", "config", "tanfig.json", "titan.json"];
|
|
95
104
|
|
|
96
105
|
// Clear or ensure build dir
|
|
97
106
|
if (fs.existsSync(buildDir)) {
|
|
@@ -111,11 +120,19 @@ export async function release(root = process.cwd()) {
|
|
|
111
120
|
}
|
|
112
121
|
}
|
|
113
122
|
|
|
114
|
-
// 3. Copy package.json
|
|
123
|
+
// 3. Copy package.json & tanfig.json
|
|
115
124
|
const pkgPath = path.join(root, "package.json");
|
|
116
125
|
if (fs.existsSync(pkgPath)) {
|
|
117
126
|
fs.copyFileSync(pkgPath, path.join(buildDir, "package.json"));
|
|
118
127
|
}
|
|
128
|
+
const tanfigPath = path.join(root, "tanfig.json");
|
|
129
|
+
if (fs.existsSync(tanfigPath)) {
|
|
130
|
+
fs.copyFileSync(tanfigPath, path.join(buildDir, "tanfig.json"));
|
|
131
|
+
}
|
|
132
|
+
const titanConfigPath = path.join(root, "titan.json");
|
|
133
|
+
if (fs.existsSync(titanConfigPath)) {
|
|
134
|
+
fs.copyFileSync(titanConfigPath, path.join(buildDir, "titan.json"));
|
|
135
|
+
}
|
|
119
136
|
|
|
120
137
|
// 4. Create .env
|
|
121
138
|
fs.writeFileSync(path.join(buildDir, ".env"), "TITAN_DEV=0\n");
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@titanpl/sdk",
|
|
3
|
+
"version": "7.0.0-beta",
|
|
4
|
+
"description": "The official SDK for Titan Planet extensions and testing.",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "index.js",
|
|
7
|
+
"exports": {
|
|
8
|
+
".": "./index.js",
|
|
9
|
+
"./test": "./test/index.js"
|
|
10
|
+
},
|
|
11
|
+
"keywords": [
|
|
12
|
+
"titanpl",
|
|
13
|
+
"titan",
|
|
14
|
+
"sdk"
|
|
15
|
+
],
|
|
16
|
+
"author": "ezetgalaxy",
|
|
17
|
+
"license": "ISC"
|
|
18
|
+
}
|
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
import fs from 'fs';
|
|
2
|
+
import path from 'path';
|
|
3
|
+
import vm from 'node:vm';
|
|
4
|
+
import { fileURLToPath } from 'url';
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Creates a lightweight production-grade test environment for Titan extensions.
|
|
8
|
+
* Provides isolation via node:vm and a full t-object emulation.
|
|
9
|
+
*/
|
|
10
|
+
export async function createTestEnv(options) {
|
|
11
|
+
const { extPath, allowWasm = false, allowNative = false } = options;
|
|
12
|
+
const absolutePath = path.resolve(extPath);
|
|
13
|
+
const titanJsonPath = path.join(absolutePath, 'titan.json');
|
|
14
|
+
|
|
15
|
+
if (!fs.existsSync(titanJsonPath)) {
|
|
16
|
+
throw new Error(`[@titanpl/sdk/test] titan.json not found at ${absolutePath}`);
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
const titanJson = JSON.parse(fs.readFileSync(titanJsonPath, 'utf8'));
|
|
20
|
+
|
|
21
|
+
// Create the global 't' mock
|
|
22
|
+
const tMock = {
|
|
23
|
+
_logs: [],
|
|
24
|
+
_calls: [],
|
|
25
|
+
log: (name, ...args) => {
|
|
26
|
+
const entry = `[${name}] ${args.join(' ')}`;
|
|
27
|
+
tMock._logs.push(entry);
|
|
28
|
+
console.log('\x1b[36m%s\x1b[0m', entry);
|
|
29
|
+
},
|
|
30
|
+
__native: {
|
|
31
|
+
call: async (ext, fn, args) => {
|
|
32
|
+
if (!allowNative) throw new Error(`[@titanpl/sdk/test] Native call blocked (allowNative: false)`);
|
|
33
|
+
tMock._calls.push({ type: 'native', ext, fn, args });
|
|
34
|
+
return `[MOCK_NATIVE_RESULT]`;
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
};
|
|
38
|
+
|
|
39
|
+
// Create a VM context
|
|
40
|
+
const context = {
|
|
41
|
+
t: tMock,
|
|
42
|
+
global: {},
|
|
43
|
+
globalThis: {},
|
|
44
|
+
console: console,
|
|
45
|
+
setTimeout,
|
|
46
|
+
clearTimeout,
|
|
47
|
+
process: { env: { ...process.env } }
|
|
48
|
+
};
|
|
49
|
+
context.global = context;
|
|
50
|
+
context.globalThis = context;
|
|
51
|
+
|
|
52
|
+
vm.createContext(context);
|
|
53
|
+
|
|
54
|
+
// Load extension entry
|
|
55
|
+
const entryPath = path.join(absolutePath, titanJson.entry);
|
|
56
|
+
const code = fs.readFileSync(entryPath, 'utf8');
|
|
57
|
+
|
|
58
|
+
// Resolve relative imports within the extension
|
|
59
|
+
// Simple loader: replace relative imports with absolute ones or mock them
|
|
60
|
+
// For a real production-ready test env, we'd use a custom loader or compile with ESBuild.
|
|
61
|
+
// For now, we'll use a functional script wrapper.
|
|
62
|
+
|
|
63
|
+
const script = new vm.Script(`
|
|
64
|
+
(async () => {
|
|
65
|
+
${code.replace(/import\s+{([^}]+)}\s+from\s+'\.\/utils\/registerExtension\.js'/g, 'const {$1} = t._registerHelper;')}
|
|
66
|
+
})()
|
|
67
|
+
`);
|
|
68
|
+
|
|
69
|
+
// Add registration helper to 't'
|
|
70
|
+
tMock._registerHelper = {
|
|
71
|
+
registerExtension: (name, module) => {
|
|
72
|
+
tMock[name] = module;
|
|
73
|
+
console.log(`[@titanpl/sdk/test] Registered extension: ${name}`);
|
|
74
|
+
}
|
|
75
|
+
};
|
|
76
|
+
|
|
77
|
+
try {
|
|
78
|
+
await script.runInContext(context);
|
|
79
|
+
} catch (err) {
|
|
80
|
+
console.error(`[@titanpl/sdk/test] Runtime error in extension '${titanJson.name}':`, err);
|
|
81
|
+
throw err;
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
return {
|
|
85
|
+
/**
|
|
86
|
+
* Call an extension method
|
|
87
|
+
*/
|
|
88
|
+
call: async (path, args = []) => {
|
|
89
|
+
const [extName, methodName] = path.split('.');
|
|
90
|
+
if (!tMock[extName]) throw new Error(`Extension '${extName}' not registered`);
|
|
91
|
+
if (!tMock[extName][methodName]) throw new Error(`Method '${methodName}' not found on extension '${extName}'`);
|
|
92
|
+
|
|
93
|
+
return await tMock[extName][methodName](...args);
|
|
94
|
+
},
|
|
95
|
+
|
|
96
|
+
/**
|
|
97
|
+
* Assert a method result
|
|
98
|
+
*/
|
|
99
|
+
assert: async (path, args, expected) => {
|
|
100
|
+
const result = await tMock.call(path, args);
|
|
101
|
+
if (JSON.stringify(result) !== JSON.stringify(expected)) {
|
|
102
|
+
throw new Error(`Assertion Failed for ${path}\nExpected: ${JSON.stringify(expected)}\nActual: ${JSON.stringify(result)}`);
|
|
103
|
+
}
|
|
104
|
+
console.log(`\x1b[32m✔ Assertion Passed: ${path}\x1b[0m`);
|
|
105
|
+
},
|
|
106
|
+
|
|
107
|
+
/**
|
|
108
|
+
* Get all logs captured during execution
|
|
109
|
+
*/
|
|
110
|
+
getLogs: () => tMock._logs,
|
|
111
|
+
|
|
112
|
+
/**
|
|
113
|
+
* Teardown the environment
|
|
114
|
+
*/
|
|
115
|
+
teardown: async () => {
|
|
116
|
+
// Cleanup context and references
|
|
117
|
+
for (const key in tMock) delete tMock[key];
|
|
118
|
+
}
|
|
119
|
+
};
|
|
120
|
+
}
|
|
@@ -1,14 +1,18 @@
|
|
|
1
|
-
{
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
1
|
+
{
|
|
2
|
+
"name": "{{name}}",
|
|
3
|
+
"description": "A powerful TitanPL project",
|
|
4
|
+
"version": "1.0.0",
|
|
5
|
+
"extensions": {
|
|
6
|
+
"allowWasm": false,
|
|
7
|
+
"allowNative": []
|
|
8
|
+
},
|
|
9
|
+
"build": {
|
|
10
|
+
"purpose": "test",
|
|
11
|
+
"files": [
|
|
12
|
+
"public",
|
|
13
|
+
"static",
|
|
14
|
+
"db",
|
|
15
|
+
"tanfig.json"
|
|
16
|
+
]
|
|
17
|
+
}
|
|
14
18
|
}
|
|
@@ -1,27 +1,31 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
1
|
+
/**
|
|
2
|
+
* @package ext-template
|
|
3
|
+
* Professional extension template for the TitanPL framework.
|
|
4
|
+
*/
|
|
3
5
|
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
6
|
+
/** Main configuration interface */
|
|
7
|
+
export interface Config {
|
|
8
|
+
/** Secure key or secret */
|
|
9
|
+
secret?: string;
|
|
10
|
+
/** Custom logging function */
|
|
11
|
+
log?: (msg: string) => void;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
/** Standard Success Response */
|
|
15
|
+
export interface Result {
|
|
16
|
+
result: string;
|
|
17
|
+
status: "ok" | "error";
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
/** Main Extension class */
|
|
21
|
+
declare class Extension {
|
|
22
|
+
constructor(config?: Config);
|
|
15
23
|
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
*/
|
|
19
|
-
calc(a: number, b: number): number;
|
|
24
|
+
/** Hash a string synchronously using bcryptjs */
|
|
25
|
+
hash(data: string): string;
|
|
20
26
|
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
}
|
|
24
|
-
}
|
|
27
|
+
/** Standard execution for processing input */
|
|
28
|
+
execute(input: string): Result;
|
|
25
29
|
}
|
|
26
30
|
|
|
27
|
-
export
|
|
31
|
+
export default Extension;
|
|
@@ -1,17 +1,17 @@
|
|
|
1
|
-
|
|
2
|
-
if (typeof Titan === "undefined") globalThis.Titan = t;
|
|
3
|
-
const EXT_KEY = "{{name}}";
|
|
1
|
+
import { registerExtension } from './utils/registerExtension.js';
|
|
4
2
|
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
// Example Wrapper for Native function
|
|
13
|
-
calc: function (a, b) {
|
|
14
|
-
// Assumes the native function 'add' is mapped in titan.json
|
|
15
|
-
return t[EXT_KEY].add(a, b);
|
|
3
|
+
const myExt = {
|
|
4
|
+
/**
|
|
5
|
+
* A sample function that can be called from any Titan Action.
|
|
6
|
+
*/
|
|
7
|
+
hello: () => {
|
|
8
|
+
t.log("{{name}}", "Hello from extension!");
|
|
9
|
+
return "hello";
|
|
16
10
|
}
|
|
17
|
-
}
|
|
11
|
+
};
|
|
12
|
+
|
|
13
|
+
// If this is a Wasm or Native extension, bindings will be injected here during build.
|
|
14
|
+
// Use 'titan build ext' to generate them.
|
|
15
|
+
|
|
16
|
+
registerExtension("{{name}}", myExt);
|
|
17
|
+
export default myExt;
|
|
@@ -1,9 +1,11 @@
|
|
|
1
1
|
[package]
|
|
2
|
-
name = "
|
|
3
|
-
version = "
|
|
4
|
-
edition = "
|
|
2
|
+
name = "my-extension-native"
|
|
3
|
+
version = "1.0.0"
|
|
4
|
+
edition = "2021"
|
|
5
5
|
|
|
6
6
|
[lib]
|
|
7
7
|
crate-type = ["cdylib"]
|
|
8
8
|
|
|
9
9
|
[dependencies]
|
|
10
|
+
serde = { version = "1.0", features = ["derive"] }
|
|
11
|
+
serde_json = "1.0"
|
|
@@ -1,26 +1,16 @@
|
|
|
1
1
|
{
|
|
2
|
-
"name": "
|
|
3
|
-
"version": "
|
|
4
|
-
"description": "A
|
|
2
|
+
"name": "my-extension",
|
|
3
|
+
"version": "7.0.0-beta",
|
|
4
|
+
"description": "A high-performance TitanPL extension.",
|
|
5
|
+
"type": "module",
|
|
5
6
|
"main": "index.js",
|
|
6
|
-
"
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
"
|
|
10
|
-
|
|
11
|
-
"keywords": [
|
|
12
|
-
"titan planet",
|
|
13
|
-
"extension"
|
|
7
|
+
"files": [
|
|
8
|
+
"index.js",
|
|
9
|
+
"titan.json",
|
|
10
|
+
"jsconfig.json",
|
|
11
|
+
"README.md"
|
|
14
12
|
],
|
|
15
|
-
"author": "",
|
|
16
|
-
"license": "ISC",
|
|
17
13
|
"dependencies": {
|
|
18
|
-
"@titanpl/
|
|
19
|
-
"chokidar": "^5.0.0",
|
|
20
|
-
"esbuild": "^0.27.2",
|
|
21
|
-
"titanpl-sdk": "6.0.0"
|
|
22
|
-
},
|
|
23
|
-
"devDependencies": {
|
|
24
|
-
"@tgrv/microgravity": "latest"
|
|
14
|
+
"@titanpl/sdk": "7.0.0-beta"
|
|
25
15
|
}
|
|
26
16
|
}
|
|
@@ -1,18 +1,7 @@
|
|
|
1
1
|
{
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
"functions": {
|
|
8
|
-
"add": {
|
|
9
|
-
"symbol": "add",
|
|
10
|
-
"parameters": [
|
|
11
|
-
"f64",
|
|
12
|
-
"f64"
|
|
13
|
-
],
|
|
14
|
-
"result": "f64"
|
|
15
|
-
}
|
|
16
|
-
}
|
|
17
|
-
}
|
|
2
|
+
"name": "my-extension",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"type": "wasm",
|
|
5
|
+
"entry": "index.js",
|
|
6
|
+
"description": "A high-performance TitanPL extension."
|
|
18
7
|
}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
// utils/registerExtension.js
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Safely registers an extension in the global t object
|
|
5
|
+
* @param {string} extensionName - Unique name for the extension
|
|
6
|
+
* @param {any} extensionModule - The extension module/object to register
|
|
7
|
+
* @returns {boolean} True if registration was successful
|
|
8
|
+
*/
|
|
9
|
+
export function registerExtension(extensionName, extensionModule) {
|
|
10
|
+
// Check for global t object
|
|
11
|
+
if (typeof t === 'undefined') {
|
|
12
|
+
console.warn(`[registerExtension] Global 't' object not available. Cannot register: ${extensionName}`);
|
|
13
|
+
return false;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
// Input validation
|
|
17
|
+
if (!extensionName || typeof extensionName !== 'string') {
|
|
18
|
+
console.error('[registerExtension] Invalid extension name provided');
|
|
19
|
+
return false;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
// Check for naming conflicts
|
|
23
|
+
if (t[extensionName]) {
|
|
24
|
+
console.warn(`[registerExtension] '${extensionName}' already exists in global t object, overwriting`);
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
try {
|
|
28
|
+
// Register the extension
|
|
29
|
+
t[extensionName] = extensionModule;
|
|
30
|
+
|
|
31
|
+
console.log(`[registerExtension] Successfully registered '${extensionName}'`);
|
|
32
|
+
|
|
33
|
+
return true;
|
|
34
|
+
} catch (error) {
|
|
35
|
+
// Structured error reporting
|
|
36
|
+
console.error(`[registerExtension] Failed to register '${extensionName}':`, {
|
|
37
|
+
error: error.message,
|
|
38
|
+
extensionName,
|
|
39
|
+
moduleType: typeof extensionModule
|
|
40
|
+
});
|
|
41
|
+
|
|
42
|
+
return false;
|
|
43
|
+
}
|
|
44
|
+
}
|
|
@@ -6,16 +6,16 @@
|
|
|
6
6
|
"template": "js"
|
|
7
7
|
},
|
|
8
8
|
"dependencies": {
|
|
9
|
-
"@titanpl/cli": "
|
|
10
|
-
"@titanpl/route": "
|
|
11
|
-
"@titanpl/native": "
|
|
9
|
+
"@titanpl/cli": "7.0.0-beta",
|
|
10
|
+
"@titanpl/route": "7.0.0-beta",
|
|
11
|
+
"@titanpl/native": "7.0.0-beta",
|
|
12
12
|
"@titanpl/core": "latest",
|
|
13
13
|
"@titanpl/node": "latest",
|
|
14
|
-
"@titanpl/packet": "
|
|
14
|
+
"@titanpl/packet": "7.0.0-beta"
|
|
15
15
|
},
|
|
16
16
|
"optionalDependencies": {
|
|
17
|
-
"@titanpl/engine-linux-x64": "
|
|
18
|
-
"@titanpl/engine-win32-x64": "
|
|
17
|
+
"@titanpl/engine-linux-x64": "7.0.0-beta",
|
|
18
|
+
"@titanpl/engine-win32-x64": "7.0.0-beta"
|
|
19
19
|
},
|
|
20
20
|
"scripts": {
|
|
21
21
|
"build": "titan build",
|
|
@@ -28,5 +28,5 @@
|
|
|
28
28
|
"eslint": "^9.39.2",
|
|
29
29
|
"eslint-plugin-titanpl": "latest"
|
|
30
30
|
},
|
|
31
|
-
"version": "
|
|
31
|
+
"version": "7.0.0-beta"
|
|
32
32
|
}
|
|
@@ -1,15 +1,15 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "titanpl",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "7.0.0-beta",
|
|
4
4
|
"description": "A Titan Planet server",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"titan": {
|
|
7
7
|
"template": "rust-js"
|
|
8
8
|
},
|
|
9
9
|
"dependencies": {
|
|
10
|
-
"@titanpl/cli": "
|
|
11
|
-
"@titanpl/route": "
|
|
12
|
-
"@titanpl/native": "
|
|
10
|
+
"@titanpl/cli": "7.0.0-beta",
|
|
11
|
+
"@titanpl/route": "7.0.0-beta",
|
|
12
|
+
"@titanpl/native": "7.0.0-beta",
|
|
13
13
|
"@titanpl/core": "latest",
|
|
14
14
|
"@titanpl/node": "latest"
|
|
15
15
|
},
|
|
@@ -1,15 +1,15 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "titanpl",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "7.0.0-beta",
|
|
4
4
|
"description": "A Titan Planet server (Rust + TypeScript)",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"titan": {
|
|
7
7
|
"template": "rust-ts"
|
|
8
8
|
},
|
|
9
9
|
"dependencies": {
|
|
10
|
-
"@titanpl/cli": "
|
|
11
|
-
"@titanpl/route": "
|
|
12
|
-
"@titanpl/native": "
|
|
10
|
+
"@titanpl/cli": "7.0.0-beta",
|
|
11
|
+
"@titanpl/route": "7.0.0-beta",
|
|
12
|
+
"@titanpl/native": "7.0.0-beta",
|
|
13
13
|
"@titanpl/core": "latest",
|
|
14
14
|
"@titanpl/node": "latest",
|
|
15
15
|
"typescript": "^5.0.0"
|