65 lines
2.6 KiB
Go
65 lines
2.6 KiB
Go
package runtime
|
|
|
|
import (
|
|
"archive/zip"
|
|
"bytes"
|
|
"encoding/json"
|
|
"fmt"
|
|
)
|
|
|
|
// BuildJSDeployZip упаковывает Node.js код в zip для Fission deployment package.
|
|
//
|
|
// Генерируем CommonJS wrapper: так Fission/node executor не упирается в ESM export
|
|
// синтаксис и может исполнять результат без package.json и type=module.
|
|
// Пользовательский код остаётся CJS-стилем через new Function(module, exports).
|
|
// Wrapper экспортирует main, handler и default через module.exports.
|
|
func BuildJSDeployZip(code string) ([]byte, error) {
|
|
// Сериализуем пользовательский код в JSON строку чтобы безопасно инлайнить
|
|
// в JavaScript-литерал — экранирует кавычки, переводы строк, спецсимволы.
|
|
codeJSON, err := json.Marshal(code)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("marshal user code: %w", err)
|
|
}
|
|
|
|
// main.js — CommonJS wrapper:
|
|
// 1. new Function создаёт функцию в пустом модульном контексте (нет import/export)
|
|
// 2. Передаём ей module, exports и require как параметры → пользовательский CJS код работает
|
|
// 3. require передаётся явно, т.к. new Function выполняется в глобальном scope
|
|
// и не имеет доступа к module-local require из CJS контекста main.js
|
|
// 4. Экспортируем main/handler/default через module.exports
|
|
wrapper := fmt.Sprintf(`const __mod = { exports: {} };
|
|
(new Function('module', 'exports', 'require', %s))(__mod, __mod.exports, require);
|
|
const _fn = __mod.exports;
|
|
|
|
async function __invoke(ctx) {
|
|
const fn = typeof _fn === 'function' ? _fn : (_fn.default || _fn.handler || _fn.main);
|
|
if (!fn) throw new Error('no exported function found in user code');
|
|
const result = await fn(ctx);
|
|
if (!result) return { status: 200, body: '' };
|
|
if (typeof result.status !== 'undefined') return result;
|
|
return { status: 200, ...result };
|
|
}
|
|
|
|
module.exports = __invoke;
|
|
module.exports.main = __invoke;
|
|
module.exports.handler = __invoke;
|
|
module.exports.default = __invoke;
|
|
`, string(codeJSON))
|
|
|
|
var buf bytes.Buffer
|
|
zw := zip.NewWriter(&buf)
|
|
|
|
fw, err := zw.Create("main.js")
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
if _, err := fw.Write([]byte(wrapper)); err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
if err := zw.Close(); err != nil {
|
|
return nil, err
|
|
}
|
|
return buf.Bytes(), nil
|
|
}
|