@gravito/pulse 1.0.1 → 2.0.0
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/dist/index.js +681 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -81111,6 +81111,26 @@ class BaseGenerator {
|
|
|
81111
81111
|
await this.writeFile(context.targetDir, ".dockerignore", this.generateDockerIgnore());
|
|
81112
81112
|
await this.writeFile(context.targetDir, "ARCHITECTURE.md", this.generateArchitectureDoc(context));
|
|
81113
81113
|
await this.generateCheckScripts(context);
|
|
81114
|
+
await this.generateSkills(context);
|
|
81115
|
+
}
|
|
81116
|
+
async generateSkills(context) {
|
|
81117
|
+
const skillsDir = path2.resolve(this.config.templatesDir, "skills");
|
|
81118
|
+
const targetSkillsDir = path2.join(".skills");
|
|
81119
|
+
try {
|
|
81120
|
+
await fs2.access(skillsDir);
|
|
81121
|
+
} catch {
|
|
81122
|
+
return;
|
|
81123
|
+
}
|
|
81124
|
+
const files = await walk(skillsDir);
|
|
81125
|
+
for (const filePath of files) {
|
|
81126
|
+
const relativePath = path2.relative(skillsDir, filePath);
|
|
81127
|
+
const targetPath = path2.join(targetSkillsDir, relativePath);
|
|
81128
|
+
let content = await fs2.readFile(filePath, "utf-8");
|
|
81129
|
+
try {
|
|
81130
|
+
content = this.stubGenerator.render(content, context);
|
|
81131
|
+
} catch {}
|
|
81132
|
+
await this.writeFile(context.targetDir, targetPath, content);
|
|
81133
|
+
}
|
|
81114
81134
|
}
|
|
81115
81135
|
async applyOverlays(context) {
|
|
81116
81136
|
const profile = context.profile;
|
|
@@ -85761,7 +85781,7 @@ import { confirm, note, spinner } from "@clack/prompts";
|
|
|
85761
85781
|
// ../core/package.json
|
|
85762
85782
|
var package_default = {
|
|
85763
85783
|
name: "@gravito/core",
|
|
85764
|
-
version: "1.
|
|
85784
|
+
version: "1.1.0",
|
|
85765
85785
|
description: "",
|
|
85766
85786
|
module: "./dist/index.js",
|
|
85767
85787
|
main: "./dist/index.cjs",
|
|
@@ -85777,6 +85797,11 @@ var package_default = {
|
|
|
85777
85797
|
types: "./dist/compat.d.ts",
|
|
85778
85798
|
import: "./dist/compat.js",
|
|
85779
85799
|
require: "./dist/compat.cjs"
|
|
85800
|
+
},
|
|
85801
|
+
"./engine": {
|
|
85802
|
+
types: "./dist/engine/index.d.ts",
|
|
85803
|
+
import: "./dist/engine/index.js",
|
|
85804
|
+
require: "./dist/engine/index.cjs"
|
|
85780
85805
|
}
|
|
85781
85806
|
},
|
|
85782
85807
|
files: [
|
|
@@ -88444,6 +88469,661 @@ class ServiceProvider {
|
|
|
88444
88469
|
return Array.from(ServiceProvider.publishables.keys());
|
|
88445
88470
|
}
|
|
88446
88471
|
}
|
|
88472
|
+
// ../core/src/engine/AOTRouter.ts
|
|
88473
|
+
class AOTRouter {
|
|
88474
|
+
staticRoutes = new Map;
|
|
88475
|
+
dynamicRouter = new RadixRouter;
|
|
88476
|
+
globalMiddleware = [];
|
|
88477
|
+
pathMiddleware = new Map;
|
|
88478
|
+
add(method, path4, handler, middleware = []) {
|
|
88479
|
+
const normalizedMethod = method.toLowerCase();
|
|
88480
|
+
if (this.isStaticPath(path4)) {
|
|
88481
|
+
const key = `${normalizedMethod}:${path4}`;
|
|
88482
|
+
this.staticRoutes.set(key, { handler, middleware });
|
|
88483
|
+
} else {
|
|
88484
|
+
const wrappedHandler = handler;
|
|
88485
|
+
this.dynamicRouter.add(normalizedMethod, path4, [wrappedHandler]);
|
|
88486
|
+
if (middleware.length > 0) {
|
|
88487
|
+
this.pathMiddleware.set(`${normalizedMethod}:${path4}`, middleware);
|
|
88488
|
+
}
|
|
88489
|
+
}
|
|
88490
|
+
}
|
|
88491
|
+
use(...middleware) {
|
|
88492
|
+
this.globalMiddleware.push(...middleware);
|
|
88493
|
+
}
|
|
88494
|
+
usePattern(pattern, ...middleware) {
|
|
88495
|
+
const existing = this.pathMiddleware.get(pattern) ?? [];
|
|
88496
|
+
this.pathMiddleware.set(pattern, [...existing, ...middleware]);
|
|
88497
|
+
}
|
|
88498
|
+
match(method, path4) {
|
|
88499
|
+
const normalizedMethod = method.toLowerCase();
|
|
88500
|
+
const staticKey = `${normalizedMethod}:${path4}`;
|
|
88501
|
+
const staticRoute = this.staticRoutes.get(staticKey);
|
|
88502
|
+
if (staticRoute) {
|
|
88503
|
+
return {
|
|
88504
|
+
handler: staticRoute.handler,
|
|
88505
|
+
params: {},
|
|
88506
|
+
middleware: this.collectMiddleware(path4, staticRoute.middleware)
|
|
88507
|
+
};
|
|
88508
|
+
}
|
|
88509
|
+
const match2 = this.dynamicRouter.match(normalizedMethod, path4);
|
|
88510
|
+
if (match2 && match2.handlers.length > 0) {
|
|
88511
|
+
const handler = match2.handlers[0];
|
|
88512
|
+
const routeKey = this.findDynamicRouteKey(normalizedMethod, path4);
|
|
88513
|
+
const routeMiddleware = routeKey ? this.pathMiddleware.get(routeKey) ?? [] : [];
|
|
88514
|
+
return {
|
|
88515
|
+
handler,
|
|
88516
|
+
params: match2.params,
|
|
88517
|
+
middleware: this.collectMiddleware(path4, routeMiddleware)
|
|
88518
|
+
};
|
|
88519
|
+
}
|
|
88520
|
+
return {
|
|
88521
|
+
handler: null,
|
|
88522
|
+
params: {},
|
|
88523
|
+
middleware: []
|
|
88524
|
+
};
|
|
88525
|
+
}
|
|
88526
|
+
collectMiddlewarePublic(path4, routeMiddleware) {
|
|
88527
|
+
return this.collectMiddleware(path4, routeMiddleware);
|
|
88528
|
+
}
|
|
88529
|
+
collectMiddleware(path4, routeMiddleware) {
|
|
88530
|
+
if (this.globalMiddleware.length === 0 && this.pathMiddleware.size === 0 && routeMiddleware.length === 0) {
|
|
88531
|
+
return [];
|
|
88532
|
+
}
|
|
88533
|
+
const middleware = [];
|
|
88534
|
+
if (this.globalMiddleware.length > 0) {
|
|
88535
|
+
middleware.push(...this.globalMiddleware);
|
|
88536
|
+
}
|
|
88537
|
+
if (this.pathMiddleware.size > 0) {
|
|
88538
|
+
for (const [pattern, mw] of this.pathMiddleware) {
|
|
88539
|
+
if (pattern.includes(":"))
|
|
88540
|
+
continue;
|
|
88541
|
+
if (this.matchPattern(pattern, path4)) {
|
|
88542
|
+
middleware.push(...mw);
|
|
88543
|
+
}
|
|
88544
|
+
}
|
|
88545
|
+
}
|
|
88546
|
+
if (routeMiddleware.length > 0) {
|
|
88547
|
+
middleware.push(...routeMiddleware);
|
|
88548
|
+
}
|
|
88549
|
+
return middleware;
|
|
88550
|
+
}
|
|
88551
|
+
isStaticPath(path4) {
|
|
88552
|
+
return !path4.includes(":") && !path4.includes("*");
|
|
88553
|
+
}
|
|
88554
|
+
matchPattern(pattern, path4) {
|
|
88555
|
+
if (pattern === "*")
|
|
88556
|
+
return true;
|
|
88557
|
+
if (pattern === path4)
|
|
88558
|
+
return true;
|
|
88559
|
+
if (pattern.endsWith("/*")) {
|
|
88560
|
+
const prefix = pattern.slice(0, -2);
|
|
88561
|
+
return path4.startsWith(prefix);
|
|
88562
|
+
}
|
|
88563
|
+
return false;
|
|
88564
|
+
}
|
|
88565
|
+
findDynamicRouteKey(method, path4) {
|
|
88566
|
+
for (const key of this.pathMiddleware.keys()) {
|
|
88567
|
+
if (key.startsWith(`${method}:`)) {
|
|
88568
|
+
return key;
|
|
88569
|
+
}
|
|
88570
|
+
}
|
|
88571
|
+
return null;
|
|
88572
|
+
}
|
|
88573
|
+
getRoutes() {
|
|
88574
|
+
const routes = [];
|
|
88575
|
+
for (const key of this.staticRoutes.keys()) {
|
|
88576
|
+
const [method, path4] = key.split(":");
|
|
88577
|
+
routes.push({ method, path: path4, type: "static" });
|
|
88578
|
+
}
|
|
88579
|
+
return routes;
|
|
88580
|
+
}
|
|
88581
|
+
}
|
|
88582
|
+
|
|
88583
|
+
// ../core/src/engine/analyzer.ts
|
|
88584
|
+
function analyzeHandler(handler) {
|
|
88585
|
+
const source = handler.toString();
|
|
88586
|
+
return {
|
|
88587
|
+
usesHeaders: source.includes(".header(") || source.includes(".header)") || source.includes(".headers(") || source.includes(".headers)"),
|
|
88588
|
+
usesQuery: source.includes(".query(") || source.includes(".query)") || source.includes(".queries(") || source.includes(".queries)"),
|
|
88589
|
+
usesBody: source.includes(".json()") || source.includes(".text()") || source.includes(".formData()") || source.includes(".body"),
|
|
88590
|
+
usesParams: source.includes(".param(") || source.includes(".param)") || source.includes(".params(") || source.includes(".params)"),
|
|
88591
|
+
isAsync: source.includes("async") || source.includes("await")
|
|
88592
|
+
};
|
|
88593
|
+
}
|
|
88594
|
+
function getOptimalContextType(analysis) {
|
|
88595
|
+
if (analysis.usesHeaders) {
|
|
88596
|
+
return "fast";
|
|
88597
|
+
}
|
|
88598
|
+
if (!analysis.usesQuery && !analysis.usesBody && !analysis.usesParams) {
|
|
88599
|
+
return "minimal";
|
|
88600
|
+
}
|
|
88601
|
+
if (!analysis.usesQuery && !analysis.usesBody && analysis.usesParams) {
|
|
88602
|
+
return "minimal";
|
|
88603
|
+
}
|
|
88604
|
+
if (analysis.usesBody) {
|
|
88605
|
+
return "full";
|
|
88606
|
+
}
|
|
88607
|
+
return "fast";
|
|
88608
|
+
}
|
|
88609
|
+
|
|
88610
|
+
// ../core/src/engine/FastContext.ts
|
|
88611
|
+
class FastRequestImpl {
|
|
88612
|
+
_request;
|
|
88613
|
+
_params;
|
|
88614
|
+
_url = new URL("http://localhost");
|
|
88615
|
+
_query = null;
|
|
88616
|
+
_headers = null;
|
|
88617
|
+
reset(request, params = {}) {
|
|
88618
|
+
this._request = request;
|
|
88619
|
+
this._params = params;
|
|
88620
|
+
this._url.href = request.url;
|
|
88621
|
+
this._query = null;
|
|
88622
|
+
this._headers = null;
|
|
88623
|
+
}
|
|
88624
|
+
get url() {
|
|
88625
|
+
return this._request.url;
|
|
88626
|
+
}
|
|
88627
|
+
get method() {
|
|
88628
|
+
return this._request.method;
|
|
88629
|
+
}
|
|
88630
|
+
get path() {
|
|
88631
|
+
return this._url.pathname;
|
|
88632
|
+
}
|
|
88633
|
+
param(name) {
|
|
88634
|
+
return this._params[name];
|
|
88635
|
+
}
|
|
88636
|
+
params() {
|
|
88637
|
+
return { ...this._params };
|
|
88638
|
+
}
|
|
88639
|
+
query(name) {
|
|
88640
|
+
if (!this._query) {
|
|
88641
|
+
this._query = this._url.searchParams;
|
|
88642
|
+
}
|
|
88643
|
+
return this._query.get(name) ?? undefined;
|
|
88644
|
+
}
|
|
88645
|
+
queries() {
|
|
88646
|
+
if (!this._query) {
|
|
88647
|
+
this._query = this._url.searchParams;
|
|
88648
|
+
}
|
|
88649
|
+
const result = {};
|
|
88650
|
+
for (const [key, value] of this._query.entries()) {
|
|
88651
|
+
const existing = result[key];
|
|
88652
|
+
if (existing === undefined) {
|
|
88653
|
+
result[key] = value;
|
|
88654
|
+
} else if (Array.isArray(existing)) {
|
|
88655
|
+
existing.push(value);
|
|
88656
|
+
} else {
|
|
88657
|
+
result[key] = [existing, value];
|
|
88658
|
+
}
|
|
88659
|
+
}
|
|
88660
|
+
return result;
|
|
88661
|
+
}
|
|
88662
|
+
header(name) {
|
|
88663
|
+
return this._request.headers.get(name) ?? undefined;
|
|
88664
|
+
}
|
|
88665
|
+
headers() {
|
|
88666
|
+
if (!this._headers) {
|
|
88667
|
+
this._headers = {};
|
|
88668
|
+
for (const [key, value] of this._request.headers.entries()) {
|
|
88669
|
+
this._headers[key] = value;
|
|
88670
|
+
}
|
|
88671
|
+
}
|
|
88672
|
+
return { ...this._headers };
|
|
88673
|
+
}
|
|
88674
|
+
async json() {
|
|
88675
|
+
return this._request.json();
|
|
88676
|
+
}
|
|
88677
|
+
async text() {
|
|
88678
|
+
return this._request.text();
|
|
88679
|
+
}
|
|
88680
|
+
async formData() {
|
|
88681
|
+
return this._request.formData();
|
|
88682
|
+
}
|
|
88683
|
+
get raw() {
|
|
88684
|
+
return this._request;
|
|
88685
|
+
}
|
|
88686
|
+
}
|
|
88687
|
+
|
|
88688
|
+
class FastContext {
|
|
88689
|
+
_req = new FastRequestImpl;
|
|
88690
|
+
_statusCode = 200;
|
|
88691
|
+
_headers = new Headers;
|
|
88692
|
+
reset(request, params = {}) {
|
|
88693
|
+
this._req.reset(request, params);
|
|
88694
|
+
this._statusCode = 200;
|
|
88695
|
+
this._headers = new Headers;
|
|
88696
|
+
return this;
|
|
88697
|
+
}
|
|
88698
|
+
get req() {
|
|
88699
|
+
return this._req;
|
|
88700
|
+
}
|
|
88701
|
+
json(data2, status = 200) {
|
|
88702
|
+
this._headers.set("Content-Type", "application/json; charset=utf-8");
|
|
88703
|
+
return new Response(JSON.stringify(data2), {
|
|
88704
|
+
status,
|
|
88705
|
+
headers: this._headers
|
|
88706
|
+
});
|
|
88707
|
+
}
|
|
88708
|
+
text(text, status = 200) {
|
|
88709
|
+
this._headers.set("Content-Type", "text/plain; charset=utf-8");
|
|
88710
|
+
return new Response(text, {
|
|
88711
|
+
status,
|
|
88712
|
+
headers: this._headers
|
|
88713
|
+
});
|
|
88714
|
+
}
|
|
88715
|
+
html(html, status = 200) {
|
|
88716
|
+
this._headers.set("Content-Type", "text/html; charset=utf-8");
|
|
88717
|
+
return new Response(html, {
|
|
88718
|
+
status,
|
|
88719
|
+
headers: this._headers
|
|
88720
|
+
});
|
|
88721
|
+
}
|
|
88722
|
+
redirect(url, status = 302) {
|
|
88723
|
+
this._headers.set("Location", url);
|
|
88724
|
+
return new Response(null, {
|
|
88725
|
+
status,
|
|
88726
|
+
headers: this._headers
|
|
88727
|
+
});
|
|
88728
|
+
}
|
|
88729
|
+
body(data2, status = 200) {
|
|
88730
|
+
return new Response(data2, {
|
|
88731
|
+
status,
|
|
88732
|
+
headers: this._headers
|
|
88733
|
+
});
|
|
88734
|
+
}
|
|
88735
|
+
header(name, value) {
|
|
88736
|
+
this._headers.set(name, value);
|
|
88737
|
+
}
|
|
88738
|
+
status(code) {
|
|
88739
|
+
this._statusCode = code;
|
|
88740
|
+
}
|
|
88741
|
+
}
|
|
88742
|
+
|
|
88743
|
+
// ../core/src/engine/MinimalContext.ts
|
|
88744
|
+
class MinimalRequest {
|
|
88745
|
+
_request;
|
|
88746
|
+
_params;
|
|
88747
|
+
_path;
|
|
88748
|
+
constructor(_request, _params, _path) {
|
|
88749
|
+
this._request = _request;
|
|
88750
|
+
this._params = _params;
|
|
88751
|
+
this._path = _path;
|
|
88752
|
+
}
|
|
88753
|
+
get url() {
|
|
88754
|
+
return this._request.url;
|
|
88755
|
+
}
|
|
88756
|
+
get method() {
|
|
88757
|
+
return this._request.method;
|
|
88758
|
+
}
|
|
88759
|
+
get path() {
|
|
88760
|
+
return this._path;
|
|
88761
|
+
}
|
|
88762
|
+
param(name) {
|
|
88763
|
+
return this._params[name];
|
|
88764
|
+
}
|
|
88765
|
+
params() {
|
|
88766
|
+
return { ...this._params };
|
|
88767
|
+
}
|
|
88768
|
+
query(name) {
|
|
88769
|
+
const url = new URL(this._request.url);
|
|
88770
|
+
return url.searchParams.get(name) ?? undefined;
|
|
88771
|
+
}
|
|
88772
|
+
queries() {
|
|
88773
|
+
const url = new URL(this._request.url);
|
|
88774
|
+
const result = {};
|
|
88775
|
+
for (const [key, value] of url.searchParams.entries()) {
|
|
88776
|
+
const existing = result[key];
|
|
88777
|
+
if (existing === undefined) {
|
|
88778
|
+
result[key] = value;
|
|
88779
|
+
} else if (Array.isArray(existing)) {
|
|
88780
|
+
existing.push(value);
|
|
88781
|
+
} else {
|
|
88782
|
+
result[key] = [existing, value];
|
|
88783
|
+
}
|
|
88784
|
+
}
|
|
88785
|
+
return result;
|
|
88786
|
+
}
|
|
88787
|
+
header(name) {
|
|
88788
|
+
return this._request.headers.get(name) ?? undefined;
|
|
88789
|
+
}
|
|
88790
|
+
headers() {
|
|
88791
|
+
const result = {};
|
|
88792
|
+
for (const [key, value] of this._request.headers.entries()) {
|
|
88793
|
+
result[key] = value;
|
|
88794
|
+
}
|
|
88795
|
+
return result;
|
|
88796
|
+
}
|
|
88797
|
+
async json() {
|
|
88798
|
+
return this._request.json();
|
|
88799
|
+
}
|
|
88800
|
+
async text() {
|
|
88801
|
+
return this._request.text();
|
|
88802
|
+
}
|
|
88803
|
+
async formData() {
|
|
88804
|
+
return this._request.formData();
|
|
88805
|
+
}
|
|
88806
|
+
get raw() {
|
|
88807
|
+
return this._request;
|
|
88808
|
+
}
|
|
88809
|
+
}
|
|
88810
|
+
|
|
88811
|
+
class MinimalContext {
|
|
88812
|
+
_req;
|
|
88813
|
+
constructor(request, params, path4) {
|
|
88814
|
+
this._req = new MinimalRequest(request, params, path4);
|
|
88815
|
+
}
|
|
88816
|
+
get req() {
|
|
88817
|
+
return this._req;
|
|
88818
|
+
}
|
|
88819
|
+
json(data2, status = 200) {
|
|
88820
|
+
return new Response(JSON.stringify(data2), {
|
|
88821
|
+
status,
|
|
88822
|
+
headers: { "Content-Type": "application/json; charset=utf-8" }
|
|
88823
|
+
});
|
|
88824
|
+
}
|
|
88825
|
+
text(text, status = 200) {
|
|
88826
|
+
return new Response(text, {
|
|
88827
|
+
status,
|
|
88828
|
+
headers: { "Content-Type": "text/plain; charset=utf-8" }
|
|
88829
|
+
});
|
|
88830
|
+
}
|
|
88831
|
+
html(html, status = 200) {
|
|
88832
|
+
return new Response(html, {
|
|
88833
|
+
status,
|
|
88834
|
+
headers: { "Content-Type": "text/html; charset=utf-8" }
|
|
88835
|
+
});
|
|
88836
|
+
}
|
|
88837
|
+
redirect(url, status = 302) {
|
|
88838
|
+
return new Response(null, {
|
|
88839
|
+
status,
|
|
88840
|
+
headers: { Location: url }
|
|
88841
|
+
});
|
|
88842
|
+
}
|
|
88843
|
+
body(data2, status = 200) {
|
|
88844
|
+
return new Response(data2, { status });
|
|
88845
|
+
}
|
|
88846
|
+
header(_name, _value) {
|
|
88847
|
+
console.warn("MinimalContext.header() is a no-op. Use FastContext for custom headers.");
|
|
88848
|
+
}
|
|
88849
|
+
status(_code) {}
|
|
88850
|
+
reset(_request, _params) {
|
|
88851
|
+
throw new Error("MinimalContext does not support reset. Create a new instance instead.");
|
|
88852
|
+
}
|
|
88853
|
+
}
|
|
88854
|
+
|
|
88855
|
+
// ../core/src/engine/path.ts
|
|
88856
|
+
function extractPath(url) {
|
|
88857
|
+
const protocolEnd = url.indexOf("://");
|
|
88858
|
+
const searchStart = protocolEnd === -1 ? 0 : protocolEnd + 3;
|
|
88859
|
+
const pathStart = url.indexOf("/", searchStart);
|
|
88860
|
+
if (pathStart === -1) {
|
|
88861
|
+
return "/";
|
|
88862
|
+
}
|
|
88863
|
+
const queryStart = url.indexOf("?", pathStart);
|
|
88864
|
+
if (queryStart === -1) {
|
|
88865
|
+
return url.slice(pathStart);
|
|
88866
|
+
}
|
|
88867
|
+
return url.slice(pathStart, queryStart);
|
|
88868
|
+
}
|
|
88869
|
+
|
|
88870
|
+
// ../core/src/engine/pool.ts
|
|
88871
|
+
class ObjectPool {
|
|
88872
|
+
pool = [];
|
|
88873
|
+
factory;
|
|
88874
|
+
reset;
|
|
88875
|
+
maxSize;
|
|
88876
|
+
constructor(factory, reset, maxSize = 256) {
|
|
88877
|
+
this.factory = factory;
|
|
88878
|
+
this.reset = reset;
|
|
88879
|
+
this.maxSize = maxSize;
|
|
88880
|
+
}
|
|
88881
|
+
acquire() {
|
|
88882
|
+
const obj = this.pool.pop();
|
|
88883
|
+
if (obj !== undefined) {
|
|
88884
|
+
return obj;
|
|
88885
|
+
}
|
|
88886
|
+
return this.factory();
|
|
88887
|
+
}
|
|
88888
|
+
release(obj) {
|
|
88889
|
+
if (this.pool.length < this.maxSize) {
|
|
88890
|
+
this.reset(obj);
|
|
88891
|
+
this.pool.push(obj);
|
|
88892
|
+
}
|
|
88893
|
+
}
|
|
88894
|
+
clear() {
|
|
88895
|
+
this.pool = [];
|
|
88896
|
+
}
|
|
88897
|
+
get size() {
|
|
88898
|
+
return this.pool.length;
|
|
88899
|
+
}
|
|
88900
|
+
get capacity() {
|
|
88901
|
+
return this.maxSize;
|
|
88902
|
+
}
|
|
88903
|
+
prewarm(count) {
|
|
88904
|
+
const targetSize = Math.min(count, this.maxSize);
|
|
88905
|
+
while (this.pool.length < targetSize) {
|
|
88906
|
+
const obj = this.factory();
|
|
88907
|
+
this.reset(obj);
|
|
88908
|
+
this.pool.push(obj);
|
|
88909
|
+
}
|
|
88910
|
+
}
|
|
88911
|
+
}
|
|
88912
|
+
|
|
88913
|
+
// ../core/src/engine/Gravito.ts
|
|
88914
|
+
class Gravito {
|
|
88915
|
+
router = new AOTRouter;
|
|
88916
|
+
contextPool;
|
|
88917
|
+
errorHandler;
|
|
88918
|
+
notFoundHandler;
|
|
88919
|
+
staticRoutes;
|
|
88920
|
+
isPureStaticApp = true;
|
|
88921
|
+
constructor(options = {}) {
|
|
88922
|
+
const poolSize = options.poolSize ?? 256;
|
|
88923
|
+
this.contextPool = new ObjectPool(() => new FastContext, (ctx) => ctx.reset(new Request("http://localhost")), poolSize);
|
|
88924
|
+
this.contextPool.prewarm(Math.min(32, poolSize));
|
|
88925
|
+
if (options.onError) {
|
|
88926
|
+
this.errorHandler = options.onError;
|
|
88927
|
+
}
|
|
88928
|
+
if (options.onNotFound) {
|
|
88929
|
+
this.notFoundHandler = options.onNotFound;
|
|
88930
|
+
}
|
|
88931
|
+
this.compileRoutes();
|
|
88932
|
+
}
|
|
88933
|
+
get(path4, ...handlers) {
|
|
88934
|
+
return this.addRoute("get", path4, handlers);
|
|
88935
|
+
}
|
|
88936
|
+
post(path4, ...handlers) {
|
|
88937
|
+
return this.addRoute("post", path4, handlers);
|
|
88938
|
+
}
|
|
88939
|
+
put(path4, ...handlers) {
|
|
88940
|
+
return this.addRoute("put", path4, handlers);
|
|
88941
|
+
}
|
|
88942
|
+
delete(path4, ...handlers) {
|
|
88943
|
+
return this.addRoute("delete", path4, handlers);
|
|
88944
|
+
}
|
|
88945
|
+
patch(path4, ...handlers) {
|
|
88946
|
+
return this.addRoute("patch", path4, handlers);
|
|
88947
|
+
}
|
|
88948
|
+
options(path4, ...handlers) {
|
|
88949
|
+
return this.addRoute("options", path4, handlers);
|
|
88950
|
+
}
|
|
88951
|
+
head(path4, ...handlers) {
|
|
88952
|
+
return this.addRoute("head", path4, handlers);
|
|
88953
|
+
}
|
|
88954
|
+
all(path4, ...handlers) {
|
|
88955
|
+
const methods = ["get", "post", "put", "delete", "patch", "options", "head"];
|
|
88956
|
+
for (const method of methods) {
|
|
88957
|
+
this.addRoute(method, path4, handlers);
|
|
88958
|
+
}
|
|
88959
|
+
return this;
|
|
88960
|
+
}
|
|
88961
|
+
use(pathOrMiddleware, ...middleware) {
|
|
88962
|
+
this.isPureStaticApp = false;
|
|
88963
|
+
if (typeof pathOrMiddleware === "string") {
|
|
88964
|
+
this.router.usePattern(pathOrMiddleware, ...middleware);
|
|
88965
|
+
} else {
|
|
88966
|
+
this.router.use(pathOrMiddleware, ...middleware);
|
|
88967
|
+
}
|
|
88968
|
+
return this;
|
|
88969
|
+
}
|
|
88970
|
+
route(path4, app2) {
|
|
88971
|
+
console.warn("route() method is not yet fully implemented");
|
|
88972
|
+
return this;
|
|
88973
|
+
}
|
|
88974
|
+
onError(handler) {
|
|
88975
|
+
this.errorHandler = handler;
|
|
88976
|
+
return this;
|
|
88977
|
+
}
|
|
88978
|
+
notFound(handler) {
|
|
88979
|
+
this.notFoundHandler = handler;
|
|
88980
|
+
return this;
|
|
88981
|
+
}
|
|
88982
|
+
fetch = (request) => {
|
|
88983
|
+
const path4 = extractPath(request.url);
|
|
88984
|
+
const method = request.method.toLowerCase();
|
|
88985
|
+
const staticKey = `${method}:${path4}`;
|
|
88986
|
+
const staticRoute = this.staticRoutes.get(staticKey);
|
|
88987
|
+
if (staticRoute) {
|
|
88988
|
+
if (staticRoute.useMinimal) {
|
|
88989
|
+
const ctx = new MinimalContext(request, {}, path4);
|
|
88990
|
+
try {
|
|
88991
|
+
const result = staticRoute.handler(ctx);
|
|
88992
|
+
if (result instanceof Response) {
|
|
88993
|
+
return result;
|
|
88994
|
+
}
|
|
88995
|
+
return result;
|
|
88996
|
+
} catch (error) {
|
|
88997
|
+
return this.handleErrorSync(error, request, path4);
|
|
88998
|
+
}
|
|
88999
|
+
}
|
|
89000
|
+
return this.handleWithMiddleware(request, path4, staticRoute);
|
|
89001
|
+
}
|
|
89002
|
+
return this.handleDynamicRoute(request, method, path4);
|
|
89003
|
+
};
|
|
89004
|
+
async handleWithMiddleware(request, path4, route) {
|
|
89005
|
+
const ctx = this.contextPool.acquire();
|
|
89006
|
+
try {
|
|
89007
|
+
ctx.reset(request, {});
|
|
89008
|
+
const middleware = this.collectMiddlewareForPath(path4, route.middleware);
|
|
89009
|
+
if (middleware.length === 0) {
|
|
89010
|
+
return await route.handler(ctx);
|
|
89011
|
+
}
|
|
89012
|
+
return await this.executeMiddleware(ctx, middleware, route.handler);
|
|
89013
|
+
} catch (error) {
|
|
89014
|
+
return await this.handleError(error, ctx);
|
|
89015
|
+
} finally {
|
|
89016
|
+
this.contextPool.release(ctx);
|
|
89017
|
+
}
|
|
89018
|
+
}
|
|
89019
|
+
handleDynamicRoute(request, method, path4) {
|
|
89020
|
+
const match2 = this.router.match(method.toUpperCase(), path4);
|
|
89021
|
+
if (!match2.handler) {
|
|
89022
|
+
return this.handleNotFoundSync(request, path4);
|
|
89023
|
+
}
|
|
89024
|
+
const ctx = this.contextPool.acquire();
|
|
89025
|
+
const execute = async () => {
|
|
89026
|
+
try {
|
|
89027
|
+
ctx.reset(request, match2.params);
|
|
89028
|
+
if (match2.middleware.length === 0) {
|
|
89029
|
+
return await match2.handler(ctx);
|
|
89030
|
+
}
|
|
89031
|
+
return await this.executeMiddleware(ctx, match2.middleware, match2.handler);
|
|
89032
|
+
} catch (error) {
|
|
89033
|
+
return await this.handleError(error, ctx);
|
|
89034
|
+
} finally {
|
|
89035
|
+
this.contextPool.release(ctx);
|
|
89036
|
+
}
|
|
89037
|
+
};
|
|
89038
|
+
return execute();
|
|
89039
|
+
}
|
|
89040
|
+
handleErrorSync(error, request, path4) {
|
|
89041
|
+
if (this.errorHandler) {
|
|
89042
|
+
const ctx = new MinimalContext(request, {}, path4);
|
|
89043
|
+
const result = this.errorHandler(error, ctx);
|
|
89044
|
+
if (result instanceof Response) {
|
|
89045
|
+
return result;
|
|
89046
|
+
}
|
|
89047
|
+
return result;
|
|
89048
|
+
}
|
|
89049
|
+
console.error("Unhandled error:", error);
|
|
89050
|
+
return new Response(JSON.stringify({
|
|
89051
|
+
error: "Internal Server Error",
|
|
89052
|
+
message: error.message
|
|
89053
|
+
}), {
|
|
89054
|
+
status: 500,
|
|
89055
|
+
headers: { "Content-Type": "application/json" }
|
|
89056
|
+
});
|
|
89057
|
+
}
|
|
89058
|
+
handleNotFoundSync(request, path4) {
|
|
89059
|
+
if (this.notFoundHandler) {
|
|
89060
|
+
const ctx = new MinimalContext(request, {}, path4);
|
|
89061
|
+
const result = this.notFoundHandler(ctx);
|
|
89062
|
+
if (result instanceof Response) {
|
|
89063
|
+
return result;
|
|
89064
|
+
}
|
|
89065
|
+
return result;
|
|
89066
|
+
}
|
|
89067
|
+
return new Response(JSON.stringify({ error: "Not Found" }), {
|
|
89068
|
+
status: 404,
|
|
89069
|
+
headers: { "Content-Type": "application/json" }
|
|
89070
|
+
});
|
|
89071
|
+
}
|
|
89072
|
+
collectMiddlewareForPath(path4, routeMiddleware) {
|
|
89073
|
+
if (this.router.globalMiddleware.length === 0 && this.router.pathMiddleware.size === 0) {
|
|
89074
|
+
return routeMiddleware;
|
|
89075
|
+
}
|
|
89076
|
+
return this.router.collectMiddlewarePublic(path4, routeMiddleware);
|
|
89077
|
+
}
|
|
89078
|
+
compileRoutes() {
|
|
89079
|
+
this.staticRoutes = this.router.staticRoutes;
|
|
89080
|
+
const hasGlobalMiddleware = this.router.globalMiddleware.length > 0;
|
|
89081
|
+
const hasPathMiddleware = this.router.pathMiddleware.size > 0;
|
|
89082
|
+
this.isPureStaticApp = !hasGlobalMiddleware && !hasPathMiddleware;
|
|
89083
|
+
for (const [_key, route] of this.staticRoutes) {
|
|
89084
|
+
const analysis = analyzeHandler(route.handler);
|
|
89085
|
+
const optimalType = getOptimalContextType(analysis);
|
|
89086
|
+
route.useMinimal = this.isPureStaticApp && route.middleware.length === 0 && optimalType === "minimal";
|
|
89087
|
+
}
|
|
89088
|
+
}
|
|
89089
|
+
addRoute(method, path4, handlers) {
|
|
89090
|
+
if (handlers.length === 0) {
|
|
89091
|
+
throw new Error(`No handler provided for ${method.toUpperCase()} ${path4}`);
|
|
89092
|
+
}
|
|
89093
|
+
const handler = handlers[handlers.length - 1];
|
|
89094
|
+
const middleware = handlers.slice(0, -1);
|
|
89095
|
+
this.router.add(method, path4, handler, middleware);
|
|
89096
|
+
this.compileRoutes();
|
|
89097
|
+
return this;
|
|
89098
|
+
}
|
|
89099
|
+
async executeMiddleware(ctx, middleware, handler) {
|
|
89100
|
+
let index = 0;
|
|
89101
|
+
const next = async () => {
|
|
89102
|
+
if (index < middleware.length) {
|
|
89103
|
+
const mw = middleware[index++];
|
|
89104
|
+
await mw(ctx, next);
|
|
89105
|
+
}
|
|
89106
|
+
};
|
|
89107
|
+
await next();
|
|
89108
|
+
return await handler(ctx);
|
|
89109
|
+
}
|
|
89110
|
+
async handleNotFound(ctx) {
|
|
89111
|
+
if (this.notFoundHandler) {
|
|
89112
|
+
return await this.notFoundHandler(ctx);
|
|
89113
|
+
}
|
|
89114
|
+
return ctx.json({ error: "Not Found" }, 404);
|
|
89115
|
+
}
|
|
89116
|
+
async handleError(error, ctx) {
|
|
89117
|
+
if (this.errorHandler) {
|
|
89118
|
+
return await this.errorHandler(error, ctx);
|
|
89119
|
+
}
|
|
89120
|
+
console.error("Unhandled error:", error);
|
|
89121
|
+
return ctx.json({
|
|
89122
|
+
error: "Internal Server Error",
|
|
89123
|
+
message: error.message
|
|
89124
|
+
}, 500);
|
|
89125
|
+
}
|
|
89126
|
+
}
|
|
88447
89127
|
// ../core/src/index.ts
|
|
88448
89128
|
var VERSION = package_default.version;
|
|
88449
89129
|
|