{
+}
diff --git a/graalwasm/graalwasm-micronaut-excelize/src/main/resources/.gitignore b/graalwasm/graalwasm-micronaut-excelize/src/main/resources/.gitignore
new file mode 100644
index 00000000..e69de29b
diff --git a/graalwasm/graalwasm-micronaut-excelize/src/main/resources/application.properties b/graalwasm/graalwasm-micronaut-excelize/src/main/resources/application.properties
new file mode 100644
index 00000000..fcbe56d0
--- /dev/null
+++ b/graalwasm/graalwasm-micronaut-excelize/src/main/resources/application.properties
@@ -0,0 +1,19 @@
+
+micronaut.application.name=micronautdemo
+
+
+datasources.default.url=jdbc:h2:mem:devDb
+datasources.default.driverClassName=org.h2.Driver
+datasources.default.username=sa
+datasources.default.password=
+datasources.default.dialect=H2
+datasources.default.schema-generate=CREATE_DROP
+
+jpa.default.properties.hibernate.hbm2ddl.auto=update
+jpa.default.properties.hibernate.show_sql=true
+
+
+micronaut.views.enabled=true
+micronaut.views.defaultRenderer=thymeleaf
+
+
diff --git a/graalwasm/graalwasm-micronaut-excelize/src/main/resources/excelize.js b/graalwasm/graalwasm-micronaut-excelize/src/main/resources/excelize.js
new file mode 100644
index 00000000..cb6ab7db
--- /dev/null
+++ b/graalwasm/graalwasm-micronaut-excelize/src/main/resources/excelize.js
@@ -0,0 +1,70 @@
+let f;
+let reader = null;
+global.excelize = {};
+const go = new Go();
+WebAssembly.instantiate(new Uint8Array(wasmBytes), go.importObject).then((result) => {go.run(result.instance);});
+
+function generateExcel(data) {
+ new Promise((resolve, reject) => {
+ f = excelize.NewFile();
+ data.forEach((row, idx) => {
+ const ret1 = excelize.CoordinatesToCellName(1, idx + 1);
+ if (ret1.error) {
+ console.log(ret1.error);
+ reject(ret1.error);
+ return;
+ }
+ const res2 = f.SetSheetRow('Sheet1', ret1.cell, row);
+ if (res2.error) {
+ console.log(res2.error);
+ reject(res2.error);
+ return;
+ }
+ });
+
+
+ const { buffer, error } = f.WriteToBuffer();
+ if (error) {
+ console.error(error);
+ reject(error);
+ } else {
+ // Expose the buffer to Java
+ Polyglot.export("excelBuffer", buffer);
+ resolve(buffer);
+ }
+ })
+
+}
+
+function readExcel(excelFileBytes) {
+ let result ;
+
+ return new Promise((resolve, reject) => {
+
+
+ if(reader == null) reader = excelize.OpenReader(new Uint8Array(excelFileBytes));
+
+
+
+ // Get all rows from Sheet1
+ const ret2 = reader.GetRows('Sheet1');
+ if (ret2.error) {
+ console.error(ret2.error);
+ reject(ret2.error); // Reject promise in case of error
+ } else {
+ // Format the rows into a simple array format for return
+ const resultArray = ret2.result.map(row => row.map(colCell => colCell));
+ //console.log("Extracted data:", resultArray);
+
+
+ // Resolve the promise with the result array
+
+ Polyglot.export("resultArray", resultArray);
+ resolve(resultArray);
+ }
+
+ //console.log("Excel read successfully.");
+
+ });
+}
+
diff --git a/graalwasm/graalwasm-micronaut-excelize/src/main/resources/excelize.wasm b/graalwasm/graalwasm-micronaut-excelize/src/main/resources/excelize.wasm
new file mode 100755
index 00000000..2837a0fa
Binary files /dev/null and b/graalwasm/graalwasm-micronaut-excelize/src/main/resources/excelize.wasm differ
diff --git a/graalwasm/graalwasm-micronaut-excelize/src/main/resources/excelize_m.js b/graalwasm/graalwasm-micronaut-excelize/src/main/resources/excelize_m.js
new file mode 100644
index 00000000..f4227be6
--- /dev/null
+++ b/graalwasm/graalwasm-micronaut-excelize/src/main/resources/excelize_m.js
@@ -0,0 +1,566 @@
+//this file comes from Dmitrii Nikeshkin
+//Github : https://github.com/DimaNike
+
+'use strict';
+
+if (typeof window === 'undefined') {
+ global.crypto = {
+ getRandomValues(b) {
+ return nodeCrypto.randomFillSync(b);
+ }
+ };
+ global.performance = {
+ now() {
+ const [sec, nsec] = process.hrtime();
+ return sec * 1000 + nsec / 1000000;
+ }
+ };
+}
+(() => {
+ const enosys = () => {
+ const err = new Error("not implemented");
+ err.code = "ENOSYS";
+ return err;
+ };
+
+ if (!globalThis.fs) {
+ let outputBuf = "";
+ globalThis.fs = {
+ constants: { O_WRONLY: -1, O_RDWR: -1, O_CREAT: -1, O_TRUNC: -1, O_APPEND: -1, O_EXCL: -1 }, // unused
+ writeSync(fd, buf) {
+ outputBuf += decoder.decode(buf);
+ const nl = outputBuf.lastIndexOf("\n");
+ if (nl != -1) {
+ console.log(outputBuf.substr(0, nl));
+ outputBuf = outputBuf.substr(nl + 1);
+ }
+ return buf.length;
+ },
+ write(fd, buf, offset, length, position, callback) {
+ if (offset !== 0 || length !== buf.length || position !== null) {
+ callback(enosys());
+ return;
+ }
+ const n = this.writeSync(fd, buf);
+ callback(null, n);
+ },
+ chmod(path, mode, callback) { callback(enosys()); },
+ chown(path, uid, gid, callback) { callback(enosys()); },
+ close(fd, callback) { callback(enosys()); },
+ fchmod(fd, mode, callback) { callback(enosys()); },
+ fchown(fd, uid, gid, callback) { callback(enosys()); },
+ fstat(fd, callback) { callback(enosys()); },
+ fsync(fd, callback) { callback(null); },
+ ftruncate(fd, length, callback) { callback(enosys()); },
+ lchown(path, uid, gid, callback) { callback(enosys()); },
+ link(path, link, callback) { callback(enosys()); },
+ lstat(path, callback) { callback(enosys()); },
+ mkdir(path, perm, callback) { callback(enosys()); },
+ open(path, flags, mode, callback) { callback(enosys()); },
+ read(fd, buffer, offset, length, position, callback) { callback(enosys()); },
+ readdir(path, callback) { callback(enosys()); },
+ readlink(path, callback) { callback(enosys()); },
+ rename(from, to, callback) { callback(enosys()); },
+ rmdir(path, callback) { callback(enosys()); },
+ stat(path, callback) { callback(enosys()); },
+ symlink(path, link, callback) { callback(enosys()); },
+ truncate(path, length, callback) { callback(enosys()); },
+ unlink(path, callback) { callback(enosys()); },
+ utimes(path, atime, mtime, callback) { callback(enosys()); },
+ };
+ }
+
+ if (!globalThis.process) {
+ globalThis.process = {
+ getuid() { return -1; },
+ getgid() { return -1; },
+ geteuid() { return -1; },
+ getegid() { return -1; },
+ getgroups() { throw enosys(); },
+ pid: -1,
+ ppid: -1,
+ umask() { throw enosys(); },
+ cwd() { throw enosys(); },
+ chdir() { throw enosys(); },
+ }
+ }
+
+ if (!globalThis.crypto) {
+ throw new Error("globalThis.crypto is not available, polyfill required (crypto.getRandomValues only)");
+ }
+
+ if (!globalThis.performance) {
+ throw new Error("globalThis.performance is not available, polyfill required (performance.now only)");
+ }
+
+ if (!globalThis.TextEncoder) {
+ throw new Error("globalThis.TextEncoder is not available, polyfill required");
+ }
+
+ if (!globalThis.TextDecoder) {
+ throw new Error("globalThis.TextDecoder is not available, polyfill required");
+ }
+
+ const encoder = new TextEncoder("utf-8");
+ const decoder = new TextDecoder("utf-8");
+
+ globalThis.Go = class {
+ constructor() {
+ this.argv = ["js"];
+ this.env = {};
+ this.exit = (code) => {
+ if (code !== 0) {
+ console.warn("exit code:", code);
+ }
+ };
+ this._exitPromise = new Promise((resolve) => {
+ this._resolveExitPromise = resolve;
+ });
+ this._pendingEvent = null;
+ this._scheduledTimeouts = new Map();
+ this._nextCallbackTimeoutID = 1;
+
+ const setInt64 = (addr, v) => {
+ this.mem.setUint32(addr + 0, v, true);
+ this.mem.setUint32(addr + 4, Math.floor(v / 4294967296), true);
+ }
+
+ const getInt64 = (addr) => {
+ const low = this.mem.getUint32(addr + 0, true);
+ const high = this.mem.getInt32(addr + 4, true);
+ return low + high * 4294967296;
+ }
+
+ const loadValue = (addr) => {
+ const f = this.mem.getFloat64(addr, true);
+ if (f === 0) {
+ return undefined;
+ }
+ if (!isNaN(f)) {
+ return f;
+ }
+
+ const id = this.mem.getUint32(addr, true);
+ return this._values[id];
+ }
+
+ const storeValue = (addr, v) => {
+ const nanHead = 0x7FF80000;
+
+ if (typeof v === "number" && v !== 0) {
+ if (isNaN(v)) {
+ this.mem.setUint32(addr + 4, nanHead, true);
+ this.mem.setUint32(addr, 0, true);
+ return;
+ }
+ this.mem.setFloat64(addr, v, true);
+ return;
+ }
+
+ if (v === undefined) {
+ this.mem.setFloat64(addr, 0, true);
+ return;
+ }
+
+ let id = this._ids.get(v);
+ if (id === undefined) {
+ id = this._idPool.pop();
+ if (id === undefined) {
+ id = this._values.length;
+ }
+ this._values[id] = v;
+ this._goRefCounts[id] = 0;
+ this._ids.set(v, id);
+ }
+ this._goRefCounts[id]++;
+ let typeFlag = 0;
+ switch (typeof v) {
+ case "object":
+ if (v !== null) {
+ typeFlag = 1;
+ }
+ break;
+ case "string":
+ typeFlag = 2;
+ break;
+ case "symbol":
+ typeFlag = 3;
+ break;
+ case "function":
+ typeFlag = 4;
+ break;
+ }
+ this.mem.setUint32(addr + 4, nanHead | typeFlag, true);
+ this.mem.setUint32(addr, id, true);
+ }
+
+ const loadSlice = (addr) => {
+ const array = getInt64(addr + 0);
+ const len = getInt64(addr + 8);
+ return new Uint8Array(this._inst.exports.mem.buffer, array, len);
+ }
+
+ const loadSliceOfValues = (addr) => {
+ const array = getInt64(addr + 0);
+ const len = getInt64(addr + 8);
+ const a = new Array(len);
+ for (let i = 0; i < len; i++) {
+ a[i] = loadValue(array + i * 8);
+ }
+ return a;
+ }
+
+ const loadString = (addr) => {
+ const saddr = getInt64(addr + 0);
+ const len = getInt64(addr + 8);
+ return decoder.decode(new DataView(this._inst.exports.mem.buffer, saddr, len));
+ }
+
+ const timeOrigin = Date.now() - performance.now();
+ this.importObject = {
+ gojs: {
+ // Go's SP does not change as long as no Go code is running. Some operations (e.g. calls, getters and setters)
+ // may synchronously trigger a Go event handler. This makes Go code get executed in the middle of the imported
+ // function. A goroutine can switch to a new stack if the current stack is too small (see morestack function).
+ // This changes the SP, thus we have to update the SP used by the imported function.
+
+ // func wasmExit(code int32)
+ "runtime.wasmExit": (sp) => {
+ sp >>>= 0;
+ const code = this.mem.getInt32(sp + 8, true);
+ this.exited = true;
+ delete this._inst;
+ delete this._values;
+ delete this._goRefCounts;
+ delete this._ids;
+ delete this._idPool;
+ this.exit(code);
+ },
+
+ // func wasmWrite(fd uintptr, p unsafe.Pointer, n int32)
+ "runtime.wasmWrite": (sp) => {
+ sp >>>= 0;
+ const fd = getInt64(sp + 8);
+ const p = getInt64(sp + 16);
+ const n = this.mem.getInt32(sp + 24, true);
+ fs.writeSync(fd, new Uint8Array(this._inst.exports.mem.buffer, p, n));
+ },
+
+ // func resetMemoryDataView()
+ "runtime.resetMemoryDataView": (sp) => {
+ sp >>>= 0;
+ this.mem = new DataView(this._inst.exports.mem.buffer);
+ },
+
+ // func nanotime1() int64
+ "runtime.nanotime1": (sp) => {
+ sp >>>= 0;
+ setInt64(sp + 8, (timeOrigin + performance.now()) * 1000000);
+ },
+
+ // func walltime() (sec int64, nsec int32)
+ "runtime.walltime": (sp) => {
+ sp >>>= 0;
+ const msec = (new Date).getTime();
+ setInt64(sp + 8, msec / 1000);
+ this.mem.setInt32(sp + 16, (msec % 1000) * 1000000, true);
+ },
+
+ // func scheduleTimeoutEvent(delay int64) int32
+ "runtime.scheduleTimeoutEvent": (sp) => {
+ sp >>>= 0;
+ const id = this._nextCallbackTimeoutID;
+ this._nextCallbackTimeoutID++;
+ this._scheduledTimeouts.set(id, setTimeout(
+ () => {
+ this._resume();
+ while (this._scheduledTimeouts.has(id)) {
+ // for some reason Go failed to register the timeout event, log and try again
+ // (temporary workaround for https://github.com/golang/go/issues/28975)
+ console.warn("scheduleTimeoutEvent: missed timeout event");
+ this._resume();
+ }
+ },
+ getInt64(sp + 8) + 1, // setTimeout has been seen to fire up to 1 millisecond early
+ ));
+ this.mem.setInt32(sp + 16, id, true);
+ },
+
+ // func clearTimeoutEvent(id int32)
+ "runtime.clearTimeoutEvent": (sp) => {
+ sp >>>= 0;
+ const id = this.mem.getInt32(sp + 8, true);
+ clearTimeout(this._scheduledTimeouts.get(id));
+ this._scheduledTimeouts.delete(id);
+ },
+
+ // func getRandomData(r []byte)
+ "runtime.getRandomData": (sp) => {
+ sp >>>= 0;
+ crypto.getRandomValues(loadSlice(sp + 8));
+ },
+
+ // func finalizeRef(v ref)
+ "syscall/js.finalizeRef": (sp) => {
+ sp >>>= 0;
+ const id = this.mem.getUint32(sp + 8, true);
+ this._goRefCounts[id]--;
+ if (this._goRefCounts[id] === 0) {
+ const v = this._values[id];
+ this._values[id] = null;
+ this._ids.delete(v);
+ this._idPool.push(id);
+ }
+ },
+
+ // func stringVal(value string) ref
+ "syscall/js.stringVal": (sp) => {
+ sp >>>= 0;
+ storeValue(sp + 24, loadString(sp + 8));
+ },
+
+ // func valueGet(v ref, p string) ref
+ "syscall/js.valueGet": (sp) => {
+ sp >>>= 0;
+ const result = Reflect.get(loadValue(sp + 8), loadString(sp + 16));
+ sp = this._inst.exports.getsp() >>> 0; // see comment above
+ storeValue(sp + 32, result);
+ },
+
+ // func valueSet(v ref, p string, x ref)
+ "syscall/js.valueSet": (sp) => {
+ sp >>>= 0;
+ Reflect.set(loadValue(sp + 8), loadString(sp + 16), loadValue(sp + 32));
+ },
+
+ // func valueDelete(v ref, p string)
+ "syscall/js.valueDelete": (sp) => {
+ sp >>>= 0;
+ Reflect.deleteProperty(loadValue(sp + 8), loadString(sp + 16));
+ },
+
+ // func valueIndex(v ref, i int) ref
+ "syscall/js.valueIndex": (sp) => {
+ sp >>>= 0;
+ storeValue(sp + 24, Reflect.get(loadValue(sp + 8), getInt64(sp + 16)));
+ },
+
+ // valueSetIndex(v ref, i int, x ref)
+ "syscall/js.valueSetIndex": (sp) => {
+ sp >>>= 0;
+ Reflect.set(loadValue(sp + 8), getInt64(sp + 16), loadValue(sp + 24));
+ },
+
+ // func valueCall(v ref, m string, args []ref) (ref, bool)
+ "syscall/js.valueCall": (sp) => {
+ sp >>>= 0;
+ try {
+ const v = loadValue(sp + 8);
+ const m = Reflect.get(v, loadString(sp + 16));
+ const args = loadSliceOfValues(sp + 32);
+ const result = Reflect.apply(m, v, args);
+ sp = this._inst.exports.getsp() >>> 0; // see comment above
+ storeValue(sp + 56, result);
+ this.mem.setUint8(sp + 64, 1);
+ } catch (err) {
+ sp = this._inst.exports.getsp() >>> 0; // see comment above
+ storeValue(sp + 56, err);
+ this.mem.setUint8(sp + 64, 0);
+ }
+ },
+
+ // func valueInvoke(v ref, args []ref) (ref, bool)
+ "syscall/js.valueInvoke": (sp) => {
+ sp >>>= 0;
+ try {
+ const v = loadValue(sp + 8);
+ const args = loadSliceOfValues(sp + 16);
+ const result = Reflect.apply(v, undefined, args);
+ sp = this._inst.exports.getsp() >>> 0; // see comment above
+ storeValue(sp + 40, result);
+ this.mem.setUint8(sp + 48, 1);
+ } catch (err) {
+ sp = this._inst.exports.getsp() >>> 0; // see comment above
+ storeValue(sp + 40, err);
+ this.mem.setUint8(sp + 48, 0);
+ }
+ },
+
+ // func valueNew(v ref, args []ref) (ref, bool)
+ "syscall/js.valueNew": (sp) => {
+ sp >>>= 0;
+ try {
+ const v = loadValue(sp + 8);
+ const args = loadSliceOfValues(sp + 16);
+ const result = Reflect.construct(v, args);
+ sp = this._inst.exports.getsp() >>> 0; // see comment above
+ storeValue(sp + 40, result);
+ this.mem.setUint8(sp + 48, 1);
+ } catch (err) {
+ sp = this._inst.exports.getsp() >>> 0; // see comment above
+ storeValue(sp + 40, err);
+ this.mem.setUint8(sp + 48, 0);
+ }
+ },
+
+ // func valueLength(v ref) int
+ "syscall/js.valueLength": (sp) => {
+ sp >>>= 0;
+ setInt64(sp + 16, parseInt(loadValue(sp + 8).length));
+ },
+
+ // valuePrepareString(v ref) (ref, int)
+ "syscall/js.valuePrepareString": (sp) => {
+ sp >>>= 0;
+ const str = encoder.encode(String(loadValue(sp + 8)));
+ storeValue(sp + 16, str);
+ setInt64(sp + 24, str.length);
+ },
+
+ // valueLoadString(v ref, b []byte)
+ "syscall/js.valueLoadString": (sp) => {
+ sp >>>= 0;
+ const str = loadValue(sp + 8);
+ loadSlice(sp + 16).set(str);
+ },
+
+ // func valueInstanceOf(v ref, t ref) bool
+ "syscall/js.valueInstanceOf": (sp) => {
+ sp >>>= 0;
+ this.mem.setUint8(sp + 24, (loadValue(sp + 8) instanceof loadValue(sp + 16)) ? 1 : 0);
+ },
+
+ // func copyBytesToGo(dst []byte, src ref) (int, bool)
+ "syscall/js.copyBytesToGo": (sp) => {
+ sp >>>= 0;
+ const dst = loadSlice(sp + 8);
+ const src = loadValue(sp + 32);
+ if (!(src instanceof Uint8Array || src instanceof Uint8ClampedArray)) {
+ this.mem.setUint8(sp + 48, 0);
+ return;
+ }
+ const toCopy = src.subarray(0, dst.length);
+ dst.set(toCopy);
+ setInt64(sp + 40, toCopy.length);
+ this.mem.setUint8(sp + 48, 1);
+ },
+
+ // func copyBytesToJS(dst ref, src []byte) (int, bool)
+ "syscall/js.copyBytesToJS": (sp) => {
+ sp >>>= 0;
+ const dst = loadValue(sp + 8);
+ const src = loadSlice(sp + 16);
+ if (!(dst instanceof Uint8Array || dst instanceof Uint8ClampedArray)) {
+ this.mem.setUint8(sp + 48, 0);
+ return;
+ }
+ const toCopy = src.subarray(0, dst.length);
+ dst.set(toCopy);
+ setInt64(sp + 40, toCopy.length);
+ this.mem.setUint8(sp + 48, 1);
+ },
+
+ "debug": (value) => {
+ console.log(value);
+ },
+ }
+ };
+ }
+
+ async run(instance) {
+ if (!(instance instanceof WebAssembly.Instance)) {
+ throw new Error("Go.run: WebAssembly.Instance expected");
+ }
+ this._inst = instance;
+ this.mem = new DataView(this._inst.exports.mem.buffer);
+ this._values = [ // JS values that Go currently has references to, indexed by reference id
+ NaN,
+ 0,
+ null,
+ true,
+ false,
+ globalThis,
+ this,
+ ];
+ this._goRefCounts = new Array(this._values.length).fill(Infinity); // number of references that Go has to a JS value, indexed by reference id
+ this._ids = new Map([ // mapping from JS values to reference ids
+ [0, 1],
+ [null, 2],
+ [true, 3],
+ [false, 4],
+ [globalThis, 5],
+ [this, 6],
+ ]);
+ this._idPool = []; // unused ids that have been garbage collected
+ this.exited = false; // whether the Go program has exited
+
+ // Pass command line arguments and environment variables to WebAssembly by writing them to the linear memory.
+ let offset = 4096;
+
+ const strPtr = (str) => {
+ const ptr = offset;
+ const bytes = encoder.encode(str + "\0");
+ new Uint8Array(this.mem.buffer, offset, bytes.length).set(bytes);
+ offset += bytes.length;
+ if (offset % 8 !== 0) {
+ offset += 8 - (offset % 8);
+ }
+ return ptr;
+ };
+
+ const argc = this.argv.length;
+
+ const argvPtrs = [];
+ this.argv.forEach((arg) => {
+ argvPtrs.push(strPtr(arg));
+ });
+ argvPtrs.push(0);
+
+ const keys = Object.keys(this.env).sort();
+ keys.forEach((key) => {
+ argvPtrs.push(strPtr(`${key}=${this.env[key]}`));
+ });
+ argvPtrs.push(0);
+
+ const argv = offset;
+ argvPtrs.forEach((ptr) => {
+ this.mem.setUint32(offset, ptr, true);
+ this.mem.setUint32(offset + 4, 0, true);
+ offset += 8;
+ });
+
+ // The linker guarantees global data starts from at least wasmMinDataAddr.
+ // Keep in sync with cmd/link/internal/ld/data.go:wasmMinDataAddr.
+ const wasmMinDataAddr = 4096 + 8192;
+ if (offset >= wasmMinDataAddr) {
+ throw new Error("total length of command line and environment variables exceeds limit");
+ }
+
+ this._inst.exports.run(argc, argv);
+ if (this.exited) {
+ this._resolveExitPromise();
+ }
+ await this._exitPromise;
+ }
+
+ _resume() {
+ if (this.exited) {
+ throw new Error("Go program has already exited");
+ }
+ this._inst.exports.resume();
+ if (this.exited) {
+ this._resolveExitPromise();
+ }
+ }
+
+ _makeFuncWrapper(id) {
+ const go = this;
+ return function () {
+ const event = { id: id, this: this, args: arguments };
+ go._pendingEvent = event;
+ go._resume();
+ return event.result;
+ };
+ }
+ }
+})();
\ No newline at end of file
diff --git a/graalwasm/graalwasm-micronaut-excelize/src/main/resources/excelize_prep.js b/graalwasm/graalwasm-micronaut-excelize/src/main/resources/excelize_prep.js
new file mode 100644
index 00000000..81803f06
--- /dev/null
+++ b/graalwasm/graalwasm-micronaut-excelize/src/main/resources/excelize_prep.js
@@ -0,0 +1,42 @@
+//this file comes from Dmitrii Nikeshkin
+//Github : https://github.com/DimaNike
+
+
+(async () => {
+
+globalThis.setTimeout = (fn, ms) => {
+ // Use GraalVM's Java `Thread.sleep` if available
+ const Thread = Java.type("java.lang.Thread");
+ Thread.sleep(ms);
+ fn(); // run after sleep
+ return 0; // fake timeout ID
+ };
+ globalThis.clearTimeout = function (id) {};
+
+ global = globalThis;
+ const nowOffset = Date.now();
+ const now = () => Date.now() - nowOffset;
+ global.process = {};
+ global.nodeCrypto = {};
+ global.process.hrtime = global.process.hrtime || ((previousTimestamp) => {
+ const baseNow = Math.floor((Date.now() - now()) * 1e-3)
+ const clocktime = now() * 1e-3
+ let seconds = Math.floor(clocktime) + baseNow
+ let nanoseconds = Math.floor((clocktime % 1) * 1e9)
+
+ if (previousTimestamp) {
+ seconds = seconds - previousTimestamp[0]
+ nanoseconds = nanoseconds - previousTimestamp[1]
+ if (nanoseconds < 0) {
+ seconds--
+ nanoseconds += 1e9
+ }
+ }
+ return [seconds, nanoseconds]
+ });
+ global.nodeCrypto.randomFillSync = function(number) {
+ return 123;
+ };
+})();
+
+
diff --git a/graalwasm/graalwasm-micronaut-excelize/src/main/resources/logback.xml b/graalwasm/graalwasm-micronaut-excelize/src/main/resources/logback.xml
new file mode 100644
index 00000000..2d77bdab
--- /dev/null
+++ b/graalwasm/graalwasm-micronaut-excelize/src/main/resources/logback.xml
@@ -0,0 +1,14 @@
+
+
+
+
+
+ %cyan(%d{HH:mm:ss.SSS}) %gray([%thread]) %highlight(%-5level) %magenta(%logger{36}) - %msg%n
+
+
+
+
+
+
+
diff --git a/graalwasm/graalwasm-micronaut-excelize/src/main/resources/output.xlsx b/graalwasm/graalwasm-micronaut-excelize/src/main/resources/output.xlsx
new file mode 100644
index 00000000..a4361a26
Binary files /dev/null and b/graalwasm/graalwasm-micronaut-excelize/src/main/resources/output.xlsx differ
diff --git a/graalwasm/graalwasm-micronaut-excelize/src/main/resources/views/index.html b/graalwasm/graalwasm-micronaut-excelize/src/main/resources/views/index.html
new file mode 100644
index 00000000..f46f57d0
--- /dev/null
+++ b/graalwasm/graalwasm-micronaut-excelize/src/main/resources/views/index.html
@@ -0,0 +1,151 @@
+
+
+
+
+
+
+
+ Excel File Upload and Download
+
+
+
+
+
+
Upload an Excel File
+
+
+
+
+
+
+
Download Excel File
+
+
+
+
+
+
diff --git a/graalwasm/graalwasm-micronaut-excelize/src/test/java/com/example/MicronautdemoTest.java b/graalwasm/graalwasm-micronaut-excelize/src/test/java/com/example/MicronautdemoTest.java
new file mode 100644
index 00000000..7185110e
--- /dev/null
+++ b/graalwasm/graalwasm-micronaut-excelize/src/test/java/com/example/MicronautdemoTest.java
@@ -0,0 +1,49 @@
+package com.example;
+
+import io.micronaut.http.HttpRequest;
+import io.micronaut.http.MediaType;
+import io.micronaut.http.client.HttpClient;
+import io.micronaut.http.client.annotation.Client;
+import io.micronaut.http.client.multipart.MultipartBody;
+import io.micronaut.test.extensions.junit5.annotation.MicronautTest;
+import jakarta.inject.Inject;
+import org.junit.jupiter.api.Test;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+
+import static org.junit.jupiter.api.Assertions.*;
+
+@MicronautTest
+public class MicronautdemoTest {
+
+ @Inject
+ @Client("/")
+ HttpClient client;
+
+ @Test
+ void testDownloadExcelEndpoint() {
+ byte[] response = client.toBlocking().retrieve(HttpRequest.GET("/download"), byte[].class);
+
+ assertNotNull(response);
+ assertTrue(response.length > 0, "Excel file should not be empty");
+ }
+
+ @Test
+ void testUploadExcelEndpoint() throws IOException {
+ InputStream is = getClass().getResourceAsStream("/test.xlsx");
+ assertNotNull(is, "output.xlsx should exist in src/test/resources");
+
+ MultipartBody body = MultipartBody.builder()
+ .addPart("file", "output.xlsx", MediaType.APPLICATION_OCTET_STREAM_TYPE, is.readAllBytes())
+ .build();
+
+ String response = client.toBlocking().retrieve(HttpRequest.POST("/upload", body)
+ .contentType(MediaType.MULTIPART_FORM_DATA_TYPE), String.class);
+
+ assertTrue(response.contains("successfully"), "Upload should respond with success message");
+ }
+}
diff --git a/graalwasm/graalwasm-micronaut-excelize/src/test/resources/test.xlsx b/graalwasm/graalwasm-micronaut-excelize/src/test/resources/test.xlsx
new file mode 100644
index 00000000..a4361a26
Binary files /dev/null and b/graalwasm/graalwasm-micronaut-excelize/src/test/resources/test.xlsx differ