diff --git a/.gitignore b/.gitignore
index 415b7c79..988754a8 100644
--- a/.gitignore
+++ b/.gitignore
@@ -2,11 +2,27 @@
.idea
.DS_Store
-build/
-src/bundles/js/
-src/js/core.js
-src/js/std.js
-src/version.h
-node_modules/
-docs/api/
-test_dir*/
+/build/
+/src/bundles/js/
+/src/js/core.js
+/src/js/std.js
+/src/version.h
+/node_modules/
+/docs/api/
+/test_dir*/
+
+#External modules
+/benchmark/extras/
+/deps/extras/
+/examples/extras/
+/tests/extras/
+/src/bundles/c/extras/
+/src/js/extras/
+/src/extras/
+/extras/
+/docs/types/extras/
+
+/src/*.c.frag
+
+#Module files
+modules.json
\ No newline at end of file
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 0b96e00e..38a8a18e 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -2,6 +2,13 @@ cmake_minimum_required(VERSION 3.14)
project(tjs LANGUAGES C)
+if(IS_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/deps/extras")
+ enable_language(CXX)
+ set(CMAKE_CXX_STANDARD_REQUIRED ON)
+ set(CMAKE_CXX_EXTENSIONS ON)
+ set(CMAKE_CXX_STANDARD 20)
+endif()
+
include(ExternalProject)
include(GNUInstallDirs)
@@ -16,6 +23,8 @@ set(CMAKE_C_STANDARD_REQUIRED ON)
set(CMAKE_C_EXTENSIONS ON)
set(CMAKE_C_STANDARD 11)
+
+
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
list(APPEND tjs_cflags -Wall -g)
@@ -57,6 +66,10 @@ add_subdirectory(deps/sqlite3 EXCLUDE_FROM_ALL)
set(BUILD_WASI "simple" CACHE STRING "WASI implementation")
add_subdirectory(deps/wasm3 EXCLUDE_FROM_ALL)
+if(IS_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/deps/extras")
+ add_subdirectory(deps/extras EXCLUDE_FROM_ALL)
+endif()
+
if(BUILD_WITH_MIMALLOC)
option(MI_OVERRIDE "" OFF)
option(MI_BUILD_SHARED "" OFF)
@@ -68,6 +81,9 @@ endif()
find_package(CURL REQUIRED)
+file(GLOB_RECURSE src_extras "src/extras/**/*.c" "src/extras/**/*.cpp")
+file(GLOB src_bundles_extras "src/bundles/c/extras/*.c")
+
add_library(tjs STATIC
src/builtins.c
src/curl-utils.c
@@ -100,6 +116,8 @@ add_library(tjs STATIC
src/bundles/c/core/polyfills.c
src/bundles/c/core/run-main.c
src/bundles/c/core/worker-bootstrap.c
+ ${src_extras}
+ ${src_bundles_extras}
deps/quickjs/cutils.c
)
@@ -152,7 +170,8 @@ target_compile_options(tjs PRIVATE ${tjs_cflags})
target_compile_definitions(tjs PRIVATE TJS__PLATFORM="${TJS_PLATFORM}")
target_include_directories(tjs PRIVATE ${CURL_INCLUDE_DIRS})
target_include_directories(tjs PUBLIC src)
-target_link_libraries(tjs qjs uv_a m3 sqlite3 m pthread ${CURL_LIBRARIES})
+target_include_directories(tjs PRIVATE deps)
+target_link_libraries(tjs qjs uv_a m3 sqlite3 m pthread ${CURL_LIBRARIES} ${EXTRA_MODULES})
if (BUILD_WITH_MIMALLOC)
target_compile_definitions(tjs PRIVATE TJS__HAS_MIMALLOC)
@@ -170,4 +189,4 @@ set_target_properties(tjs-cli
add_executable(tjsc EXCLUDE_FROM_ALL
src/qjsc.c
)
-target_link_libraries(tjsc qjs m)
+target_link_libraries(tjsc qjs m)
\ No newline at end of file
diff --git a/Makefile b/Makefile
index 6679ed6f..e5ed08f7 100644
--- a/Makefile
+++ b/Makefile
@@ -6,6 +6,7 @@ JS_NO_STRIP?=0
TJS=$(BUILD_DIR)/tjs
QJSC=$(BUILD_DIR)/tjsc
STDLIB_MODULES=$(wildcard src/js/stdlib/*.js)
+EXTRAS_MODULES=$(wildcard src/js/extras/*.js)
ESBUILD?=npx esbuild
ESBUILD_PARAMS_COMMON=--target=es2022 --platform=neutral --format=esm --main-fields=main,module
ESBUILD_PARAMS_MINIFY=--minify
@@ -109,18 +110,29 @@ src/bundles/js/stdlib/%.js: src/js/stdlib/*.js src/js/stdlib/ffi/*.js
$(ESBUILD_PARAMS_MINIFY) \
$(ESBUILD_PARAMS_COMMON)
-src/bundles/c/stdlib/%.c: $(QJSC) src/bundles/js/stdlib/%.js
+src/bundles/c/extras/%.c: $(QJSC) src/bundles/js/extras/%.js
@mkdir -p $(basename $(dir $@))
$(QJSC) -m \
$(QJSC_PARAMS_STIP) \
-o $@ \
-n "tjs:$(basename $(notdir $@))" \
-p tjs__ \
- src/bundles/js/stdlib/$(basename $(notdir $@)).js
+ src/bundles/js/extras/$(basename $(notdir $@)).js
+
+src/bundles/js/extras/%.js: src/js/extras/*.js
+ $(ESBUILD) src/js/extras/$(notdir $@) \
+ --bundle \
+ --outfile=$@ \
+ --external:buffer \
+ --external:crypto \
+ --external:"tjs:*" \
+ $(ESBUILD_PARAMS_MINIFY) \
+ $(ESBUILD_PARAMS_COMMON)
stdlib: $(addprefix src/bundles/c/stdlib/, $(patsubst %.js, %.c, $(notdir $(STDLIB_MODULES))))
+extras: $(addprefix src/bundles/c/extras/, $(patsubst %.js, %.c, $(notdir $(EXTRAS_MODULES))))
-js: core stdlib
+js: core stdlib extras
install: $(TJS)
cmake --build $(BUILD_DIR) --target install
@@ -140,10 +152,11 @@ format:
test:
./$(BUILD_DIR)/tjs test tests/
+ if [ -d "tests/extras" ]; then ./$(BUILD_DIR)/tjs test tests/extras/; fi
test-advanced:
cd tests/advanced && npm install
./$(BUILD_DIR)/tjs test tests/advanced/
-.PRECIOUS: src/bundles/js/core/%.js src/bundles/js/stdlib/%.js
-.PHONY: all js debug install clean distclean format test test-advanced core stdlib $(TJS)
+.PRECIOUS: src/bundles/js/core/%.js src/bundles/js/stdlib/%.js src/bundles/js/extras/%.js
+.PHONY: all js debug install clean distclean format test test-advanced core stdlib extras $(TJS)
\ No newline at end of file
diff --git a/deps/quickjs b/deps/quickjs
index 99c6719b..accd2d57 160000
--- a/deps/quickjs
+++ b/deps/quickjs
@@ -1 +1 @@
-Subproject commit 99c6719b7d2fe5aba4e9ff28936173fd0c4f2805
+Subproject commit accd2d5758694cdc4f0e1a2f5f21e4b5405d4e56
diff --git a/docs/tsconfig.doc.json b/docs/tsconfig.doc.json
index ca3cd296..d04634fc 100644
--- a/docs/tsconfig.doc.json
+++ b/docs/tsconfig.doc.json
@@ -1,18 +1,22 @@
{
- "compilerOptions": {
- "lib": ["ES2020", "dom"],
- "noImplicitAny": true
- },
- "typedocOptions": {
- "name": "txiki.js",
- "entryPoints": [ "types/" ],
- "entryPointStrategy": "expand",
- "out": "api/",
- "readme": "intro.md",
- "disableSources": true,
- "exclude":["types/index.d.ts"]
- },
- "watchOptions": {
- "excludeDirectories": ["api/*"]
- }
+ "compilerOptions": {
+ "lib": ["ES2020", "dom"],
+ "target": "ESNext",
+ "noImplicitAny": true,
+ "baseUrl": ".",
+ "typeRoots": ["./node_modules/@types"]
+ },
+ "typedocOptions": {
+ "name": "txiki.js",
+ "entryPoints": ["types/"],
+ "entryPointStrategy": "expand",
+ "out": "api/",
+ "readme": "intro.md",
+ "disableSources": true,
+ "exclude": ["types/index.d.ts"]
+ },
+ "watchOptions": {
+ "excludeDirectories": ["api/*"]
+ },
+ "include": ["types/**/*.ts"]
}
diff --git a/docs/types/index.d.ts b/docs/types/index.d.ts
index 0f0811cc..5bfcf107 100644
--- a/docs/types/index.d.ts
+++ b/docs/types/index.d.ts
@@ -1,11 +1,12 @@
-///
-///
-///
-///
-///
-///
-///
-///
-///
+import "./txikijs.d.ts"
+import "./assert.d.ts"
+import "./ffi.d.ts"
+import "./getopts.d.ts"
+import "./hashing.d.ts"
+import "./ipaddr.d.ts"
+import "./path.d.ts"
+import "./sqlite.d.ts"
+import "./uuid.d.ts"
+import "./extras/index.d.ts"
export {};
diff --git a/extras-helper.mjs b/extras-helper.mjs
new file mode 100755
index 00000000..69a73537
--- /dev/null
+++ b/extras-helper.mjs
@@ -0,0 +1,285 @@
+#!/bin/env node
+/**
+The MIT License (MIT)
+
+Copyright (c) 2024-present karurochari
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
+*/
+
+let STRICT = false;
+const protocol_version = [2, 2, 0]
+//TODO: take this from the makefile? There must be a better way to handle this.
+const runtime_version = [23, 12, 0]
+
+import { readFile, writeFile, mkdir, rm, cp } from 'node:fs/promises'
+import { existsSync } from 'node:fs';
+
+import { dirname } from 'node:path'
+import util from 'node:util';
+
+import { program } from 'commander';
+import { exec as _exec } from 'node:child_process';
+const exec = util.promisify(_exec);
+
+import { Readable } from 'node:stream'
+import fg from 'fast-glob'
+
+/**
+ * It checks the version of the runtime & module interface against the one presented by a module
+ * @param {string} name
+ * @param {[number,number,number]|undefined} modprotocol_version
+ * @param {[number,number,number]|undefined} runtime_version
+ * @param {boolean} strict
+ * @returns {boolean} True if versions are matching
+ */
+function check_versions(strict, name, modprotocol_version, runtime_version) {
+ if (strict === true) {
+ if (modprotocol_version === undefined) {
+ console.error(
+ `Module is not versioned against the module protocol.`,
+ );
+ return false;
+ }
+ if (runtime_version === undefined) {
+ console.error(
+ `Module is not versioned against the runtime.`,
+ );
+ return false;
+ }
+ }
+ else {
+ if (modprotocol_version === undefined)
+ console.warn(
+ `Module has no protocol version reported. It might end up being incompatible`,
+ );
+ if (runtime_version === undefined)
+ console.warn(
+ `Module has no runtime version reported. It might end up being incompatible`,
+ );
+ }
+
+ //TODO: Add any logic to be determined to ensure compatibility here.
+ return true;
+}
+
+/**
+ * Recover a native dependency from a git server.
+ * @param {string} name Name of the submodule
+ * @param {string} url Source
+ * @param {string} branch Branch/Tag
+ */
+async function clone_shallow(name, url, branch) {
+ await rm(`./deps/extras/${name}`, { recursive: true, force: true })
+ await exec(`git clone --recurse-submodules --shallow-submodules --depth 1 --single-branch --branch ${branch} ${url} ./deps/extras/${name}`);
+}
+
+async function copy_template(path, subdir) {
+ const files = await fg(`./extras/${path}/${subdir}/*.js`);
+ const prefix = `./${subdir}/${path}/${subdir}/`.length
+ const suffix = ".js".length
+ for (const file of files) {
+ const name = file.substring(prefix, file.length - suffix).replaceAll("[module]", path)
+ await writeFile(`./${subdir}/extras/${name}.js`, ((await readFile(file)).toString().replaceAll('__MODULE__', path)))
+ }
+}
+
+
+async function retrieve(name, path, prefix) {
+ //From the internet
+ if (path.startsWith('https://') || path.startsWith('http://')) {
+ await writeFile(
+ `${prefix}${name}.tar.gz`,
+ Readable.fromWeb(
+ (await fetch(path)).body,
+ ),
+ )
+ await exec(`mkdir ${prefix}${name} && tar -xvzf ${prefix}${name}.tar.gz -C ${prefix}${name} --strip-components=1`);
+ await rm(`${prefix}${name}.tar.gz`)
+ }
+ //Local folder
+ else {
+ await cp(path, `${prefix}${name}`, { recursive: true, dereference: true, errorOnExist: false })
+ }
+}
+
+async function install(path) {
+ let modcfg = {}
+ if (await existsSync(`./extras/${path}/module.json`)) modcfg = JSON.parse((await readFile(`./extras/${path}/module.json`)).toString())
+ if (!check_versions(STRICT, path, modcfg["module-version"], modcfg["runtime-version"])) {
+ console.error(`Unable to properly handle module ${path}`)
+ process.exit(1)
+ }
+
+ const cmake = []
+ const names = []
+
+ for (const [name, info] of Object.entries(modcfg["native-deps"] ?? {})) {
+ if (info.url) {
+ console.log(
+ `Fetch of ${name} @ ${info.url}`,
+ );
+ await retrieve(name, info.url, './deps/extras/')
+ }
+ else {
+ console.log(
+ `Shallow cloning ${name} @ ${info.repo} branch ${info.branch}`,
+ );
+ await clone_shallow(name, info.repo, info.branch);
+ }
+ cmake.push("block()")
+
+ //Build the extras cmake entries
+ for (const item of Object.entries(info.env ?? {})) {
+ //TODO: Evaluate if we want to have escaping, or a better handling of types.
+ //In general all this part is likely to be reworked and extended at some point.
+ const { value, type, force } = item[1]
+ cmake.push(`set(${item[0]} ${value} CACHE ${type} "Handle ${name} ${item[0]} variable" ${force ? 'FORCE' : ''})`)
+ }
+ if (info['raw-cmake']) cmake.push(info['raw-cmake'])
+ cmake.push(`add_subdirectory(./${name} EXCLUDE_FROM_ALL)`)
+ cmake.push("endblock()")
+ names.push(...(info.symbols ?? [name]))
+ }
+
+ await mkdir(`src/extras/${path}`, { errorOnExist: false });
+
+ //Copy over all files in src
+ {
+ const files = await fg(`./extras/${path}/src/**/*`);
+ const prefix = `./extras/${path}/src/`.length
+ for (const file of files) {
+ const name = file.substring(prefix).replaceAll("[module]", path)
+ const fullPath = `./src/extras/${path}/${name}`
+ await mkdir(dirname(fullPath), { errorOnExist: false, recursive: true });
+ await writeFile(fullPath, ((await readFile(file)).toString().replaceAll('__MODULE__', path)))
+
+ }
+ }
+
+ //While js/ts files must be already reduced in a bundle by this point.
+ await writeFile(`./src/js/extras/${path}.js`, ((await readFile(`./extras/${path}/bundle/[module].js`)).toString().replaceAll('__MODULE__', path)))
+ await writeFile(`./docs/types/extras/${path}.d.ts`, ((await readFile(`./extras/${path}/bundle/[module].d.ts`)).toString().replaceAll('__MODULE__', path)))
+ await copy_template(path, 'examples')
+ await copy_template(path, 'benchmarks')
+ await copy_template(path, 'tests')
+
+
+ return { cmake: cmake, names: names }
+}
+
+async function clear() {
+ await rm('extras/', { recursive: true, force: true });
+ await rm('src/extras/', { recursive: true, force: true });
+ await rm('src/js/extras/', { recursive: true, force: true });
+ await rm('tests/extras/', { recursive: true, force: true });
+ await rm('examples/extras/', { recursive: true, force: true });
+ await rm('deps/extras/', { recursive: true, force: true });
+ await rm('benchmark/extras/', { recursive: true, force: true });
+ await rm('docs/types/extras/', { recursive: true, force: true });
+
+ await rm('./src/extras-bootstrap.c.frag', { force: true })
+ await rm('./src/extras-headers.c.frag', { force: true })
+ await rm('./src/extras-bundles.c.frag', { force: true })
+ await rm('./src/extras-entries.c.frag', { force: true })
+}
+
+program
+ .name('extras-helper.mjs')
+ .description('A CLI to customize your txiki distribution')
+
+program.command('clear')
+ .description('Clear after your previous configuration')
+ .action(async () => {
+ await clear()
+ })
+
+program.command('refresh')
+ .description('Refresh a single module, keeping the rest the same')
+ .argument("", 'module name ')
+ .argument("[filename]", 'filename for the configuration', './modules.json')
+ .option("-s, --strict", "Force checks for versions")
+ .action(async (modname, filename, options) => {
+ STRICT = options.strict
+ let config = undefined
+ try {
+ config = JSON.parse(await readFile(filename))
+ }
+ catch (e) {
+ console.error("Unable to parse the config file.")
+ process.exit(1)
+ }
+
+ await retrieve(modname, config[modname], './extras/')
+ await install(modname)
+ })
+
+program.command('clone')
+ .description('Clear after your previous configuration')
+ .argument("[filename]", 'filename for the configuration', './modules.json')
+ .option("-s, --strict", "Force checks for versions")
+ .action(async (filename, options) => {
+ STRICT = options.strict
+ //For now, since I am too lazy to handle merging
+ await clear()
+
+ await mkdir("extras/", { errorOnExist: false });
+ await mkdir('src/extras/', { errorOnExist: false });
+ await mkdir('src/js/extras/', { errorOnExist: false });
+ await mkdir('tests/extras/', { errorOnExist: false });
+ await mkdir('examples/extras/', { errorOnExist: false });
+ await mkdir('deps/extras/', { errorOnExist: false });
+ await mkdir('benchmark/extras/', { errorOnExist: false });
+ await mkdir('docs/types/extras/', { errorOnExist: false });
+
+ let config = undefined
+ try {
+ config = JSON.parse(await readFile(filename))
+ }
+ catch (e) {
+ console.error("Unable to parse the config file.")
+ process.exit(1)
+ }
+
+ const cmake = []
+ const names = []
+
+ for (const module of Object.entries(config)) {
+ await retrieve(module[0], module[1], './extras/')
+ const moduleInfo = (await install(module[0]))
+ cmake.push(moduleInfo.cmake.join('\n'))
+ names.push(...moduleInfo.names)
+ }
+
+ //Placeholder for now
+ await writeFile('deps/extras/CMakeLists.txt', `${cmake.join("\n")}\nset(EXTRA_MODULES "${names.join(' ')}" CACHE STRING "" FORCE)`)
+ await writeFile('./modules.json', JSON.stringify(config, null, 4))
+
+ //Construct src/extras.bootstrap to initialize the extra modules
+ await writeFile('./src/extras-bootstrap.c.frag', Object.keys(config).map(x => `tjs__mod_${x}_init(ctx, ns);`).join('\n'))
+ await writeFile('./src/extras-headers.c.frag', Object.keys(config).map(x => `#include "./extras/${x}/module.h"`).join('\n'))
+ await writeFile('./src/extras-bundles.c.frag', Object.keys(config).map(x => `#include "bundles/c/extras/${x}.c"`).join('\n'))
+ await writeFile('./src/extras-entries.c.frag', Object.keys(config).map(x => `{ "tjs:${x}", tjs__${x}, tjs__${x}_size},`).join('\n'))
+
+ //Construct the ts header
+ await writeFile('./docs/types/extras/index.d.ts', Object.keys(config).map(x => `import "./${x}.d.ts";`).join('\n'))
+ })
+
+
+program.parse();
diff --git a/package-lock.json b/package-lock.json
index 2cf273ba..e308edf5 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -33,6 +33,8 @@
"whatwg-url": "^14.0.0"
},
"devDependencies": {
+ "commander": "^12.0.0",
+ "fast-glob": "^3.3.2",
"typedoc": "^0.25.2"
}
},
@@ -686,9 +688,13 @@
"integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU="
},
"node_modules/commander": {
- "version": "2.20.3",
- "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz",
- "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ=="
+ "version": "12.0.0",
+ "resolved": "https://registry.npmjs.org/commander/-/commander-12.0.0.tgz",
+ "integrity": "sha512-MwVNWlYjDTtOjX5PiD7o5pK0UrFU/OYgcJfjjK4RaHZETNtjJqrZa9Y9ds88+A+f+d5lv+561eZ+yCKoS3gbAA==",
+ "dev": true,
+ "engines": {
+ "node": ">=18"
+ }
},
"node_modules/commondir": {
"version": "1.0.1",
@@ -1363,9 +1369,9 @@
"integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q=="
},
"node_modules/fast-glob": {
- "version": "3.2.12",
- "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.2.12.tgz",
- "integrity": "sha512-DVj4CQIYYow0BlaelwK1pHl5n5cRSJfM60UA0zK891sVInoPri2Ekj7+e1CT3/3qxXenpI+nBBmQAcJPJgaj4w==",
+ "version": "3.3.2",
+ "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.2.tgz",
+ "integrity": "sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow==",
"dependencies": {
"@nodelib/fs.stat": "^2.0.2",
"@nodelib/fs.walk": "^1.2.3",
@@ -1626,6 +1632,11 @@
"node": ">=10"
}
},
+ "node_modules/gh-pages/node_modules/commander": {
+ "version": "2.20.3",
+ "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz",
+ "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ=="
+ },
"node_modules/gh-pages/node_modules/fs-extra": {
"version": "8.1.0",
"resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-8.1.0.tgz",
@@ -3465,9 +3476,10 @@
"integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU="
},
"commander": {
- "version": "2.20.3",
- "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz",
- "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ=="
+ "version": "12.0.0",
+ "resolved": "https://registry.npmjs.org/commander/-/commander-12.0.0.tgz",
+ "integrity": "sha512-MwVNWlYjDTtOjX5PiD7o5pK0UrFU/OYgcJfjjK4RaHZETNtjJqrZa9Y9ds88+A+f+d5lv+561eZ+yCKoS3gbAA==",
+ "dev": true
},
"commondir": {
"version": "1.0.1",
@@ -3964,9 +3976,9 @@
"integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q=="
},
"fast-glob": {
- "version": "3.2.12",
- "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.2.12.tgz",
- "integrity": "sha512-DVj4CQIYYow0BlaelwK1pHl5n5cRSJfM60UA0zK891sVInoPri2Ekj7+e1CT3/3qxXenpI+nBBmQAcJPJgaj4w==",
+ "version": "3.3.2",
+ "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.2.tgz",
+ "integrity": "sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow==",
"requires": {
"@nodelib/fs.stat": "^2.0.2",
"@nodelib/fs.walk": "^1.2.3",
@@ -4164,6 +4176,11 @@
"globby": "^6.1.0"
},
"dependencies": {
+ "commander": {
+ "version": "2.20.3",
+ "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz",
+ "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ=="
+ },
"fs-extra": {
"version": "8.1.0",
"resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-8.1.0.tgz",
diff --git a/package.json b/package.json
index 81afc966..74ef12f2 100644
--- a/package.json
+++ b/package.json
@@ -8,6 +8,8 @@
"api-docs": "typedoc --tsconfig docs/tsconfig.doc.json",
"api-docs-watch": "typedoc --tsconfig docs/tsconfig.doc.json --watch --preserveWatchOutput --logLevel Verbose",
"deploy-api-docs": "gh-pages -d docs/api -e api -u \"github-actions-bot \"",
+ "extra-modules-clear": "./extras-helper.mjs clear",
+ "extra-modules-clone": "./extras-helper.mjs clone",
"lint": "eslint --max-warnings 0 ."
},
"license": "MIT",
@@ -35,6 +37,8 @@
"whatwg-url": "^14.0.0"
},
"devDependencies": {
+ "commander": "^12.0.0",
+ "fast-glob": "^3.3.2",
"typedoc": "^0.25.2"
}
}
diff --git a/src/builtins.c b/src/builtins.c
index f55bfd92..f878a69c 100644
--- a/src/builtins.c
+++ b/src/builtins.c
@@ -30,6 +30,11 @@
#include "bundles/c/stdlib/path.c"
#include "bundles/c/stdlib/sqlite.c"
#include "bundles/c/stdlib/uuid.c"
+
+#if __has_include("extras-bundles.c.frag")
+#include "extras-bundles.c.frag"
+#endif
+
#include "private.h"
@@ -48,6 +53,9 @@ static tjs_builtin_t builtins[] = {
{ "tjs:path", tjs__path, tjs__path_size },
{ "tjs:sqlite", tjs__sqlite, tjs__sqlite_size },
{ "tjs:uuid", tjs__uuid, tjs__uuid_size },
+ #if __has_include("extras-entries.c.frag")
+ #include "extras-entries.c.frag"
+ #endif
{ NULL, NULL, 0 },
};
diff --git a/src/private.h b/src/private.h
index 49973ad1..24981a4d 100644
--- a/src/private.h
+++ b/src/private.h
@@ -78,6 +78,9 @@ void tjs__mod_wasm_init(JSContext *ctx, JSValue ns);
void tjs__mod_worker_init(JSContext *ctx, JSValue ns);
void tjs__mod_ws_init(JSContext *ctx, JSValue ns);
void tjs__mod_xhr_init(JSContext *ctx, JSValue ns);
+#if __has_include("extras-headers.c.frag")
+#include "extras-headers.c.frag"
+#endif
#ifndef _WIN32
void tjs__mod_posix_socket_init(JSContext *ctx, JSValue ns);
diff --git a/src/vm.c b/src/vm.c
index bd86dbd3..b90c3ab9 100644
--- a/src/vm.c
+++ b/src/vm.c
@@ -126,6 +126,9 @@ static void tjs__bootstrap_core(JSContext *ctx, JSValue ns) {
#ifndef _WIN32
tjs__mod_posix_socket_init(ctx, ns);
#endif
+ #if __has_include("extras-bootstrap.c.frag")
+ #include "extras-bootstrap.c.frag"
+ #endif
}
JSValue tjs__get_args(JSContext *ctx) {