shokupan 0.16.4 → 0.16.5

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.
@@ -4888,7 +4888,7 @@ class ApiExplorerPlugin extends ShokupanRouter {
4888
4888
  }
4889
4889
  }
4890
4890
  static getBasePath() {
4891
- const dir = path$1.dirname(node_url.fileURLToPath(typeof document === "undefined" ? require("url").pathToFileURL(__filename).href : _documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === "SCRIPT" && _documentCurrentScript.src || new URL("index-BLdx5fql.cjs", document.baseURI).href));
4891
+ const dir = path$1.dirname(node_url.fileURLToPath(typeof document === "undefined" ? require("url").pathToFileURL(__filename).href : _documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === "SCRIPT" && _documentCurrentScript.src || new URL("index-Cx60P13T.cjs", document.baseURI).href));
4892
4892
  if (dir.endsWith("dist")) {
4893
4893
  return dir + "/plugins/application/api-explorer";
4894
4894
  }
@@ -5692,7 +5692,7 @@ class AsyncApiPlugin extends ShokupanRouter {
5692
5692
  this.init();
5693
5693
  }
5694
5694
  static getBasePath() {
5695
- const dir = path$1.dirname(node_url.fileURLToPath(typeof document === "undefined" ? require("url").pathToFileURL(__filename).href : _documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === "SCRIPT" && _documentCurrentScript.src || new URL("index-BLdx5fql.cjs", document.baseURI).href));
5695
+ const dir = path$1.dirname(node_url.fileURLToPath(typeof document === "undefined" ? require("url").pathToFileURL(__filename).href : _documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === "SCRIPT" && _documentCurrentScript.src || new URL("index-Cx60P13T.cjs", document.baseURI).href));
5696
5696
  if (dir.endsWith("dist")) {
5697
5697
  return dir + "/plugins/application/asyncapi";
5698
5698
  }
@@ -6216,7 +6216,7 @@ function createHTTPLogger() {
6216
6216
  return result;
6217
6217
  };
6218
6218
  }
6219
- const require$1 = node_module.createRequire(typeof document === "undefined" ? require("url").pathToFileURL(__filename).href : _documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === "SCRIPT" && _documentCurrentScript.src || new URL("index-BLdx5fql.cjs", document.baseURI).href);
6219
+ const require$1 = node_module.createRequire(typeof document === "undefined" ? require("url").pathToFileURL(__filename).href : _documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === "SCRIPT" && _documentCurrentScript.src || new URL("index-Cx60P13T.cjs", document.baseURI).href);
6220
6220
  const http = require$1("node:http");
6221
6221
  const https = require$1("node:https");
6222
6222
  class FetchInterceptor {
@@ -6823,7 +6823,7 @@ class Dashboard {
6823
6823
  }
6824
6824
  // Get base path for dashboard files - works in both dev (src/) and production (dist/)
6825
6825
  static getBasePath() {
6826
- const dir = path$1.dirname(node_url.fileURLToPath(typeof document === "undefined" ? require("url").pathToFileURL(__filename).href : _documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === "SCRIPT" && _documentCurrentScript.src || new URL("index-BLdx5fql.cjs", document.baseURI).href));
6826
+ const dir = path$1.dirname(node_url.fileURLToPath(typeof document === "undefined" ? require("url").pathToFileURL(__filename).href : _documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === "SCRIPT" && _documentCurrentScript.src || new URL("index-Cx60P13T.cjs", document.baseURI).href));
6827
6827
  if (dir.endsWith("dist")) {
6828
6828
  return dir + "/plugins/application/dashboard";
6829
6829
  }
@@ -9814,6 +9814,7 @@ class Shokupan extends ShokupanRouter {
9814
9814
  startupHooks = [];
9815
9815
  plugins = [];
9816
9816
  specAvailableHooks = [];
9817
+ pluginInitPromises = [];
9817
9818
  get db() {
9818
9819
  return this.datastore;
9819
9820
  }
@@ -9926,24 +9927,24 @@ class Shokupan extends ShokupanRouter {
9926
9927
  try {
9927
9928
  switch (adapterName) {
9928
9929
  case "sqlite": {
9929
- const { SqliteAdapter } = await Promise.resolve().then(() => require("./sqlite-Tbm9zDxt.cjs"));
9930
+ const { SqliteAdapter } = await Promise.resolve().then(() => require("./sqlite-CvoMrQNx.cjs"));
9930
9931
  this.datastore = new SqliteAdapter(options);
9931
9932
  break;
9932
9933
  }
9933
9934
  case "level": {
9934
- const { LevelAdapter } = await Promise.resolve().then(() => require("./level-ySRat4Qf.cjs"));
9935
+ const { LevelAdapter } = await Promise.resolve().then(() => require("./level-DzWOqk9S.cjs"));
9935
9936
  this.datastore = new LevelAdapter(options);
9936
9937
  break;
9937
9938
  }
9938
9939
  case "surrealdb": {
9939
- const { SurrealAdapter } = await Promise.resolve().then(() => require("./surreal-DGDSgKuP.cjs"));
9940
+ const { SurrealAdapter } = await Promise.resolve().then(() => require("./surreal-DOJpgKP7.cjs"));
9940
9941
  const legacyConfig = this.applicationConfig.surreal || {};
9941
9942
  const effectiveOptions = { ...legacyConfig, ...options };
9942
9943
  this.datastore = new SurrealAdapter(effectiveOptions);
9943
9944
  break;
9944
9945
  }
9945
9946
  default: {
9946
- const { SurrealAdapter } = await Promise.resolve().then(() => require("./surreal-DGDSgKuP.cjs"));
9947
+ const { SurrealAdapter } = await Promise.resolve().then(() => require("./surreal-DOJpgKP7.cjs"));
9947
9948
  const legacy = this.applicationConfig.surreal;
9948
9949
  this.datastore = new SurrealAdapter(options || legacy || {});
9949
9950
  }
@@ -9979,11 +9980,16 @@ class Shokupan extends ShokupanRouter {
9979
9980
  }
9980
9981
  /**
9981
9982
  * Registers a plugin.
9983
+ * This returns a promise that resolves when the plugin is initialized. You do not
9984
+ * need to await it unless you want to run code specifically after the plugin is initialized.
9985
+ * Shokupan automatically awaits plugin initialization promises when calling listen().
9982
9986
  */
9983
9987
  async register(plugin, options) {
9984
9988
  this.plugins.push(plugin);
9985
9989
  try {
9986
- await plugin.onInit(this, options);
9990
+ const promise = plugin.onInit(this, options);
9991
+ this.pluginInitPromises.push(promise);
9992
+ await promise;
9987
9993
  } catch (err) {
9988
9994
  this.logger?.error("Shokupan", "Failed to initialize plugin", { error: err });
9989
9995
  throw err;
@@ -10149,6 +10155,7 @@ class Shokupan extends ShokupanRouter {
10149
10155
  */
10150
10156
  async listen(port, callback) {
10151
10157
  this.httpServer = new ShokupanServer(this);
10158
+ await Promise.allSettled(this.pluginInitPromises);
10152
10159
  this.server = await this.httpServer.listen(port);
10153
10160
  const protocol = this.applicationConfig.tls || this.applicationConfig.development ? "https" : "http";
10154
10161
  const url = `${protocol}://${this.applicationConfig.hostname}:${this.applicationConfig.port}`;
@@ -10603,6 +10610,21 @@ class AuthPlugin extends ShokupanRouter {
10603
10610
  return jwt;
10604
10611
  }
10605
10612
  init() {
10613
+ this.get("/auth/me", async (ctx) => {
10614
+ const cookieHeader = ctx.req.headers.get("Cookie");
10615
+ const token = cookieHeader?.match(/auth_token=([^;]+)/)?.[1];
10616
+ if (!token) return ctx.json({ error: "Unauthenticated" }, 401);
10617
+ try {
10618
+ const { payload } = await this.jose.jwtVerify(token, this.secret);
10619
+ return ctx.json(payload);
10620
+ } catch {
10621
+ return ctx.json({ error: "Invalid or expired token" }, 401);
10622
+ }
10623
+ });
10624
+ this.post("/auth/logout", (ctx) => {
10625
+ ctx.set("Set-Cookie", "auth_token=; Path=/; HttpOnly; Max-Age=0; SameSite=Lax");
10626
+ return ctx.json({ ok: true });
10627
+ });
10606
10628
  const { generateState, generateCodeVerifier, GitHub, Google, MicrosoftEntraId, Apple, Auth0, Okta, OAuth2Client } = this.arctic;
10607
10629
  const providerEntries = Object.entries(this.authConfig.providers);
10608
10630
  for (let i = 0; i < providerEntries.length; i++) {
@@ -10640,6 +10662,7 @@ class AuthPlugin extends ShokupanRouter {
10640
10662
  const url = new URL(ctx.req.url);
10641
10663
  const code = url.searchParams.get("code");
10642
10664
  const state = url.searchParams.get("state");
10665
+ console.log("== OAuth Callback Hit ==", { providerName, code, state });
10643
10666
  const cookieHeader = ctx.req.headers.get("Cookie");
10644
10667
  const storedState = cookieHeader?.match(/oauth_state=([^;]+)/)?.[1];
10645
10668
  const storedVerifier = cookieHeader?.match(/oauth_verifier=([^;]+)/)?.[1];
@@ -10663,17 +10686,38 @@ class AuthPlugin extends ShokupanRouter {
10663
10686
  if (!providerConfig.tokenUrl) return ctx.text("Config error: tokenUrl required for oauth2", 500);
10664
10687
  tokens = await provider.validateAuthorizationCode(providerConfig.tokenUrl, code, null);
10665
10688
  }
10666
- const accessToken = tokens.accessToken || tokens.access_token;
10689
+ const accessToken = typeof tokens.accessToken === "function" ? tokens.accessToken() : tokens.accessToken || tokens.access_token;
10690
+ try {
10691
+ if (typeof tokens.idToken === "function") {
10692
+ idToken = tokens.idToken();
10693
+ } else if (tokens.idToken) {
10694
+ idToken = tokens.idToken;
10695
+ }
10696
+ } catch (e) {
10697
+ }
10667
10698
  const user = await this.fetchUser(providerName, accessToken, providerConfig, idToken);
10668
10699
  if (this.authConfig.onSuccess) {
10669
10700
  const res = await this.authConfig.onSuccess(user, ctx);
10670
10701
  if (res) return res;
10671
10702
  }
10672
10703
  const jwt = await this.createSession(user, ctx);
10704
+ if (this.authConfig.successRedirect) {
10705
+ return ctx.redirect(this.authConfig.successRedirect);
10706
+ }
10673
10707
  return ctx.json({ token: jwt, user });
10674
10708
  } catch (e) {
10709
+ console.error("Auth Exception:", e);
10710
+ let extradata = "";
10711
+ try {
10712
+ if (e && e.response) extradata = " | Body: " + await e.response.text();
10713
+ } catch {
10714
+ }
10675
10715
  ctx.app?.logger?.error("Auth", "Authentication failed", e);
10676
- return ctx.text("Authentication failed. Please try again.", 500);
10716
+ return ctx.text(`Authentication failed.
10717
+ Error: ${e?.message ?? String(e)}${extradata}
10718
+
10719
+ Stack:
10720
+ ${e?.stack}`, 500);
10677
10721
  }
10678
10722
  });
10679
10723
  }
@@ -10682,7 +10726,10 @@ class AuthPlugin extends ShokupanRouter {
10682
10726
  let user = { id: "unknown", provider };
10683
10727
  if (provider === "github") {
10684
10728
  const res = await fetch("https://api.github.com/user", {
10685
- headers: { Authorization: `Bearer ${token}` }
10729
+ headers: {
10730
+ Authorization: `Bearer ${token}`,
10731
+ "User-Agent": "Shokupan-Auth/1.0"
10732
+ }
10686
10733
  });
10687
10734
  const data = await res.json();
10688
10735
  user = {
@@ -13067,4 +13114,4 @@ exports.traceMiddleware = traceMiddleware;
13067
13114
  exports.useExpress = useExpress;
13068
13115
  exports.valibot = valibot;
13069
13116
  exports.validate = validate;
13070
- //# sourceMappingURL=index-BLdx5fql.cjs.map
13117
+ //# sourceMappingURL=index-Cx60P13T.cjs.map