@faasjs/dev 8.0.0-beta.10
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/LICENSE +21 -0
- package/README.md +141 -0
- package/configs/oxlint.base.json +5 -0
- package/dist/chunk-D8kEL_kv.mjs +38 -0
- package/dist/cli/index.cjs +292 -0
- package/dist/cli/index.d.ts +5 -0
- package/dist/cli/index.mjs +290 -0
- package/dist/index.cjs +318 -0
- package/dist/index.d.ts +105 -0
- package/dist/index.mjs +272 -0
- package/dist/typegen-BNWmP5Qp.mjs +165 -0
- package/dist/typegen-HX5QyuhP.cjs +182 -0
- package/faas.mjs +7 -0
- package/package.json +59 -0
|
@@ -0,0 +1,290 @@
|
|
|
1
|
+
import { r as resolveServerConfig, t as generateFaasTypes } from "../typegen-BNWmP5Qp.mjs";
|
|
2
|
+
import { createRequire } from "node:module";
|
|
3
|
+
import { KnexSchema, useKnex } from "@faasjs/core";
|
|
4
|
+
import { loadConfig, loadEnvFileIfExists } from "@faasjs/node-utils";
|
|
5
|
+
import { existsSync, readFileSync } from "node:fs";
|
|
6
|
+
import { dirname, join, resolve } from "node:path";
|
|
7
|
+
import { execFileSync } from "node:child_process";
|
|
8
|
+
|
|
9
|
+
//#region package.json
|
|
10
|
+
var version = "8.0.0-beta.9";
|
|
11
|
+
|
|
12
|
+
//#endregion
|
|
13
|
+
//#region src/cli/shared.ts
|
|
14
|
+
function parseCommonCliArgs(args, scope) {
|
|
15
|
+
const options = {};
|
|
16
|
+
const rest = [];
|
|
17
|
+
for (let i = 0; i < args.length; i++) {
|
|
18
|
+
const arg = args[i];
|
|
19
|
+
if (arg === "-h" || arg === "--help") return {
|
|
20
|
+
mode: "help",
|
|
21
|
+
options,
|
|
22
|
+
rest
|
|
23
|
+
};
|
|
24
|
+
if (arg === "-v" || arg === "--version") return {
|
|
25
|
+
mode: "version",
|
|
26
|
+
options,
|
|
27
|
+
rest
|
|
28
|
+
};
|
|
29
|
+
if (arg === "--root") {
|
|
30
|
+
const value = args[i + 1];
|
|
31
|
+
if (!value || value.startsWith("-")) throw Error(`[${scope}] Missing value for ${arg}`);
|
|
32
|
+
options.root = value;
|
|
33
|
+
i += 1;
|
|
34
|
+
continue;
|
|
35
|
+
}
|
|
36
|
+
if (arg.startsWith("-")) throw Error(`[${scope}] Unknown option: ${arg}`);
|
|
37
|
+
rest.push(arg);
|
|
38
|
+
}
|
|
39
|
+
return {
|
|
40
|
+
mode: "run",
|
|
41
|
+
options,
|
|
42
|
+
rest
|
|
43
|
+
};
|
|
44
|
+
}
|
|
45
|
+
function printVersion() {
|
|
46
|
+
console.log(version);
|
|
47
|
+
return 0;
|
|
48
|
+
}
|
|
49
|
+
async function runCli(handler) {
|
|
50
|
+
try {
|
|
51
|
+
return await handler();
|
|
52
|
+
} catch (error) {
|
|
53
|
+
console.error(error?.message || error);
|
|
54
|
+
return 1;
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
function createMain(run) {
|
|
58
|
+
return async (argv = process.argv) => runCli(() => run(argv.slice(2)));
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
//#endregion
|
|
62
|
+
//#region src/cli/knex.ts
|
|
63
|
+
const MigrateActions = [
|
|
64
|
+
"latest",
|
|
65
|
+
"rollback",
|
|
66
|
+
"status",
|
|
67
|
+
"current",
|
|
68
|
+
"make"
|
|
69
|
+
];
|
|
70
|
+
function isMigrateAction(value) {
|
|
71
|
+
return MigrateActions.includes(value);
|
|
72
|
+
}
|
|
73
|
+
const ActionHandlers = {
|
|
74
|
+
latest: (schema) => schema.migrateLatest(),
|
|
75
|
+
rollback: (schema) => schema.migrateRollback(),
|
|
76
|
+
status: async (schema) => {
|
|
77
|
+
console.log(await schema.migrateStatus());
|
|
78
|
+
},
|
|
79
|
+
current: async (schema) => {
|
|
80
|
+
console.log(await schema.migrateCurrentVersion());
|
|
81
|
+
}
|
|
82
|
+
};
|
|
83
|
+
const HelpText$3 = `Run FaasJS knex migrations.
|
|
84
|
+
|
|
85
|
+
Usage:
|
|
86
|
+
faas knex <action> [name] [options]
|
|
87
|
+
|
|
88
|
+
Actions:
|
|
89
|
+
latest Run all pending migrations
|
|
90
|
+
rollback Roll back the last migration batch
|
|
91
|
+
status Print pending migration count
|
|
92
|
+
current Print current migration version
|
|
93
|
+
make <name> Create a new migration file
|
|
94
|
+
|
|
95
|
+
Options:
|
|
96
|
+
--root <path> Project root path (default: process.cwd())
|
|
97
|
+
-h, --help Show help
|
|
98
|
+
-v, --version Show version
|
|
99
|
+
`;
|
|
100
|
+
function parseCliArgs(args) {
|
|
101
|
+
const { mode, options, rest } = parseCommonCliArgs(args, "faas knex");
|
|
102
|
+
if (mode !== "run") return {
|
|
103
|
+
mode,
|
|
104
|
+
options
|
|
105
|
+
};
|
|
106
|
+
const [action, name, extra] = rest;
|
|
107
|
+
if (!action) throw Error("[faas knex] Missing action. Usage: faas knex <latest|rollback|status|current|make>");
|
|
108
|
+
if (!isMigrateAction(action)) throw Error(`[faas knex] Unknown action: ${action}`);
|
|
109
|
+
if (action !== "make") {
|
|
110
|
+
if (name) throw Error(`[faas knex] Unexpected argument: ${name}`);
|
|
111
|
+
return {
|
|
112
|
+
mode: "run",
|
|
113
|
+
action,
|
|
114
|
+
options
|
|
115
|
+
};
|
|
116
|
+
}
|
|
117
|
+
if (!name) throw Error("[faas knex] Missing migration name. Usage: faas knex make create_users");
|
|
118
|
+
if (extra) throw Error(`[faas knex] Unexpected argument: ${extra}`);
|
|
119
|
+
return {
|
|
120
|
+
mode: "run",
|
|
121
|
+
action: "make",
|
|
122
|
+
name,
|
|
123
|
+
options
|
|
124
|
+
};
|
|
125
|
+
}
|
|
126
|
+
async function run$3(args) {
|
|
127
|
+
const parsed = parseCliArgs(args);
|
|
128
|
+
if (parsed.mode === "help") {
|
|
129
|
+
console.log(HelpText$3);
|
|
130
|
+
return 0;
|
|
131
|
+
}
|
|
132
|
+
if (parsed.mode === "version") return printVersion();
|
|
133
|
+
const envRoot = parsed.options.root ?? process.cwd();
|
|
134
|
+
loadEnvFileIfExists({ cwd: envRoot });
|
|
135
|
+
const { root: projectRoot, staging } = resolveServerConfig(envRoot);
|
|
136
|
+
const srcRoot = join(projectRoot, "src");
|
|
137
|
+
const knex = useKnex({ config: loadConfig(srcRoot, join(srcRoot, "index.func.ts"), staging).plugins?.knex?.config });
|
|
138
|
+
await knex.mount();
|
|
139
|
+
const schema = new KnexSchema(knex);
|
|
140
|
+
try {
|
|
141
|
+
if (parsed.action === "make") console.log(await schema.migrateMake(parsed.name));
|
|
142
|
+
else await ActionHandlers[parsed.action](schema);
|
|
143
|
+
} finally {
|
|
144
|
+
await knex.quit();
|
|
145
|
+
}
|
|
146
|
+
return 0;
|
|
147
|
+
}
|
|
148
|
+
const main$3 = createMain(run$3);
|
|
149
|
+
|
|
150
|
+
//#endregion
|
|
151
|
+
//#region src/cli/lint.ts
|
|
152
|
+
const HelpText$2 = `Run formatter and lint checks with Oxc shared configs.
|
|
153
|
+
|
|
154
|
+
Usage:
|
|
155
|
+
faas lint [options]
|
|
156
|
+
|
|
157
|
+
Options:
|
|
158
|
+
--root <path> Project root path (default: process.cwd())
|
|
159
|
+
-h, --help Show help
|
|
160
|
+
-v, --version Show version
|
|
161
|
+
`;
|
|
162
|
+
function resolvePackageJsonPath(projectRoot, packageName) {
|
|
163
|
+
const requireFromProject = createRequire(resolve(projectRoot, "package.json"));
|
|
164
|
+
let packageEntryPath = "";
|
|
165
|
+
try {
|
|
166
|
+
packageEntryPath = requireFromProject.resolve(packageName);
|
|
167
|
+
} catch {
|
|
168
|
+
throw Error(`[faas lint] Missing dependency: ${packageName}. Please install ${packageName} in your project.`);
|
|
169
|
+
}
|
|
170
|
+
let currentPath = dirname(packageEntryPath);
|
|
171
|
+
let packageJsonPath = "";
|
|
172
|
+
while (true) {
|
|
173
|
+
const candidate = join(currentPath, "package.json");
|
|
174
|
+
if (existsSync(candidate)) {
|
|
175
|
+
packageJsonPath = candidate;
|
|
176
|
+
break;
|
|
177
|
+
}
|
|
178
|
+
const parentPath = dirname(currentPath);
|
|
179
|
+
if (parentPath === currentPath) break;
|
|
180
|
+
currentPath = parentPath;
|
|
181
|
+
}
|
|
182
|
+
if (!packageJsonPath) throw Error(`[faas lint] Invalid dependency: Cannot find package.json for ${packageName}.`);
|
|
183
|
+
return packageJsonPath;
|
|
184
|
+
}
|
|
185
|
+
function resolveBinPath(projectRoot, packageName, binName) {
|
|
186
|
+
const packageJsonPath = resolvePackageJsonPath(projectRoot, packageName);
|
|
187
|
+
const packageJSON = JSON.parse(readFileSync(packageJsonPath, "utf8"));
|
|
188
|
+
const bin = typeof packageJSON.bin === "string" ? packageJSON.bin : packageJSON.bin?.[binName];
|
|
189
|
+
if (!bin) throw Error(`[faas lint] Invalid dependency: ${packageName} does not expose "${binName}" bin.`);
|
|
190
|
+
return resolve(dirname(packageJsonPath), bin);
|
|
191
|
+
}
|
|
192
|
+
function resolveSharedConfigPath(projectRoot, configFileName) {
|
|
193
|
+
const configPath = resolve(dirname(resolvePackageJsonPath(projectRoot, "@faasjs/dev")), "configs", configFileName);
|
|
194
|
+
if (!existsSync(configPath)) throw Error(`[faas lint] Missing shared config: ${configPath}`);
|
|
195
|
+
return configPath;
|
|
196
|
+
}
|
|
197
|
+
function runNodeBin(projectRoot, command, binPath, args) {
|
|
198
|
+
try {
|
|
199
|
+
execFileSync(process.execPath, [binPath, ...args], {
|
|
200
|
+
cwd: projectRoot,
|
|
201
|
+
stdio: "inherit"
|
|
202
|
+
});
|
|
203
|
+
} catch {
|
|
204
|
+
throw Error(`[faas lint] ${command} failed`);
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
async function run$2(args) {
|
|
208
|
+
const { mode, options, rest } = parseCommonCliArgs(args, "faas lint");
|
|
209
|
+
if (mode === "help") {
|
|
210
|
+
console.log(HelpText$2);
|
|
211
|
+
return 0;
|
|
212
|
+
}
|
|
213
|
+
if (mode === "version") return printVersion();
|
|
214
|
+
if (rest.length) throw Error(`[faas lint] Unexpected argument: ${rest[0]}`);
|
|
215
|
+
const projectRoot = options.root ?? process.cwd();
|
|
216
|
+
loadEnvFileIfExists({ cwd: projectRoot });
|
|
217
|
+
runNodeBin(projectRoot, "oxlint", resolveBinPath(projectRoot, "oxlint", "oxlint"), [
|
|
218
|
+
"-c",
|
|
219
|
+
resolveSharedConfigPath(projectRoot, "oxlint.base.json"),
|
|
220
|
+
"--fix",
|
|
221
|
+
"."
|
|
222
|
+
]);
|
|
223
|
+
console.log("[faas lint] Done");
|
|
224
|
+
return 0;
|
|
225
|
+
}
|
|
226
|
+
const main$2 = createMain(run$2);
|
|
227
|
+
|
|
228
|
+
//#endregion
|
|
229
|
+
//#region src/cli/types.ts
|
|
230
|
+
const HelpText$1 = `Generate FaasJS API/event type declarations.
|
|
231
|
+
|
|
232
|
+
Usage:
|
|
233
|
+
faas types [options]
|
|
234
|
+
|
|
235
|
+
Options:
|
|
236
|
+
--root <path> Project root path (default: process.cwd())
|
|
237
|
+
-h, --help Show help
|
|
238
|
+
-v, --version Show version
|
|
239
|
+
`;
|
|
240
|
+
async function run$1(args) {
|
|
241
|
+
const { mode, options, rest } = parseCommonCliArgs(args, "faas types");
|
|
242
|
+
if (mode === "help") {
|
|
243
|
+
console.log(HelpText$1);
|
|
244
|
+
return 0;
|
|
245
|
+
}
|
|
246
|
+
if (mode === "version") return printVersion();
|
|
247
|
+
if (rest.length) throw Error(`[faas types] Unknown option: ${rest[0]}`);
|
|
248
|
+
loadEnvFileIfExists({ cwd: options.root ?? process.cwd() });
|
|
249
|
+
const result = await generateFaasTypes(options);
|
|
250
|
+
console.log(`[faas types] ${result.changed ? "Generated" : "Up to date"} ${result.output} (${result.routeCount} routes from ${result.fileCount} files)`);
|
|
251
|
+
return 0;
|
|
252
|
+
}
|
|
253
|
+
const main$1 = createMain(run$1);
|
|
254
|
+
|
|
255
|
+
//#endregion
|
|
256
|
+
//#region src/cli/index.ts
|
|
257
|
+
const HelpText = `FaasJS CLI.
|
|
258
|
+
|
|
259
|
+
Usage:
|
|
260
|
+
faas <command> [...args]
|
|
261
|
+
|
|
262
|
+
Commands:
|
|
263
|
+
types [options] Generate FaasJS API/event type declarations
|
|
264
|
+
knex <action> [name] [options] Run FaasJS knex migrations
|
|
265
|
+
lint [options] Run formatter and lint with Oxc
|
|
266
|
+
|
|
267
|
+
Options:
|
|
268
|
+
-h, --help Show help
|
|
269
|
+
-v, --version Show version
|
|
270
|
+
`;
|
|
271
|
+
const Commands = {
|
|
272
|
+
types: run$1,
|
|
273
|
+
knex: run$3,
|
|
274
|
+
lint: run$2
|
|
275
|
+
};
|
|
276
|
+
async function run(args) {
|
|
277
|
+
const command = args[0];
|
|
278
|
+
if (!command || command === "-h" || command === "--help") {
|
|
279
|
+
console.log(HelpText);
|
|
280
|
+
return 0;
|
|
281
|
+
}
|
|
282
|
+
if (command === "-v" || command === "--version") return printVersion();
|
|
283
|
+
const handler = Commands[command];
|
|
284
|
+
if (!handler) throw Error(`[faas] Unknown command: ${command}`);
|
|
285
|
+
return await handler(args.slice(1));
|
|
286
|
+
}
|
|
287
|
+
const main = createMain(run);
|
|
288
|
+
|
|
289
|
+
//#endregion
|
|
290
|
+
export { main, run };
|
package/dist/index.cjs
ADDED
|
@@ -0,0 +1,318 @@
|
|
|
1
|
+
Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
|
|
2
|
+
//#region \0rolldown/runtime.js
|
|
3
|
+
var __defProp = Object.defineProperty;
|
|
4
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
5
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
6
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
7
|
+
var __exportAll = (all, no_symbols) => {
|
|
8
|
+
let target = {};
|
|
9
|
+
for (var name in all) {
|
|
10
|
+
__defProp(target, name, {
|
|
11
|
+
get: all[name],
|
|
12
|
+
enumerable: true
|
|
13
|
+
});
|
|
14
|
+
}
|
|
15
|
+
if (!no_symbols) {
|
|
16
|
+
__defProp(target, Symbol.toStringTag, { value: "Module" });
|
|
17
|
+
}
|
|
18
|
+
return target;
|
|
19
|
+
};
|
|
20
|
+
var __copyProps = (to, from, except, desc) => {
|
|
21
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
22
|
+
for (var keys = __getOwnPropNames(from), i = 0, n = keys.length, key; i < n; i++) {
|
|
23
|
+
key = keys[i];
|
|
24
|
+
if (!__hasOwnProp.call(to, key) && key !== except) {
|
|
25
|
+
__defProp(to, key, {
|
|
26
|
+
get: ((k) => from[k]).bind(null, key),
|
|
27
|
+
enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable
|
|
28
|
+
});
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
return to;
|
|
33
|
+
};
|
|
34
|
+
var __reExport = (target, mod, secondTarget) => (__copyProps(target, mod, "default"), secondTarget && __copyProps(secondTarget, mod, "default"));
|
|
35
|
+
|
|
36
|
+
//#endregion
|
|
37
|
+
const require_typegen = require('./typegen-HX5QyuhP.cjs');
|
|
38
|
+
let node_zlib = require("node:zlib");
|
|
39
|
+
let _faasjs_core = require("@faasjs/core");
|
|
40
|
+
let _faasjs_node_utils = require("@faasjs/node-utils");
|
|
41
|
+
let node_path = require("node:path");
|
|
42
|
+
|
|
43
|
+
//#region src/test.ts
|
|
44
|
+
/**
|
|
45
|
+
* Test wrapper for a function.
|
|
46
|
+
*
|
|
47
|
+
* ```ts
|
|
48
|
+
* import { FuncWarper } from '@faasjs/dev'
|
|
49
|
+
* import Func from '../demo.func.ts'
|
|
50
|
+
*
|
|
51
|
+
* const func = new FuncWarper(Func)
|
|
52
|
+
*
|
|
53
|
+
* expect(await func.handler()).toEqual('Hello, world')
|
|
54
|
+
* ```
|
|
55
|
+
*/
|
|
56
|
+
var FuncWarper = class {
|
|
57
|
+
file;
|
|
58
|
+
staging;
|
|
59
|
+
logger;
|
|
60
|
+
func;
|
|
61
|
+
config;
|
|
62
|
+
plugins;
|
|
63
|
+
_handler;
|
|
64
|
+
/**
|
|
65
|
+
* @param initBy {Func} A FaasJS function
|
|
66
|
+
* ```ts
|
|
67
|
+
* import { FuncWarper } from '@faasjs/dev'
|
|
68
|
+
*
|
|
69
|
+
* new FuncWarper(__dirname + '/../demo.func.ts')
|
|
70
|
+
* ```
|
|
71
|
+
*/
|
|
72
|
+
constructor(initBy) {
|
|
73
|
+
this.staging = process.env.FaasEnv ?? "default";
|
|
74
|
+
this.logger = new _faasjs_node_utils.Logger("TestCase");
|
|
75
|
+
this.func = initBy.default ? initBy.default : initBy;
|
|
76
|
+
if (this.func.filename) this.func.config = (0, _faasjs_node_utils.deepMerge)((0, _faasjs_node_utils.loadConfig)(process.cwd(), this.func.filename, this.staging, this.logger), this.func.config);
|
|
77
|
+
this.file = this.func.filename || "";
|
|
78
|
+
this.config = this.func.config;
|
|
79
|
+
this.plugins = this.func.plugins || [];
|
|
80
|
+
for (const plugin of this.plugins) {
|
|
81
|
+
if ([
|
|
82
|
+
"handler",
|
|
83
|
+
"config",
|
|
84
|
+
"plugins",
|
|
85
|
+
"logger",
|
|
86
|
+
"mount"
|
|
87
|
+
].includes(plugin.type)) continue;
|
|
88
|
+
this[plugin.type] = plugin;
|
|
89
|
+
}
|
|
90
|
+
this._handler = this.func.export().handler;
|
|
91
|
+
}
|
|
92
|
+
async mount(handler) {
|
|
93
|
+
if (!this.func.mounted) await this.func.mount();
|
|
94
|
+
if (handler) await handler(this);
|
|
95
|
+
}
|
|
96
|
+
async handler(event = Object.create(null), context = Object.create(null)) {
|
|
97
|
+
await this.mount();
|
|
98
|
+
const response = await this._handler(event, context);
|
|
99
|
+
this.logger.debug("response: %j", response);
|
|
100
|
+
return response;
|
|
101
|
+
}
|
|
102
|
+
async JSONhandler(body, options = Object.create(null)) {
|
|
103
|
+
await this.mount();
|
|
104
|
+
const headers = options.headers || Object.create(null);
|
|
105
|
+
if (this.http && this.http instanceof _faasjs_core.Http) {
|
|
106
|
+
if (options.cookie) for (const key in options.cookie) this.http.cookie.write(key, options.cookie[key]);
|
|
107
|
+
if (options.session) {
|
|
108
|
+
for (const key in options.session) this.http.session.write(key, options.session[key]);
|
|
109
|
+
this.http.session.update();
|
|
110
|
+
}
|
|
111
|
+
const cookie = this.http.cookie.headers()["Set-Cookie"]?.map((c) => c.split(";")[0]).join(";");
|
|
112
|
+
if (cookie) if (headers.cookie) headers.cookie += `;${cookie}`;
|
|
113
|
+
else headers.cookie = cookie;
|
|
114
|
+
}
|
|
115
|
+
const response = await this._handler({
|
|
116
|
+
httpMethod: "POST",
|
|
117
|
+
headers: Object.assign({ "content-type": "application/json" }, headers),
|
|
118
|
+
body: typeof body === "string" ? body : JSON.stringify(body)
|
|
119
|
+
});
|
|
120
|
+
if (response?.body instanceof ReadableStream) {
|
|
121
|
+
let stream = response.body;
|
|
122
|
+
const encoding = response.headers?.["Content-Encoding"] || response.headers?.["content-encoding"];
|
|
123
|
+
if (encoding) {
|
|
124
|
+
const chunks = [];
|
|
125
|
+
const reader = stream.getReader();
|
|
126
|
+
try {
|
|
127
|
+
while (true) {
|
|
128
|
+
const { done, value } = await reader.read();
|
|
129
|
+
if (done) break;
|
|
130
|
+
if (value) chunks.push(value);
|
|
131
|
+
}
|
|
132
|
+
} catch (error) {
|
|
133
|
+
this.logger.error("Failed to read ReadableStream: %s", error);
|
|
134
|
+
response.body = JSON.stringify({ error: { message: error.message } });
|
|
135
|
+
response.error = { message: error.message };
|
|
136
|
+
response.statusCode = 500;
|
|
137
|
+
reader.releaseLock();
|
|
138
|
+
return response;
|
|
139
|
+
}
|
|
140
|
+
reader.releaseLock();
|
|
141
|
+
const compressedBuffer = Buffer.concat(chunks);
|
|
142
|
+
try {
|
|
143
|
+
let decompressed;
|
|
144
|
+
if (encoding === "br") decompressed = (0, node_zlib.brotliDecompressSync)(compressedBuffer);
|
|
145
|
+
else if (encoding === "gzip") decompressed = (0, node_zlib.gunzipSync)(compressedBuffer);
|
|
146
|
+
else if (encoding === "deflate") decompressed = (0, node_zlib.inflateSync)(compressedBuffer);
|
|
147
|
+
else throw new Error(`Unsupported encoding: ${encoding}`);
|
|
148
|
+
stream = new ReadableStream({ start(controller) {
|
|
149
|
+
controller.enqueue(new Uint8Array(decompressed));
|
|
150
|
+
controller.close();
|
|
151
|
+
} });
|
|
152
|
+
} catch (error) {
|
|
153
|
+
this.logger.error("Failed to decompress: %s", error);
|
|
154
|
+
response.body = JSON.stringify({ error: { message: error.message } });
|
|
155
|
+
response.error = { message: error.message };
|
|
156
|
+
response.statusCode = 500;
|
|
157
|
+
return response;
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
try {
|
|
161
|
+
response.body = await (0, _faasjs_node_utils.streamToText)(stream);
|
|
162
|
+
} catch (error) {
|
|
163
|
+
this.logger.error("Failed to decode ReadableStream: %s", error);
|
|
164
|
+
response.body = JSON.stringify({ error: { message: error.message } });
|
|
165
|
+
response.error = { message: error.message };
|
|
166
|
+
response.statusCode = 500;
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
if (response?.headers && response.body && response.headers["content-type"]?.includes("json")) {
|
|
170
|
+
const parsedBody = JSON.parse(response.body);
|
|
171
|
+
response.data = parsedBody.data;
|
|
172
|
+
response.error = parsedBody.error;
|
|
173
|
+
}
|
|
174
|
+
if (this.http) {
|
|
175
|
+
response.cookie = this.http.cookie.content;
|
|
176
|
+
response.session = this.http.session.content;
|
|
177
|
+
}
|
|
178
|
+
this.logger.debug("response: %j", response);
|
|
179
|
+
return response;
|
|
180
|
+
}
|
|
181
|
+
};
|
|
182
|
+
/**
|
|
183
|
+
* A simple way to wrap a FaasJS function.
|
|
184
|
+
* @param initBy {Func} Full file path or a FaasJs function
|
|
185
|
+
*
|
|
186
|
+
* ```ts
|
|
187
|
+
* import { test } from '@faasjs/dev'
|
|
188
|
+
* import Func from '../demo.func.ts'
|
|
189
|
+
*
|
|
190
|
+
* const func = test(Func)
|
|
191
|
+
*
|
|
192
|
+
* expect(await func.handler()).toEqual('Hello, world')
|
|
193
|
+
* ```
|
|
194
|
+
*/
|
|
195
|
+
function test(initBy) {
|
|
196
|
+
const warper = new FuncWarper(initBy);
|
|
197
|
+
warper.mount = warper.mount.bind(warper);
|
|
198
|
+
warper.handler = warper.handler.bind(warper);
|
|
199
|
+
warper.JSONhandler = warper.JSONhandler.bind(warper);
|
|
200
|
+
return warper;
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
//#endregion
|
|
204
|
+
//#region src/vite.ts
|
|
205
|
+
const TYPEGEN_DEBOUNCE = 120;
|
|
206
|
+
function normalizeBase(base) {
|
|
207
|
+
const normalized = base.startsWith("/") ? base : `/${base}`;
|
|
208
|
+
if (normalized === "/") return "/";
|
|
209
|
+
return normalized.endsWith("/") ? normalized.slice(0, -1) : normalized;
|
|
210
|
+
}
|
|
211
|
+
function stripBase(url, base) {
|
|
212
|
+
if (base === "/") return url;
|
|
213
|
+
const queryIndex = url.indexOf("?");
|
|
214
|
+
const pathname = queryIndex >= 0 ? url.slice(0, queryIndex) : url;
|
|
215
|
+
const search = queryIndex >= 0 ? url.slice(queryIndex) : "";
|
|
216
|
+
if (pathname === base) return `/${search}`;
|
|
217
|
+
if (pathname.startsWith(`${base}/`)) return `${pathname.slice(base.length)}${search}`;
|
|
218
|
+
return url;
|
|
219
|
+
}
|
|
220
|
+
/**
|
|
221
|
+
* Create a Vite plugin that proxies POST requests to an in-process FaasJS server.
|
|
222
|
+
*
|
|
223
|
+
* It resolves server root/base from `src/faas.yaml` and strips `base` from
|
|
224
|
+
* request URL before forwarding to `@faasjs/core`.
|
|
225
|
+
*/
|
|
226
|
+
function viteFaasJsServer() {
|
|
227
|
+
let config;
|
|
228
|
+
let server = null;
|
|
229
|
+
const logger = new _faasjs_node_utils.Logger("FaasJs:Vite");
|
|
230
|
+
return {
|
|
231
|
+
name: "vite:faasjs",
|
|
232
|
+
enforce: "pre",
|
|
233
|
+
configResolved(resolvedConfig) {
|
|
234
|
+
const { root, base } = require_typegen.resolveServerConfig(resolvedConfig.root, logger, resolvedConfig.base);
|
|
235
|
+
config = {
|
|
236
|
+
root,
|
|
237
|
+
base: normalizeBase(base)
|
|
238
|
+
};
|
|
239
|
+
},
|
|
240
|
+
configureServer: async ({ middlewares, watcher }) => {
|
|
241
|
+
if (process.env.VITEST) {
|
|
242
|
+
logger.debug("Skipping faas server in vitest environment");
|
|
243
|
+
return;
|
|
244
|
+
}
|
|
245
|
+
if (!config) throw new Error("viteFaasJsServer: config is not resolved");
|
|
246
|
+
server = new _faasjs_core.Server((0, node_path.join)(config.root, "src"));
|
|
247
|
+
const runTypegen = async () => {
|
|
248
|
+
try {
|
|
249
|
+
const result = await require_typegen.generateFaasTypes({ root: config.root });
|
|
250
|
+
logger.debug("[faas types] %s %s (%i routes)", result.changed ? "generated" : "up-to-date", result.output, result.routeCount);
|
|
251
|
+
} catch (error) {
|
|
252
|
+
logger.error("[faas types] %s", error.message);
|
|
253
|
+
}
|
|
254
|
+
};
|
|
255
|
+
let timer;
|
|
256
|
+
let typegenChain = Promise.resolve();
|
|
257
|
+
const scheduleTypegen = () => {
|
|
258
|
+
if (timer) clearTimeout(timer);
|
|
259
|
+
timer = setTimeout(() => {
|
|
260
|
+
typegenChain = typegenChain.then(runTypegen);
|
|
261
|
+
}, TYPEGEN_DEBOUNCE);
|
|
262
|
+
};
|
|
263
|
+
await runTypegen();
|
|
264
|
+
watcher.on("all", (_eventName, filePath) => {
|
|
265
|
+
if (!require_typegen.isTypegenSourceFile(filePath)) return;
|
|
266
|
+
scheduleTypegen();
|
|
267
|
+
});
|
|
268
|
+
middlewares.use(async (req, res, next) => {
|
|
269
|
+
if (!req.url || req.method !== "POST" || !server) return next();
|
|
270
|
+
const originalUrl = req.url;
|
|
271
|
+
req.url = stripBase(req.url, config.base);
|
|
272
|
+
try {
|
|
273
|
+
logger.debug(`Request ${req.url}`);
|
|
274
|
+
await server.handle(req, res, { requestedAt: Date.now() });
|
|
275
|
+
} catch (error) {
|
|
276
|
+
logger.error(error);
|
|
277
|
+
if (!res.headersSent && !res.writableEnded) {
|
|
278
|
+
res.writeHead(500, { "Content-Type": "application/json" });
|
|
279
|
+
res.write(JSON.stringify({ error: { message: "Internal Server Error" } }));
|
|
280
|
+
res.end();
|
|
281
|
+
}
|
|
282
|
+
} finally {
|
|
283
|
+
req.url = originalUrl;
|
|
284
|
+
}
|
|
285
|
+
if (!res.writableEnded) next();
|
|
286
|
+
});
|
|
287
|
+
}
|
|
288
|
+
};
|
|
289
|
+
}
|
|
290
|
+
|
|
291
|
+
//#endregion
|
|
292
|
+
//#region src/index.ts
|
|
293
|
+
var src_exports = /* @__PURE__ */ __exportAll({
|
|
294
|
+
FuncWarper: () => FuncWarper,
|
|
295
|
+
generateFaasTypes: () => require_typegen.generateFaasTypes,
|
|
296
|
+
isTypegenSourceFile: () => require_typegen.isTypegenSourceFile,
|
|
297
|
+
streamToObject: () => _faasjs_node_utils.streamToObject,
|
|
298
|
+
streamToString: () => _faasjs_node_utils.streamToString,
|
|
299
|
+
streamToText: () => _faasjs_node_utils.streamToText,
|
|
300
|
+
test: () => test,
|
|
301
|
+
viteFaasJsServer: () => viteFaasJsServer
|
|
302
|
+
});
|
|
303
|
+
|
|
304
|
+
//#endregion
|
|
305
|
+
exports.FuncWarper = FuncWarper;
|
|
306
|
+
exports.generateFaasTypes = require_typegen.generateFaasTypes;
|
|
307
|
+
exports.isTypegenSourceFile = require_typegen.isTypegenSourceFile;
|
|
308
|
+
exports.streamToObject = _faasjs_node_utils.streamToObject;
|
|
309
|
+
exports.streamToString = _faasjs_node_utils.streamToString;
|
|
310
|
+
exports.streamToText = _faasjs_node_utils.streamToText;
|
|
311
|
+
exports.test = test;
|
|
312
|
+
exports.viteFaasJsServer = viteFaasJsServer;
|
|
313
|
+
Object.keys(_faasjs_core).forEach(function (k) {
|
|
314
|
+
if (k !== 'default' && !Object.prototype.hasOwnProperty.call(exports, k)) Object.defineProperty(exports, k, {
|
|
315
|
+
enumerable: true,
|
|
316
|
+
get: function () { return _faasjs_core[k]; }
|
|
317
|
+
});
|
|
318
|
+
});
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
import { n as __reExport, t as __exportAll } from "./chunk-D8kEL_kv.mjs";
|
|
2
|
+
import { Config, Func, Plugin } from "@faasjs/core";
|
|
3
|
+
import { Logger, streamToObject, streamToString, streamToText } from "@faasjs/node-utils";
|
|
4
|
+
import { Plugin as Plugin$1 } from "vite";
|
|
5
|
+
export * from "@faasjs/core";
|
|
6
|
+
|
|
7
|
+
//#region src/test.d.ts
|
|
8
|
+
/**
|
|
9
|
+
* Test wrapper for a function.
|
|
10
|
+
*
|
|
11
|
+
* ```ts
|
|
12
|
+
* import { FuncWarper } from '@faasjs/dev'
|
|
13
|
+
* import Func from '../demo.func.ts'
|
|
14
|
+
*
|
|
15
|
+
* const func = new FuncWarper(Func)
|
|
16
|
+
*
|
|
17
|
+
* expect(await func.handler()).toEqual('Hello, world')
|
|
18
|
+
* ```
|
|
19
|
+
*/
|
|
20
|
+
declare class FuncWarper {
|
|
21
|
+
[key: string]: any;
|
|
22
|
+
readonly file: string;
|
|
23
|
+
readonly staging: string;
|
|
24
|
+
readonly logger: Logger;
|
|
25
|
+
readonly func: Func;
|
|
26
|
+
readonly config: Config;
|
|
27
|
+
readonly plugins: Plugin[];
|
|
28
|
+
private readonly _handler;
|
|
29
|
+
/**
|
|
30
|
+
* @param initBy {Func} A FaasJS function
|
|
31
|
+
* ```ts
|
|
32
|
+
* import { FuncWarper } from '@faasjs/dev'
|
|
33
|
+
*
|
|
34
|
+
* new FuncWarper(__dirname + '/../demo.func.ts')
|
|
35
|
+
* ```
|
|
36
|
+
*/
|
|
37
|
+
constructor(initBy: Func);
|
|
38
|
+
mount(handler?: (func: FuncWarper) => Promise<void> | void): Promise<void>;
|
|
39
|
+
handler<TResult = any>(event?: any, context?: any): Promise<TResult>;
|
|
40
|
+
JSONhandler<TData = any>(body?: Record<string, any> | string | null, options?: {
|
|
41
|
+
headers?: {
|
|
42
|
+
[key: string]: any;
|
|
43
|
+
};
|
|
44
|
+
cookie?: {
|
|
45
|
+
[key: string]: any;
|
|
46
|
+
};
|
|
47
|
+
session?: {
|
|
48
|
+
[key: string]: any;
|
|
49
|
+
};
|
|
50
|
+
}): Promise<{
|
|
51
|
+
statusCode: number;
|
|
52
|
+
headers: {
|
|
53
|
+
[key: string]: string;
|
|
54
|
+
};
|
|
55
|
+
cookie?: Record<string, any>;
|
|
56
|
+
session?: Record<string, any>;
|
|
57
|
+
body: any;
|
|
58
|
+
data?: TData;
|
|
59
|
+
error?: {
|
|
60
|
+
message: string;
|
|
61
|
+
};
|
|
62
|
+
}>;
|
|
63
|
+
}
|
|
64
|
+
/**
|
|
65
|
+
* A simple way to wrap a FaasJS function.
|
|
66
|
+
* @param initBy {Func} Full file path or a FaasJs function
|
|
67
|
+
*
|
|
68
|
+
* ```ts
|
|
69
|
+
* import { test } from '@faasjs/dev'
|
|
70
|
+
* import Func from '../demo.func.ts'
|
|
71
|
+
*
|
|
72
|
+
* const func = test(Func)
|
|
73
|
+
*
|
|
74
|
+
* expect(await func.handler()).toEqual('Hello, world')
|
|
75
|
+
* ```
|
|
76
|
+
*/
|
|
77
|
+
declare function test(initBy: Func): FuncWarper;
|
|
78
|
+
//#endregion
|
|
79
|
+
//#region src/typegen.d.ts
|
|
80
|
+
type GenerateFaasTypesOptions = {
|
|
81
|
+
/** faas project root path, default is process.cwd() */root?: string; /** optional logger instance */
|
|
82
|
+
logger?: Logger;
|
|
83
|
+
};
|
|
84
|
+
type GenerateFaasTypesResult = {
|
|
85
|
+
output: string;
|
|
86
|
+
changed: boolean;
|
|
87
|
+
fileCount: number;
|
|
88
|
+
routeCount: number;
|
|
89
|
+
};
|
|
90
|
+
declare function isTypegenSourceFile(filePath: string): boolean;
|
|
91
|
+
declare function generateFaasTypes(options?: GenerateFaasTypesOptions): Promise<GenerateFaasTypesResult>;
|
|
92
|
+
//#endregion
|
|
93
|
+
//#region src/vite.d.ts
|
|
94
|
+
/**
|
|
95
|
+
* Create a Vite plugin that proxies POST requests to an in-process FaasJS server.
|
|
96
|
+
*
|
|
97
|
+
* It resolves server root/base from `src/faas.yaml` and strips `base` from
|
|
98
|
+
* request URL before forwarding to `@faasjs/core`.
|
|
99
|
+
*/
|
|
100
|
+
declare function viteFaasJsServer(): Plugin$1;
|
|
101
|
+
declare namespace index_d_exports {
|
|
102
|
+
export { FuncWarper, GenerateFaasTypesOptions, GenerateFaasTypesResult, generateFaasTypes, isTypegenSourceFile, streamToObject, streamToString, streamToText, test, viteFaasJsServer };
|
|
103
|
+
}
|
|
104
|
+
//#endregion
|
|
105
|
+
export { FuncWarper, GenerateFaasTypesOptions, GenerateFaasTypesResult, generateFaasTypes, isTypegenSourceFile, streamToObject, streamToString, streamToText, test, viteFaasJsServer };
|