counterfact 2.6.0 → 2.7.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.
Files changed (73) hide show
  1. package/README.md +103 -141
  2. package/bin/README.md +24 -4
  3. package/bin/counterfact.js +44 -1
  4. package/dist/app.js +15 -16
  5. package/dist/counterfact-types/cookie-options.js +1 -0
  6. package/dist/counterfact-types/counterfact-response.js +7 -0
  7. package/dist/counterfact-types/example-names.js +1 -0
  8. package/dist/counterfact-types/example.js +1 -0
  9. package/dist/counterfact-types/generic-response-builder.js +1 -0
  10. package/dist/counterfact-types/http-status-code.js +1 -0
  11. package/dist/counterfact-types/if-has-key.js +1 -0
  12. package/dist/counterfact-types/index.js +0 -1
  13. package/dist/counterfact-types/maybe-promise.js +1 -0
  14. package/dist/counterfact-types/media-type.js +1 -0
  15. package/dist/counterfact-types/omit-all.js +1 -0
  16. package/dist/counterfact-types/omit-value-when-never.js +1 -0
  17. package/dist/counterfact-types/open-api-content.js +1 -0
  18. package/dist/counterfact-types/open-api-operation.js +1 -0
  19. package/dist/counterfact-types/open-api-parameters.js +1 -0
  20. package/dist/counterfact-types/open-api-response.js +1 -0
  21. package/dist/counterfact-types/random-function.js +1 -0
  22. package/dist/counterfact-types/response-builder-factory.js +1 -0
  23. package/dist/counterfact-types/response-builder.js +1 -0
  24. package/dist/counterfact-types/wide-operation-argument.js +1 -0
  25. package/dist/counterfact-types/wide-response-builder.js +1 -0
  26. package/dist/repl/repl.js +96 -3
  27. package/dist/server/context-registry.js +17 -1
  28. package/dist/server/counterfact-types/cookie-options.ts +14 -0
  29. package/dist/server/counterfact-types/counterfact-response.ts +15 -0
  30. package/dist/server/counterfact-types/example-names.ts +13 -0
  31. package/dist/server/counterfact-types/example.ts +10 -0
  32. package/dist/server/counterfact-types/generic-response-builder.ts +164 -0
  33. package/dist/server/counterfact-types/http-status-code.ts +62 -0
  34. package/dist/server/counterfact-types/if-has-key.ts +19 -0
  35. package/dist/server/counterfact-types/index.ts +20 -338
  36. package/dist/server/counterfact-types/maybe-promise.ts +6 -0
  37. package/dist/server/counterfact-types/media-type.ts +6 -0
  38. package/dist/server/counterfact-types/omit-all.ts +11 -0
  39. package/dist/server/counterfact-types/omit-value-when-never.ts +11 -0
  40. package/dist/server/counterfact-types/open-api-content.ts +8 -0
  41. package/dist/server/counterfact-types/open-api-operation.ts +36 -0
  42. package/dist/server/counterfact-types/open-api-parameters.ts +16 -0
  43. package/dist/server/counterfact-types/open-api-response.ts +22 -0
  44. package/dist/server/counterfact-types/random-function.ts +9 -0
  45. package/dist/server/counterfact-types/response-builder-factory.ts +16 -0
  46. package/dist/server/counterfact-types/response-builder.ts +31 -0
  47. package/dist/server/counterfact-types/wide-operation-argument.ts +17 -0
  48. package/dist/server/counterfact-types/wide-response-builder.ts +26 -0
  49. package/dist/server/create-koa-app.js +1 -20
  50. package/dist/server/dispatcher.js +18 -5
  51. package/dist/server/json-to-xml.js +1 -1
  52. package/dist/server/koa-middleware.js +7 -1
  53. package/dist/server/load-openapi-document.js +13 -0
  54. package/dist/server/module-loader.js +76 -4
  55. package/dist/server/openapi-watcher.js +35 -0
  56. package/dist/server/request-validator.js +3 -7
  57. package/dist/server/response-builder.js +3 -0
  58. package/dist/server/response-validator.js +58 -0
  59. package/dist/server/scenario-registry.js +29 -0
  60. package/dist/server/tools.js +2 -2
  61. package/dist/typescript-generator/coder.js +4 -2
  62. package/dist/typescript-generator/generate.js +155 -0
  63. package/dist/typescript-generator/operation-coder.js +1 -1
  64. package/dist/typescript-generator/operation-type-coder.js +1 -49
  65. package/dist/typescript-generator/read-only-comments.js +1 -1
  66. package/dist/typescript-generator/requirement.js +8 -1
  67. package/dist/typescript-generator/reserved-words.js +50 -0
  68. package/dist/util/load-config-file.js +44 -0
  69. package/package.json +7 -8
  70. package/dist/client/README.md +0 -14
  71. package/dist/client/index.html.hbs +0 -244
  72. package/dist/client/rapi-doc.html.hbs +0 -36
  73. package/dist/server/page-middleware.js +0 -23
@@ -0,0 +1,50 @@
1
+ // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Lexical_grammar#reserved_words
2
+ export const RESERVED_WORDS = new Set([
3
+ "break",
4
+ "case",
5
+ "catch",
6
+ "class",
7
+ "const",
8
+ "continue",
9
+ "debugger",
10
+ "default",
11
+ "delete",
12
+ "do",
13
+ "else",
14
+ "export",
15
+ "extends",
16
+ "false",
17
+ "finally",
18
+ "for",
19
+ "function",
20
+ "if",
21
+ "import",
22
+ "in",
23
+ "instanceof",
24
+ "new",
25
+ "null",
26
+ "return",
27
+ "static",
28
+ "super",
29
+ "switch",
30
+ "this",
31
+ "throw",
32
+ "true",
33
+ "try",
34
+ "typeof",
35
+ "var",
36
+ "void",
37
+ "while",
38
+ "with",
39
+ "yield",
40
+ "await",
41
+ "enum",
42
+ "implements",
43
+ "interface",
44
+ "let",
45
+ "package",
46
+ "private",
47
+ "protected",
48
+ "public",
49
+ "type",
50
+ ]);
@@ -0,0 +1,44 @@
1
+ import { readFile } from "node:fs/promises";
2
+ import { load as loadYaml } from "js-yaml";
3
+ function kebabToCamel(str) {
4
+ return str.replace(/-([a-z])/g, (_, letter) => letter.toUpperCase());
5
+ }
6
+ function normalizeKeys(obj) {
7
+ return Object.fromEntries(Object.entries(obj).map(([key, value]) => [kebabToCamel(key), value]));
8
+ }
9
+ /**
10
+ * Loads and parses a counterfact YAML config file.
11
+ *
12
+ * @param configPath - Absolute or relative path to the config file.
13
+ * @param required - When true, throws if the file does not exist.
14
+ * When false (default), returns an empty object for missing files.
15
+ * @returns A plain object of config keys (camelCase) to values.
16
+ */
17
+ export async function loadConfigFile(configPath, required = false) {
18
+ let content;
19
+ try {
20
+ content = await readFile(configPath, "utf8");
21
+ }
22
+ catch (error) {
23
+ if (typeof error === "object" &&
24
+ error !== null &&
25
+ "code" in error &&
26
+ error.code === "ENOENT") {
27
+ if (required) {
28
+ throw new Error(`Config file not found: ${configPath}`, {
29
+ cause: error,
30
+ });
31
+ }
32
+ return {};
33
+ }
34
+ throw error;
35
+ }
36
+ const parsed = loadYaml(content);
37
+ if (parsed === null || parsed === undefined) {
38
+ return {};
39
+ }
40
+ if (typeof parsed !== "object" || Array.isArray(parsed)) {
41
+ throw new Error(`Config file must be a YAML object (mapping): ${configPath}`);
42
+ }
43
+ return normalizeKeys(parsed);
44
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "counterfact",
3
- "version": "2.6.0",
3
+ "version": "2.7.0",
4
4
  "description": "Generate a TypeScript-based mock server from an OpenAPI spec in seconds — with stateful routes, hot reload, and REPL support.",
5
5
  "type": "module",
6
6
  "main": "./dist/app.js",
@@ -21,7 +21,7 @@
21
21
  "license": "MIT",
22
22
  "repository": {
23
23
  "type": "git",
24
- "url": "https://github.com/pmcelhaney/counterfact.git"
24
+ "url": "git+https://github.com/pmcelhaney/counterfact.git"
25
25
  },
26
26
  "bugs": "https://github.com/pmcelhaney/counterfact/issues",
27
27
  "homepage": "https://counterfact.dev",
@@ -56,7 +56,7 @@
56
56
  "node": ">=22"
57
57
  },
58
58
  "bin": {
59
- "counterfact": "./bin/counterfact.js"
59
+ "counterfact": "bin/counterfact.js"
60
60
  },
61
61
  "files": [
62
62
  "bin",
@@ -67,7 +67,7 @@
67
67
  "test": "yarn node --experimental-vm-modules ./node_modules/jest-cli/bin/jest --testPathIgnorePatterns=black-box",
68
68
  "test:black-box": "rimraf dist && yarn build && python3 -m pytest test-black-box/ -v",
69
69
  "test:tsd": "tsd --typings ./dist/server/counterfact-types/index.ts --files ./test/**/*.test-d.ts",
70
- "build": "rm -rf dist && tsc && copyfiles -f \"src/client/**\" dist/client && copyfiles -f \"src/counterfact-types/*.ts\" dist/server/counterfact-types && copyfiles -f \"src/server/*.cjs\" dist/server",
70
+ "build": "rm -rf dist && tsc && copyfiles -f \"src/counterfact-types/*.ts\" dist/server/counterfact-types && copyfiles -f \"src/server/*.cjs\" dist/server",
71
71
  "prepack": "yarn build",
72
72
  "release": "npx changeset publish",
73
73
  "prepare": "husky install",
@@ -84,7 +84,7 @@
84
84
  "@changesets/cli": "2.30.0",
85
85
  "@eslint/js": "10.0.1",
86
86
  "@jest/globals": "^30.3.0",
87
- "@swc/core": "1.15.21",
87
+ "@swc/core": "1.15.24",
88
88
  "@swc/jest": "0.2.39",
89
89
  "@testing-library/dom": "10.4.1",
90
90
  "@types/debug": "^4.1.12",
@@ -98,7 +98,7 @@
98
98
  "@typescript-eslint/eslint-plugin": "^8.58.0",
99
99
  "@typescript-eslint/parser": "^8.58.0",
100
100
  "copyfiles": "2.4.1",
101
- "eslint": "10.1.0",
101
+ "eslint": "10.2.0",
102
102
  "eslint-formatter-github-annotations": "0.1.0",
103
103
  "eslint-import-resolver-typescript": "4.4.4",
104
104
  "eslint-plugin-etc": "2.0.3",
@@ -126,12 +126,11 @@
126
126
  "@apidevtools/json-schema-ref-parser": "13.0.5",
127
127
  "@hapi/accept": "6.0.3",
128
128
  "@types/json-schema": "7.0.15",
129
- "ajv": "6.14.0",
129
+ "ajv": "8.18.0",
130
130
  "chokidar": "5.0.0",
131
131
  "commander": "14.0.3",
132
132
  "debug": "4.4.3",
133
133
  "fs-extra": "11.3.4",
134
- "handlebars": "4.7.9",
135
134
  "http-terminator": "3.2.0",
136
135
  "js-yaml": "4.1.1",
137
136
  "json-schema-faker": "0.6.0",
@@ -1,14 +0,0 @@
1
- # `src/client/` — Built-in UI Templates
2
-
3
- This directory contains [Handlebars](https://handlebarsjs.com/) (`.hbs`) templates that are rendered by `page-middleware.ts` to produce the browser-facing pages bundled with Counterfact.
4
-
5
- ## Files
6
-
7
- | File | Description |
8
- |---|---|
9
- | `index.html.hbs` | Template for the Counterfact dashboard (`/counterfact/`); lists registered routes and shows server status |
10
- | `rapi-doc.html.hbs` | Template for the interactive API documentation page (`/counterfact/swagger/`); embeds the [RapiDoc](https://rapidocweb.com/) viewer and adds VSCode "open file" links |
11
-
12
- ## How It Works
13
-
14
- When a request arrives for `/counterfact/` or `/counterfact/swagger/`, `page-middleware.ts` compiles the appropriate template with runtime data (routes, port, base path, etc.) and sends the resulting HTML to the browser. No build step is required; templates are rendered on the fly.
@@ -1,244 +0,0 @@
1
- <!--
2
- This code is hideous. I'm trying to get a feel for the layout and it's easier
3
- for me to push pixels in devtools than use a real tool like Figma. I'll clean
4
- it up later. In the mean time, I welcome pull requests. :)
5
- --->
6
-
7
- <!DOCTYPE html>
8
- <html lang="en">
9
- <head>
10
- <title>Counterfact</title>
11
- <meta charset="utf-8">
12
- <meta name="description" content="Counterfact Dashboard" />
13
- <meta name="viewport" content="width=device-width, initial-scale=1" />
14
-
15
- <style type="text/css">
16
- body {
17
- font-family: Helvetica, Arial, sans-serif;
18
- max-width: 800px;
19
- margin: 0 auto;
20
- background-color: white;
21
- color: black;
22
- }
23
-
24
- a {
25
- color: #fff;
26
- }
27
-
28
- h1 {
29
- text-align: center;
30
- }
31
-
32
- table {
33
- width: 100%;
34
- border-collapse: collapse;
35
- }
36
-
37
- .tilt {
38
- width: 1.5em;
39
- position: relative;
40
- padding-top: 75px;
41
- }
42
-
43
- .tilt > * {
44
- display: block;
45
- position: absolute;
46
- transform: rotate(-90deg);
47
- transform-origin: left;
48
- text-align: center;
49
- bottom: 0;
50
- left: 20px;
51
-
52
- }
53
-
54
- thead {
55
- position: sticky;
56
- top: 0;
57
- }
58
-
59
- th.path > * {
60
- visibility: hidden;
61
- }
62
-
63
- td.path {
64
- font-family: monospace;
65
- font-size: 1.4em;
66
- }
67
-
68
- .path {
69
- text-align: left;
70
- padding-left: 20px;
71
- }
72
-
73
- .method-identifier {
74
- text-align: center;
75
- font-size: 1.5em;
76
- font-weight: bold;
77
- color: #333;
78
- padding: 0 0.5em;
79
- }
80
-
81
- tbody tr:hover {
82
- background-color: #ccc;
83
- }
84
-
85
- .path a {
86
- color: black;
87
- text-decoration: none;
88
- }
89
-
90
-
91
- .buttons {
92
- position: relative;
93
- display: flex;
94
- justify-content: center;
95
- top: -40px;
96
- left: 72px;
97
-
98
- }
99
- .buttons > a {
100
- display: inline-block;
101
- margin: 0 0.5em;
102
- padding: 0.5em 1em;
103
- background-color: #0071b5;
104
- border-radius: 5px;
105
- color: white;
106
- text-decoration: none;
107
-
108
- }
109
-
110
- #paths-container {
111
- margin-top: -35px;
112
- }
113
-
114
- </style>
115
- <body>
116
-
117
-
118
-
119
- <h1>
120
-
121
- <svg
122
- width="616.38678"
123
- height="104.03941"
124
- viewBox="0 0 163.08567 27.527093"
125
- version="1.1"
126
- id="svg1"
127
- inkscape:version="1.3.2 (091e20e, 2023-11-25)"
128
- sodipodi:docname="counterfact.svg"
129
- xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
130
- xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
131
- xmlns="http://www.w3.org/2000/svg"
132
- xmlns:svg="http://www.w3.org/2000/svg">
133
- <sodipodi:namedview
134
- id="namedview1"
135
- pagecolor="#ffffff"
136
- bordercolor="#000000"
137
- borderopacity="0.25"
138
- inkscape:showpageshadow="2"
139
- inkscape:pageopacity="0.0"
140
- inkscape:pagecheckerboard="0"
141
- inkscape:deskcolor="#d1d1d1"
142
- inkscape:document-units="mm"
143
- inkscape:zoom="1.4873456"
144
- inkscape:cx="308.93964"
145
- inkscape:cy="100.17847"
146
- inkscape:window-width="1728"
147
- inkscape:window-height="1051"
148
- inkscape:window-x="0"
149
- inkscape:window-y="38"
150
- inkscape:window-maximized="1"
151
- inkscape:current-layer="svg1" />
152
- <defs
153
- id="defs1" />
154
- <g
155
- id="g6"
156
- transform="matrix(1.0103886,0,0,1.0103886,-29.555241,-50.917297)">
157
- <g
158
- id="g1"
159
- transform="matrix(0.27630185,0,0,0.27630185,16.871974,36.385623)">
160
- <polygon
161
- points="155.19615,103 130.19615,146.30127 105.19615,103 "
162
- fill="#f58e00"
163
- id="polygon1" />
164
- <polygon
165
- points="125,149.30127 75,149.30127 100,106 "
166
- fill="#0071b5"
167
- id="polygon2" />
168
- <polygon
169
- points="69.803848,146.30127 44.803848,103 94.803848,103 "
170
- fill="#0071b5"
171
- id="polygon3" />
172
- <polygon
173
- points="44.803848,97 69.803848,53.69873 94.803848,97 "
174
- fill="#0071b5"
175
- id="polygon4" />
176
- <polygon
177
- points="75,50.69873 125,50.69873 100,94 "
178
- fill="#0071b5"
179
- id="polygon5" />
180
- <polygon
181
- points="130.19615,53.69873 155.19615,97 105.19615,97 "
182
- fill="#0071b5"
183
- id="polygon6" />
184
- </g>
185
- </g>
186
- <g
187
- inkscape:label="Layer 1"
188
- inkscape:groupmode="layer"
189
- id="layer1"
190
- transform="translate(8.8561952,-0.31740497)">
191
- <path
192
- style="font-weight:bold;font-size:16.9333px;font-family:Futura;-inkscape-font-specification:'Futura, Bold';fill:#0071b5;fill-opacity:1;stroke-width:0.322562"
193
- d="M 39.469822,10.780228 Q 38.066034,9.0667813 36.00164,9.0667813 q -0.908333,0 -1.692803,0.330303 -0.763826,0.330302 -1.321212,0.9083327 -0.557387,0.557386 -0.887689,1.341856 -0.309659,0.78447 -0.309659,1.692803 0,0.928977 0.309659,1.713448 0.330302,0.78447 0.887689,1.3625 0.578031,0.57803 1.341857,0.908334 0.763825,0.330303 1.651515,0.330303 1.94053,0 3.488825,-1.651516 v 4.789394 l -0.412879,0.144508 q -0.928976,0.330303 -1.734091,0.474811 -0.805114,0.165151 -1.589583,0.165151 -1.610227,0 -3.096591,-0.598674 -1.46572,-0.619319 -2.601137,-1.713447 -1.114773,-1.114773 -1.796023,-2.621781 -0.68125,-1.527651 -0.68125,-3.323675 0,-1.796023 0.660606,-3.282386 0.681251,-1.5070074 1.796023,-2.5804934 1.135417,-1.094128 2.621781,-1.692803 1.486364,-0.619317 3.117235,-0.619317 0.928978,0 1.816667,0.206439 0.908333,0.185795 1.899242,0.598673 z m 5.739013,5.016479 q 0,0.536741 0.185795,0.990908 0.20644,0.433522 0.5161,0.763826 0.330302,0.330302 0.763825,0.516099 0.454168,0.185794 0.949622,0.185794 0.495453,0 0.928977,-0.185794 0.454166,-0.185797 0.763825,-0.516099 0.330303,-0.330304 0.516099,-0.763826 0.20644,-0.454167 0.20644,-0.970265 0,-0.495454 -0.20644,-0.928978 -0.185796,-0.454167 -0.516099,-0.784469 -0.309659,-0.330304 -0.763825,-0.5161 -0.433524,-0.185794 -0.928977,-0.185794 -0.495454,0 -0.949622,0.185794 -0.433523,0.185796 -0.763825,0.5161 -0.30966,0.330302 -0.5161,0.763825 -0.185795,0.433522 -0.185795,0.928979 z m -3.942993,-0.04129 q 0,-1.176705 0.474811,-2.188258 0.474811,-1.032196 1.321211,-1.775379 0.846403,-0.763826 2.002464,-1.197348 1.176704,-0.433522 2.559849,-0.433522 1.3625,0 2.51856,0.433522 1.176704,0.412878 2.023106,1.176704 0.867045,0.743182 1.341856,1.796023 0.474811,1.032198 0.474811,2.291477 0,1.259281 -0.495454,2.312123 -0.474811,1.032196 -1.321213,1.796022 -0.846402,0.743182 -2.04375,1.156061 -1.176705,0.412879 -2.559848,0.412879 -1.362501,0 -2.518563,-0.412879 -1.15606,-0.412879 -2.002462,-1.176704 -0.825756,-0.763826 -1.300567,-1.816668 -0.474811,-1.073484 -0.474811,-2.374053 z m 18.600208,-5.20227 v 5.9661 q 0,1.961175 1.899242,1.961175 1.899242,0 1.899242,-1.961175 v -5.9661 h 3.736555 v 6.688638 q 0,2.14697 -1.424433,3.220454 -1.403788,1.073485 -4.211364,1.073485 -2.807577,0 -4.232008,-1.073485 -1.403788,-1.073488 -1.403788,-3.220458 v -6.688638 z m 10.074252,0 h 3.736558 v 1.341857 q 0.763823,-0.928978 1.548299,-1.238636 0.784462,-0.330304 1.837303,-0.330304 1.114777,0 1.89924,0.371591 0.805115,0.350947 1.362508,1.011553 0.454175,0.536743 0.619315,1.197349 0.165157,0.660606 0.165157,1.507007 v 6.729926 h -3.736558 v -5.34678 q 0,-0.784472 -0.123862,-1.259282 -0.103262,-0.495455 -0.392233,-0.78447 -0.247728,-0.247727 -0.557388,-0.350946 -0.30966,-0.103224 -0.660611,-0.103224 -0.949619,0 -1.465715,0.578031 -0.495455,0.557385 -0.495455,1.610227 v 5.656437 h -3.736558 z m 17.877642,3.117236 v 7.473107 h -3.736542 v -7.473107 h -1.238638 v -3.117236 h 1.238638 V 7.3739806 h 3.736542 v 3.1791664 h 2.126327 v 3.117236 z m 11.478028,0.639962 q -0.185801,-0.78447 -0.763829,-1.259281 -0.578036,-0.474811 -1.403791,-0.474811 -0.867046,0 -1.42443,0.454167 -0.536741,0.454167 -0.681237,1.279925 z m -4.376513,2.167613 q 0,2.415342 2.270832,2.415342 1.217991,0 1.837315,-0.99091 h 3.612684 q -1.09413,3.633334 -5.470643,3.633334 -1.341865,0 -2.456623,-0.392234 -1.114777,-0.41288 -1.919893,-1.15606 -0.784472,-0.743183 -1.218004,-1.77538 -0.433505,-1.032197 -0.433505,-2.312122 0,-1.321211 0.41287,-2.374053 0.41288,-1.073485 1.176708,-1.816667 0.76382,-0.743182 1.837301,-1.135417 1.094143,-0.412878 2.456641,-0.412878 1.341844,0 2.415334,0.412878 1.073484,0.392235 1.816664,1.15606 0.74319,0.763828 1.13541,1.878601 0.39225,1.094128 0.39225,2.477272 v 0.392234 z m 9.991641,-5.924811 h 3.73656 v 1.734092 q 0.59868,-0.949622 1.46571,-1.445077 0.86705,-0.516098 2.02311,-0.516098 0.1445,0 0.30966,0 0.1858,0 0.41289,0.04129 v 3.571402 q -0.74318,-0.371592 -1.61023,-0.371592 -1.30057,0 -1.96117,0.78447 -0.63997,0.763826 -0.63997,2.25019 v 4.541667 h -3.73656 z m 14.18238,3.117236 v 7.473107 h -3.73656 v -7.473107 h -1.34185 v -3.117236 h 1.34185 V 8.9635643 q 0,-1.3212127 0.24772,-2.1056817 0.20646,-0.660606 0.66062,-1.217993 0.45416,-0.578029 1.05284,-0.990909 0.61932,-0.412878 1.32122,-0.639963 0.70189,-0.227083 1.38313,-0.227083 0.47481,0 0.86705,0.103224 0.41287,0.103224 0.82576,0.289017 v 3.261742 q -0.37159,-0.185797 -0.70189,-0.268371 -0.30966,-0.103224 -0.66062,-0.103224 -0.22707,0 -0.4748,0.08258 -0.22708,0.06193 -0.43352,0.289014 -0.20645,0.227083 -0.28902,0.660608 -0.0619,0.412878 -0.0619,1.1354157 v 1.3212117 h 2.62178 v 3.117236 z m 7.72084,2.14697 q 0,0.516098 0.18579,0.970265 0.1858,0.433522 0.49545,0.763826 0.33031,0.330302 0.76384,0.516099 0.45416,0.185794 0.97025,0.185794 0.49546,0 0.92898,-0.185794 0.45417,-0.185797 0.76384,-0.516099 0.3303,-0.330304 0.51609,-0.763826 0.20643,-0.433523 0.20643,-0.928978 0,-0.495454 -0.20643,-0.928977 -0.18579,-0.454167 -0.51609,-0.784469 -0.30967,-0.330304 -0.76384,-0.516099 -0.43352,-0.185796 -0.92898,-0.185796 -0.51609,0 -0.97025,0.185796 -0.43353,0.185795 -0.76384,0.516099 -0.30965,0.330302 -0.49545,0.763825 -0.18579,0.41288 -0.18579,0.908334 z m 4.70682,-5.264206 h 3.7572 V 21.14349 h -3.7572 v -1.176702 q -1.19735,1.507008 -3.2411,1.507008 -1.15606,0 -2.12634,-0.412879 -0.97025,-0.433522 -1.6928,-1.197347 -0.72253,-0.763827 -1.13541,-1.796023 -0.39223,-1.032198 -0.39223,-2.250191 0,-1.135417 0.39223,-2.146969 0.39223,-1.032198 1.09414,-1.796023 0.70188,-0.763828 1.67215,-1.19735 0.97026,-0.454166 2.14696,-0.454166 1.98182,0 3.2824,1.383145 z m 14.28561,3.426895 q -0.97028,-0.660607 -1.96119,-0.660607 -0.53672,0 -1.01154,0.185796 -0.45417,0.185795 -0.80512,0.536742 -0.35094,0.330304 -0.55738,0.805115 -0.1858,0.454166 -0.1858,1.032197 0,0.557386 0.1858,1.032197 0.20644,0.454166 0.53674,0.805113 0.35095,0.330303 0.82576,0.516099 0.47482,0.185795 1.01154,0.185795 1.05286,0 1.96119,-0.722538 v 3.179167 q -1.38315,0.598674 -2.62179,0.598674 -1.15606,0 -2.20889,-0.392235 -1.0322,-0.392234 -1.83732,-1.114772 -0.78446,-0.743182 -1.25928,-1.754735 -0.4748,-1.032197 -0.4748,-2.291479 0,-1.259279 0.45416,-2.291476 0.45416,-1.052842 1.23863,-1.796024 0.78448,-0.763825 1.85796,-1.176703 1.09413,-0.433523 2.33277,-0.433523 1.36249,0 2.51856,0.57803 z m 6.2964,-0.309659 v 7.473107 h -3.73655 v -7.473107 h -1.23864 v -3.117236 h 1.23864 V 7.3739806 h 3.73655 v 3.1791664 h 2.12633 v 3.117236 z"
194
- id="text1"
195
- fill="#0071b5"
196
- aria-label="Counterfact" />
197
- </g>
198
- </svg>
199
- </h1>
200
-
201
-
202
-
203
-
204
- <div class="buttons">
205
- <a href="./swagger" class="button" target="_blank">Swagger UI</a>
206
- <a href="{{openApiHref}}" class="button" target="_blank">OpenAPI</a>
207
- <a href="https://counterfact.dev/docs/usage.html" target="_blank">Usage Guide</a>
208
- <a href="https://github.com/pmcelhaney/counterfact" target="_blank">GitHub</a>
209
- </div>
210
-
211
-
212
-
213
- <div id="paths-container">
214
- <table>
215
- <thead>
216
- <tr>
217
- <th class="tilt"><span>GET</span></th>
218
- <th class="tilt"><span>POST</span></th>
219
- <th class="tilt"><span>PUT</span></th>
220
- <th class="tilt"><span>DELETE</span></th>
221
- <th class="tilt"><span>PATCH</span></th>
222
- <th class="path"><span>Path</span></th>
223
- </tr>
224
- </thead>
225
- <tbody>
226
- {{#each routes as |route|}}
227
- <tr>
228
- <td class="method-identifier" title="{{route.methods.GET}}">{{#if route.methods.GET }}⚪️{{/if}}</td>
229
- <td class="method-identifier" title="{{route.methods.POST}}">{{#if route.methods.POST }}⚪️{{/if}}</td>
230
- <td class="method-identifier" title="{{route.methods.PUT}}">{{#if route.methods.PUT }}⚪️{{/if}}</td>
231
- <td class="method-identifier" title="{{route.methods.DELETE}}">{{#if route.methods.DELETE }}⚪️{{/if}}</td>
232
- <td class="method-identifier" title="{{route.methods.PATH}}">{{#if route.methods.PATCH }}⚪️{{/if}}</td>
233
- <td class="path"><a href="vscode://file/{{../basePath}}/routes{{route.path}}.ts">{{route.path}}</a></td>
234
- </tr>
235
- {{/each}}
236
- </tbody>
237
- </table>
238
- </div>
239
-
240
-
241
-
242
-
243
- </body>
244
- </html>
@@ -1,36 +0,0 @@
1
- <!DOCTYPE html>
2
- <html lang="en">
3
- <head>
4
- <title>Counterfact</title>
5
- <meta charset="utf-8">
6
- <meta name="description" content="Rapidoc" />
7
- <meta name="viewport" content="width=device-width, initial-scale=1" />
8
- <script type="module" src="https://unpkg.com/rapidoc/dist/rapidoc-min.js"></script>
9
- </head>
10
- <body>
11
-
12
-
13
-
14
- <rapi-doc spec-url="/counterfact/openapi" show-method-in-nav-bar="as-colored-block" nav-active-item-marker="left-bar" use-path-in-nav-bar="true">
15
-
16
- <div slot="overview" style="background-color: #eee">
17
- <p>Put an explanation of Counterfact here.</p>
18
- <a
19
- href="https://github.com/pmcelhaney/counterfact/blob/main/docs/usage.md#generated-code-"
20
- >How does this work?</a
21
- >
22
- </div>
23
- {{#each routes as |route|}}
24
- <a slot="get-{{escape_route route}}" href="vscode://file/{{../basePath}}/routes/{{.}}.ts">Edit in VSCode</a>
25
- <a slot="put-{{escape_route route}}" href="vscode://file/{{../basePath}}/routes/{{.}}.ts">Edit in VSCode</a>
26
- <a slot="post-{{escape_route route}}" href="vscode://file/{{../basePath}}/routes/{{.}}.ts">Edit in VSCode</a>
27
- <a slot="delete-{{escape_route route}}" href="vscode://file/{{../basePath}}/routes/{{.}}.ts">Edit in VSCode</a>
28
- <a slot="patch-{{escape_route route}}" href="vscode://file/{{../basePath}}/routes/{{.}}.ts">Edit in VSCode</a>
29
-
30
- {{/each}}
31
- </rapi-doc>
32
-
33
-
34
-
35
- </body>
36
- </html>
@@ -1,23 +0,0 @@
1
- import nodePath from "node:path";
2
- import { fileURLToPath } from "node:url";
3
- import createDebug from "debug";
4
- import Handlebars from "handlebars";
5
- import { readFile } from "../util/read-file.js";
6
- const __dirname = nodePath.dirname(fileURLToPath(import.meta.url));
7
- const debug = createDebug("counterfact:server:page-middleware");
8
- Handlebars.registerHelper("escape_route", (route) => route.replaceAll(/[^\w/]/gu, "-"));
9
- export function pageMiddleware(pathname, templateName, locals) {
10
- return async (ctx, next) => {
11
- const pathToHandlebarsTemplate = nodePath
12
- .join(__dirname, `../client/${templateName}.html.hbs`)
13
- .replaceAll("\\", "/");
14
- const render = Handlebars.compile(await readFile(pathToHandlebarsTemplate));
15
- if (ctx.URL.pathname === pathname) {
16
- debug("rendering page: %s", pathname);
17
- debug("locals: %o", locals);
18
- ctx.body = render(locals);
19
- return;
20
- }
21
- await next();
22
- };
23
- }