@tknf/matchbox 0.2.6 → 0.3.1

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.
Files changed (37) hide show
  1. package/README.md +212 -46
  2. package/dist/cgi.d.ts +10 -21
  3. package/dist/cgi.js +26 -97
  4. package/dist/htaccess/access-control.d.ts +9 -0
  5. package/dist/htaccess/access-control.js +91 -0
  6. package/dist/htaccess/error-document.d.ts +9 -0
  7. package/dist/htaccess/error-document.js +16 -0
  8. package/dist/htaccess/headers.d.ts +32 -0
  9. package/dist/htaccess/headers.js +98 -0
  10. package/dist/htaccess/index.d.ts +8 -0
  11. package/dist/htaccess/index.js +20 -0
  12. package/dist/htaccess/parser.d.ts +9 -0
  13. package/dist/htaccess/parser.js +365 -0
  14. package/dist/htaccess/rewrite.d.ts +13 -0
  15. package/dist/htaccess/rewrite.js +69 -0
  16. package/dist/htaccess/types.d.ts +156 -0
  17. package/dist/htaccess/types.js +0 -0
  18. package/dist/htaccess/utils.d.ts +21 -0
  19. package/dist/htaccess/utils.js +69 -0
  20. package/dist/html.d.ts +1 -0
  21. package/dist/index.d.ts +3 -0
  22. package/dist/index.js +5 -1
  23. package/dist/middleware/auth.d.ts +8 -0
  24. package/dist/middleware/auth.js +28 -0
  25. package/dist/middleware/htaccess.d.ts +13 -0
  26. package/dist/middleware/htaccess.js +42 -0
  27. package/dist/middleware/index.d.ts +10 -0
  28. package/dist/middleware/index.js +14 -0
  29. package/dist/middleware/protected-files.d.ts +8 -0
  30. package/dist/middleware/protected-files.js +14 -0
  31. package/dist/middleware/session.d.ts +16 -0
  32. package/dist/middleware/session.js +37 -0
  33. package/dist/middleware/trailing-slash.d.ts +8 -0
  34. package/dist/middleware/trailing-slash.js +12 -0
  35. package/dist/with-defaults.d.ts +2 -1
  36. package/dist/with-defaults.js +17 -28
  37. package/package.json +1 -1
@@ -0,0 +1,156 @@
1
+ import { Context } from 'hono';
2
+
3
+ /**
4
+ * Main configuration type for .htaccess files (replaces RewriteMap)
5
+ * Maps directory paths to their respective configurations
6
+ */
7
+ type HtaccessConfig = Record<string, DirectoryConfig>;
8
+ /**
9
+ * Configuration for a single directory
10
+ */
11
+ interface DirectoryConfig {
12
+ rewriteRules: RewriteRuleConfig[];
13
+ redirects: RedirectConfig[];
14
+ errorDocuments: ErrorDocumentConfig[];
15
+ headers: HeaderConfig[];
16
+ authConfig?: AuthConfig;
17
+ accessControl?: AccessControlConfig;
18
+ }
19
+ /**
20
+ * RewriteRule configuration
21
+ */
22
+ interface RewriteRuleConfig {
23
+ type: "rewrite";
24
+ pattern: string;
25
+ target: string;
26
+ flags: RewriteFlags;
27
+ conditions: RewriteCondition[];
28
+ }
29
+ /**
30
+ * RewriteCond configuration
31
+ */
32
+ interface RewriteCondition {
33
+ testString: string;
34
+ pattern: string;
35
+ flags: ConditionFlags;
36
+ }
37
+ /**
38
+ * RewriteRule flags
39
+ */
40
+ interface RewriteFlags {
41
+ last?: boolean;
42
+ redirect?: number;
43
+ forbidden?: boolean;
44
+ gone?: boolean;
45
+ noCase?: boolean;
46
+ qsAppend?: boolean;
47
+ qsDiscard?: boolean;
48
+ noEscape?: boolean;
49
+ }
50
+ /**
51
+ * RewriteCond flags
52
+ */
53
+ interface ConditionFlags {
54
+ noCase?: boolean;
55
+ or?: boolean;
56
+ }
57
+ /**
58
+ * ErrorDocument configuration
59
+ */
60
+ interface ErrorDocumentConfig {
61
+ statusCode: number;
62
+ target: string;
63
+ }
64
+ /**
65
+ * Header directive configuration
66
+ */
67
+ interface HeaderConfig {
68
+ action: "set" | "append" | "unset";
69
+ name: string;
70
+ value?: string;
71
+ }
72
+ /**
73
+ * Redirect configuration (legacy support)
74
+ */
75
+ interface RedirectConfig {
76
+ type: "redirect";
77
+ code: number;
78
+ source: string;
79
+ target: string;
80
+ }
81
+ /**
82
+ * Authentication configuration
83
+ */
84
+ interface AuthConfig {
85
+ authType?: "Basic" | "Digest";
86
+ authName?: string;
87
+ authUserFile?: string;
88
+ authGroupFile?: string;
89
+ authDigestProvider?: string;
90
+ require?: RequireConfig[];
91
+ }
92
+ /**
93
+ * Require directive configuration
94
+ */
95
+ interface RequireConfig {
96
+ type: "valid-user" | "user" | "group" | "ip" | "host" | "all";
97
+ value?: string | string[];
98
+ granted?: boolean;
99
+ }
100
+ /**
101
+ * Access Control configuration (Apache 2.2 style - Order/Allow/Deny)
102
+ */
103
+ interface AccessControlConfig {
104
+ order?: "allow,deny" | "deny,allow" | "mutual-failure";
105
+ allow: AccessRule[];
106
+ deny: AccessRule[];
107
+ }
108
+ /**
109
+ * Access rule for Allow/Deny directives
110
+ */
111
+ interface AccessRule {
112
+ type: "all" | "ip" | "host" | "env";
113
+ value?: string | string[];
114
+ }
115
+ /**
116
+ * Variable context for RewriteCond evaluation
117
+ */
118
+ interface VariableContext {
119
+ HTTP_HOST: string;
120
+ HTTP_USER_AGENT: string;
121
+ REQUEST_URI: string;
122
+ QUERY_STRING: string;
123
+ HTTPS: string;
124
+ REMOTE_ADDR: string;
125
+ REQUEST_METHOD: string;
126
+ HTTP_REFERER: string;
127
+ HTTP_ACCEPT: string;
128
+ HTTP_COOKIE: string;
129
+ SERVER_NAME: string;
130
+ SERVER_PORT: string;
131
+ DOCUMENT_ROOT: string;
132
+ REQUEST_FILENAME: string;
133
+ }
134
+ /**
135
+ * Result of applying rewrite flags
136
+ */
137
+ type RewriteResult = {
138
+ type: "continue";
139
+ } | {
140
+ type: "redirect";
141
+ url: string;
142
+ status: number;
143
+ } | {
144
+ type: "forbidden";
145
+ } | {
146
+ type: "gone";
147
+ } | {
148
+ type: "rewrite";
149
+ path: string;
150
+ };
151
+ /**
152
+ * Hono Context (for type compatibility)
153
+ */
154
+ type HonoContext = Context;
155
+
156
+ export type { AccessControlConfig, AccessRule, AuthConfig, ConditionFlags, DirectoryConfig, ErrorDocumentConfig, HeaderConfig, HonoContext, HtaccessConfig, RedirectConfig, RequireConfig, RewriteCondition, RewriteFlags, RewriteResult, RewriteRuleConfig, VariableContext };
File without changes
@@ -0,0 +1,21 @@
1
+ import { Context } from 'hono';
2
+ import { VariableContext, RewriteFlags, RewriteResult, RewriteCondition } from './types.js';
3
+
4
+ /**
5
+ * Build variable context from Hono context
6
+ */
7
+ declare function buildVariableContext(c: Context): VariableContext;
8
+ /**
9
+ * Expand variables like %{HTTP_HOST} in test strings
10
+ */
11
+ declare function expandVariables(testString: string, context: VariableContext): string;
12
+ /**
13
+ * Test a single RewriteCond
14
+ */
15
+ declare function testCondition(condition: RewriteCondition, context: VariableContext): boolean;
16
+ /**
17
+ * Apply rewrite flags to determine result
18
+ */
19
+ declare function applyRewriteFlags(target: string, flags: RewriteFlags, context: Context): RewriteResult;
20
+
21
+ export { applyRewriteFlags, buildVariableContext, expandVariables, testCondition };
@@ -0,0 +1,69 @@
1
+ function buildVariableContext(c) {
2
+ const url = new URL(c.req.url);
3
+ return {
4
+ HTTP_HOST: c.req.header("host") || "",
5
+ HTTP_USER_AGENT: c.req.header("user-agent") || "",
6
+ REQUEST_URI: c.req.path,
7
+ QUERY_STRING: url.search.slice(1),
8
+ HTTPS: url.protocol === "https:" ? "on" : "off",
9
+ REMOTE_ADDR: c.req.header("x-forwarded-for")?.split(",")[0].trim() || "127.0.0.1",
10
+ REQUEST_METHOD: c.req.method,
11
+ HTTP_REFERER: c.req.header("referer") || "",
12
+ HTTP_ACCEPT: c.req.header("accept") || "",
13
+ HTTP_COOKIE: c.req.header("cookie") || "",
14
+ SERVER_NAME: c.req.header("host")?.split(":")[0] || "localhost",
15
+ SERVER_PORT: url.port || (url.protocol === "https:" ? "443" : "80"),
16
+ DOCUMENT_ROOT: "",
17
+ REQUEST_FILENAME: c.req.path
18
+ };
19
+ }
20
+ function expandVariables(testString, context) {
21
+ return testString.replace(/%\{([^}]+)\}/g, (match, varName) => {
22
+ const value = context[varName];
23
+ return value !== void 0 ? String(value) : match;
24
+ });
25
+ }
26
+ function testCondition(condition, context) {
27
+ const testValue = expandVariables(condition.testString, context);
28
+ const pattern = new RegExp(condition.pattern, condition.flags.noCase ? "i" : "");
29
+ return pattern.test(testValue);
30
+ }
31
+ function applyRewriteFlags(target, flags, context) {
32
+ if (flags.forbidden) {
33
+ return { type: "forbidden" };
34
+ }
35
+ if (flags.gone) {
36
+ return { type: "gone" };
37
+ }
38
+ if (flags.redirect) {
39
+ let finalTarget = target;
40
+ if (flags.qsAppend) {
41
+ const currentQs = new URL(context.req.url).search.slice(1);
42
+ if (currentQs) {
43
+ const separator = finalTarget.includes("?") ? "&" : "?";
44
+ finalTarget += separator + currentQs;
45
+ }
46
+ }
47
+ if (flags.qsDiscard) {
48
+ const qsIndex = finalTarget.indexOf("?");
49
+ if (qsIndex !== -1) {
50
+ finalTarget = finalTarget.slice(0, qsIndex);
51
+ }
52
+ }
53
+ return {
54
+ type: "redirect",
55
+ url: finalTarget,
56
+ status: flags.redirect
57
+ };
58
+ }
59
+ return {
60
+ type: "rewrite",
61
+ path: target
62
+ };
63
+ }
64
+ export {
65
+ applyRewriteFlags,
66
+ buildVariableContext,
67
+ expandVariables,
68
+ testCondition
69
+ };
package/dist/html.d.ts CHANGED
@@ -2,6 +2,7 @@ import * as hono_utils_html from 'hono/utils/html';
2
2
  import { CgiContext } from './cgi.js';
3
3
  import 'hono/types';
4
4
  import 'hono';
5
+ import './htaccess/types.js';
5
6
 
6
7
  declare const generateCgiInfo: ({ $_SERVER, $_SESSION, $_REQUEST, config, }: Pick<CgiContext, "$_SERVER" | "$_SESSION" | "$_REQUEST" | "config">) => () => hono_utils_html.HtmlEscapedString | Promise<hono_utils_html.HtmlEscapedString>;
7
8
  declare const generateCgiError: ({ error, $_SERVER, }: {
package/dist/index.d.ts CHANGED
@@ -1,4 +1,7 @@
1
1
  export { CgiContext, ConfigObject, MatchboxOptions, ModuleInfo, Page, SessionCookieOptions } from './cgi.js';
2
+ export { HtaccessConfig } from './htaccess/types.js';
3
+ export { parseHtaccess } from './htaccess/parser.js';
4
+ export { corsHeaders, securityHeaders } from './htaccess/headers.js';
2
5
  export { createCgi } from './with-defaults.js';
3
6
  import 'hono/types';
4
7
  import 'hono';
package/dist/index.js CHANGED
@@ -1,4 +1,8 @@
1
+ import { corsHeaders, parseHtaccess, securityHeaders } from "./htaccess/index.js";
1
2
  import { createCgi } from "./with-defaults.js";
2
3
  export {
3
- createCgi
4
+ corsHeaders,
5
+ createCgi,
6
+ parseHtaccess,
7
+ securityHeaders
4
8
  };
@@ -0,0 +1,8 @@
1
+ import { Hono } from 'hono';
2
+
3
+ /**
4
+ * Apply Basic Auth middleware to Hono app for each directory
5
+ */
6
+ declare function applyBasicAuth(app: Hono, authMap: Record<string, string>): void;
7
+
8
+ export { applyBasicAuth };
@@ -0,0 +1,28 @@
1
+ import { basicAuth } from "hono/basic-auth";
2
+ function createBasicAuthMiddleware(htpasswdContent, realm = "Restricted Area") {
3
+ const credentials = htpasswdContent.split("\n").map((line) => line.trim()).filter((line) => line && !line.startsWith("#")).map((line) => {
4
+ const [username, password] = line.split(":");
5
+ return { username, password };
6
+ });
7
+ if (credentials.length === 0) {
8
+ return async (_c, next) => {
9
+ await next();
10
+ };
11
+ }
12
+ return async (c, next) => {
13
+ const handler = basicAuth({
14
+ verifyUser: (u, p) => credentials.some((cred) => cred.username === u && cred.password === p),
15
+ realm
16
+ });
17
+ return handler(c, next);
18
+ };
19
+ }
20
+ function applyBasicAuth(app, authMap) {
21
+ Object.entries(authMap).forEach(([dir, content]) => {
22
+ const authPath = dir === "/" ? "*" : `${dir.replace(/\/$/, "")}/*`;
23
+ app.use(authPath, createBasicAuthMiddleware(content));
24
+ });
25
+ }
26
+ export {
27
+ applyBasicAuth
28
+ };
@@ -0,0 +1,13 @@
1
+ import { Hono } from 'hono';
2
+ import { HtaccessConfig } from '../htaccess/types.js';
3
+
4
+ /**
5
+ * Apply htaccess middleware to Hono app in the correct order
6
+ */
7
+ declare function applyHtaccessMiddleware(app: Hono, htaccessConfig: HtaccessConfig): void;
8
+ /**
9
+ * Apply error document middleware (must be applied last)
10
+ */
11
+ declare function applyErrorDocumentMiddleware(app: Hono, htaccessConfig: HtaccessConfig): void;
12
+
13
+ export { applyErrorDocumentMiddleware, applyHtaccessMiddleware };
@@ -0,0 +1,42 @@
1
+ import { createRewriteMiddleware } from "../htaccess/rewrite.js";
2
+ import { createHeaderMiddleware } from "../htaccess/headers.js";
3
+ import { createErrorDocumentMiddleware } from "../htaccess/error-document.js";
4
+ import { createAccessControlMiddleware } from "../htaccess/access-control.js";
5
+ function applyHtaccessMiddleware(app, htaccessConfig) {
6
+ Object.entries(htaccessConfig).forEach(([dir, config]) => {
7
+ if (config.headers.length === 0) return;
8
+ const basePath = dir === "/" ? "" : dir.replace(/\/$/, "");
9
+ app.use(`${basePath}/*`, createHeaderMiddleware(config.headers));
10
+ });
11
+ Object.entries(htaccessConfig).forEach(([dir, config]) => {
12
+ const allRules = [
13
+ ...config.rewriteRules,
14
+ ...config.redirects.map((r) => ({
15
+ type: "rewrite",
16
+ pattern: `^${r.source}$`,
17
+ target: r.target,
18
+ flags: { redirect: r.code },
19
+ conditions: []
20
+ }))
21
+ ];
22
+ if (allRules.length === 0) return;
23
+ const basePath = dir === "/" ? "" : dir.replace(/\/$/, "");
24
+ app.use(`${basePath}/*`, createRewriteMiddleware(allRules, basePath));
25
+ });
26
+ Object.entries(htaccessConfig).forEach(([dir, config]) => {
27
+ if (!config.accessControl) return;
28
+ const basePath = dir === "/" ? "" : dir.replace(/\/$/, "");
29
+ app.use(`${basePath}/*`, createAccessControlMiddleware(config.accessControl));
30
+ });
31
+ }
32
+ function applyErrorDocumentMiddleware(app, htaccessConfig) {
33
+ Object.entries(htaccessConfig).forEach(([dir, config]) => {
34
+ if (config.errorDocuments.length === 0) return;
35
+ const basePath = dir === "/" ? "" : dir.replace(/\/$/, "");
36
+ app.use(`${basePath}/*`, createErrorDocumentMiddleware(config.errorDocuments, basePath));
37
+ });
38
+ }
39
+ export {
40
+ applyErrorDocumentMiddleware,
41
+ applyHtaccessMiddleware
42
+ };
@@ -0,0 +1,10 @@
1
+ export { applyBasicAuth } from './auth.js';
2
+ export { applyErrorDocumentMiddleware, applyHtaccessMiddleware } from './htaccess.js';
3
+ export { getSessionFromCookie, saveSessionToCookie } from './session.js';
4
+ export { applyProtectedFilesMiddleware } from './protected-files.js';
5
+ export { applyTrailingSlashMiddleware } from './trailing-slash.js';
6
+ import 'hono';
7
+ import '../htaccess/types.js';
8
+ import '../cgi.js';
9
+ import 'hono/types';
10
+ import 'hono/utils/html';
@@ -0,0 +1,14 @@
1
+ import { applyBasicAuth } from "./auth.js";
2
+ import { applyHtaccessMiddleware, applyErrorDocumentMiddleware } from "./htaccess.js";
3
+ import { getSessionFromCookie, saveSessionToCookie } from "./session.js";
4
+ import { applyProtectedFilesMiddleware } from "./protected-files.js";
5
+ import { applyTrailingSlashMiddleware } from "./trailing-slash.js";
6
+ export {
7
+ applyBasicAuth,
8
+ applyErrorDocumentMiddleware,
9
+ applyHtaccessMiddleware,
10
+ applyProtectedFilesMiddleware,
11
+ applyTrailingSlashMiddleware,
12
+ getSessionFromCookie,
13
+ saveSessionToCookie
14
+ };
@@ -0,0 +1,8 @@
1
+ import { Hono } from 'hono';
2
+
3
+ /**
4
+ * Apply protected files middleware to prevent access to sensitive configuration files
5
+ */
6
+ declare function applyProtectedFilesMiddleware(app: Hono): void;
7
+
8
+ export { applyProtectedFilesMiddleware };
@@ -0,0 +1,14 @@
1
+ const PROTECTED_FILES = [".htaccess", ".htpasswd", ".htdigest", ".htgroup"];
2
+ function applyProtectedFilesMiddleware(app) {
3
+ app.use("*", async (c, next) => {
4
+ const path = c.req.path;
5
+ const lastSegment = path.slice(path.lastIndexOf("/") + 1);
6
+ if (PROTECTED_FILES.some((file) => lastSegment === file)) {
7
+ return c.text("Forbidden", 403);
8
+ }
9
+ await next();
10
+ });
11
+ }
12
+ export {
13
+ applyProtectedFilesMiddleware
14
+ };
@@ -0,0 +1,16 @@
1
+ import { Context } from 'hono';
2
+ import { SessionCookieOptions } from '../cgi.js';
3
+ import 'hono/types';
4
+ import 'hono/utils/html';
5
+ import '../htaccess/types.js';
6
+
7
+ /**
8
+ * Get session data from cookie
9
+ */
10
+ declare function getSessionFromCookie(c: Context, sessionCookieName?: string): Record<string, unknown>;
11
+ /**
12
+ * Save session data to cookie
13
+ */
14
+ declare function saveSessionToCookie(c: Context, session: Record<string, unknown>, options?: SessionCookieOptions): void;
15
+
16
+ export { getSessionFromCookie, saveSessionToCookie };
@@ -0,0 +1,37 @@
1
+ import { getCookie, setCookie } from "hono/cookie";
2
+ const DEFAULT_SESSION_COOKIE_NAME = "_SESSION_ID";
3
+ function getSessionFromCookie(c, sessionCookieName) {
4
+ const cookieName = sessionCookieName || DEFAULT_SESSION_COOKIE_NAME;
5
+ const sessionCookie = getCookie(c, cookieName);
6
+ if (sessionCookie) {
7
+ try {
8
+ return JSON.parse(decodeURIComponent(sessionCookie));
9
+ } catch {
10
+ return {};
11
+ }
12
+ }
13
+ return {};
14
+ }
15
+ function saveSessionToCookie(c, session, options) {
16
+ const cookieName = options?.name || DEFAULT_SESSION_COOKIE_NAME;
17
+ const sessionValue = encodeURIComponent(JSON.stringify(session));
18
+ const sessionOptions = {
19
+ path: options?.path || "/",
20
+ httpOnly: true,
21
+ sameSite: options?.sameSite || "Lax"
22
+ };
23
+ if (options?.secure !== void 0) {
24
+ sessionOptions.secure = options.secure;
25
+ }
26
+ if (options?.domain) {
27
+ sessionOptions.domain = options.domain;
28
+ }
29
+ if (options?.maxAge !== void 0) {
30
+ sessionOptions.maxAge = options.maxAge;
31
+ }
32
+ setCookie(c, cookieName, sessionValue, sessionOptions);
33
+ }
34
+ export {
35
+ getSessionFromCookie,
36
+ saveSessionToCookie
37
+ };
@@ -0,0 +1,8 @@
1
+ import { Hono } from 'hono';
2
+
3
+ /**
4
+ * Apply trailing slash middleware to enforce trailing slash on URLs
5
+ */
6
+ declare function applyTrailingSlashMiddleware(app: Hono): void;
7
+
8
+ export { applyTrailingSlashMiddleware };
@@ -0,0 +1,12 @@
1
+ function applyTrailingSlashMiddleware(app) {
2
+ app.use("*", async (c, next) => {
3
+ const path = c.req.path;
4
+ if (!path.endsWith("/") && !path.includes(".")) {
5
+ return c.redirect(`${path}/`, 301);
6
+ }
7
+ await next();
8
+ });
9
+ }
10
+ export {
11
+ applyTrailingSlashMiddleware
12
+ };
@@ -1,7 +1,8 @@
1
- import { MatchboxOptions } from './cgi.js';
2
1
  import * as hono from 'hono';
3
2
  import * as hono_types from 'hono/types';
3
+ import { MatchboxOptions } from './cgi.js';
4
4
  import 'hono/utils/html';
5
+ import './htaccess/types.js';
5
6
 
6
7
  declare const createCgi: (options?: MatchboxOptions) => hono.Hono<hono_types.BlankEnv, hono_types.BlankSchema, "/">;
7
8
 
@@ -1,4 +1,5 @@
1
1
  import { createCgiWithPages } from "./cgi.js";
2
+ import { parseHtaccess } from "./htaccess/parser.js";
2
3
  const loadPagesFromPublic = () => {
3
4
  const modules = import.meta.glob("/public/**/*.cgi.{tsx,jsx}", {
4
5
  eager: true
@@ -38,40 +39,28 @@ const loadPagesFromPublic = () => {
38
39
  },
39
40
  {}
40
41
  );
41
- const rewriteMap = Object.keys(htaccessFiles).reduce((acc, key) => {
42
+ const htaccessConfig = Object.keys(htaccessFiles).reduce((acc, key) => {
42
43
  const dir = key.replace(basePathRegex, "").replace(/\.htaccess$/, "") || "/";
43
- const lines = htaccessFiles[key].split("\n");
44
- const rules = lines.map((line) => {
45
- const l = line.trim();
46
- if (!l || l.startsWith("#")) return null;
47
- const parts = l.split(/\s+/);
48
- if (parts[0] === "RewriteRule") {
49
- return {
50
- type: "rewrite",
51
- pattern: parts[1],
52
- target: parts[2],
53
- flags: parts[3] || ""
54
- };
55
- }
56
- if (parts[0] === "Redirect") {
57
- return {
58
- type: "redirect",
59
- code: parts[1],
60
- source: parts[2],
61
- target: parts[3]
62
- };
63
- }
64
- return null;
65
- }).filter(Boolean);
66
- acc[dir] = rules;
44
+ const content = htaccessFiles[key];
45
+ try {
46
+ acc[dir] = parseHtaccess(content);
47
+ } catch (error) {
48
+ console.error(`Error parsing .htaccess in ${dir}:`, error.message);
49
+ acc[dir] = {
50
+ rewriteRules: [],
51
+ redirects: [],
52
+ errorDocuments: [],
53
+ headers: []
54
+ };
55
+ }
67
56
  return acc;
68
57
  }, {});
69
- return { pages, authMap, rewriteMap };
58
+ return { pages, authMap, htaccessConfig };
70
59
  };
71
60
  const createCgi = (options) => {
72
61
  const resolvedConfig = typeof __MATCHBOX_CONFIG__ === "undefined" ? {} : __MATCHBOX_CONFIG__;
73
- const { pages, authMap, rewriteMap } = loadPagesFromPublic();
74
- return createCgiWithPages(pages, resolvedConfig, authMap, rewriteMap, options);
62
+ const { pages, authMap, htaccessConfig } = loadPagesFromPublic();
63
+ return createCgiWithPages(pages, resolvedConfig, authMap, htaccessConfig, options);
75
64
  };
76
65
  export {
77
66
  createCgi
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tknf/matchbox",
3
- "version": "0.2.6",
3
+ "version": "0.3.1",
4
4
  "description": "A Simple Web Server Framework",
5
5
  "keywords": [
6
6
  "cgi",