toiljs 0.0.15 → 0.0.19

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 (273) hide show
  1. package/.babelrc +13 -13
  2. package/.gitattributes +2 -2
  3. package/.github/ISSUE_TEMPLATE/bug_report.md +38 -38
  4. package/.github/ISSUE_TEMPLATE/bug_report.yml +90 -90
  5. package/.github/ISSUE_TEMPLATE/config.yml +8 -8
  6. package/.github/ISSUE_TEMPLATE/feature_request.md +20 -20
  7. package/.github/PULL_REQUEST_TEMPLATE.md +43 -43
  8. package/.github/changelog-config.json +45 -45
  9. package/.github/dependabot.yml +27 -27
  10. package/.github/workflows/ci.yml +191 -191
  11. package/.prettierrc.json +11 -11
  12. package/.vscode/settings.json +9 -9
  13. package/CHANGELOG.md +116 -5
  14. package/LICENSE +187 -187
  15. package/README.md +524 -315
  16. package/as-pect.asconfig.json +34 -34
  17. package/as-pect.config.js +65 -65
  18. package/assets/logo.svg +36 -36
  19. package/build/backend/.tsbuildinfo +1 -1
  20. package/build/backend/index.d.ts +1 -0
  21. package/build/backend/index.js +20 -1
  22. package/build/cli/.tsbuildinfo +1 -1
  23. package/build/cli/index.js +1320 -696
  24. package/build/client/.tsbuildinfo +1 -1
  25. package/build/client/dev/devtools.d.ts +6 -0
  26. package/build/client/dev/devtools.js +479 -0
  27. package/build/client/dev/error-overlay.d.ts +9 -0
  28. package/build/client/dev/error-overlay.js +19 -4
  29. package/build/client/errors.d.ts +1 -0
  30. package/build/client/errors.js +3 -0
  31. package/build/client/index.d.ts +2 -0
  32. package/build/client/index.js +2 -0
  33. package/build/client/navigation/prefetch.d.ts +1 -0
  34. package/build/client/navigation/prefetch.js +35 -0
  35. package/build/client/routing/Router.js +1 -1
  36. package/build/client/routing/hooks.js +6 -2
  37. package/build/client/routing/loader.d.ts +23 -0
  38. package/build/client/routing/loader.js +53 -7
  39. package/build/client/routing/mount.js +4 -3
  40. package/build/client/rpc.d.ts +1 -0
  41. package/build/client/rpc.js +37 -0
  42. package/build/compiler/.tsbuildinfo +1 -1
  43. package/build/compiler/config.d.ts +16 -0
  44. package/build/compiler/config.js +9 -0
  45. package/build/compiler/docs.js +78 -21
  46. package/build/compiler/generate.js +5 -4
  47. package/build/compiler/index.d.ts +3 -2
  48. package/build/compiler/index.js +2 -2
  49. package/build/compiler/plugin.js +228 -0
  50. package/build/compiler/prerender.d.ts +1 -0
  51. package/build/compiler/prerender.js +1 -1
  52. package/build/compiler/seo.d.ts +1 -1
  53. package/build/compiler/seo.js +20 -5
  54. package/build/compiler/ssg.js +39 -2
  55. package/build/compiler/vite.js +25 -0
  56. package/build/io/.tsbuildinfo +1 -1
  57. package/build/io/codec.d.ts +54 -0
  58. package/build/io/codec.js +143 -0
  59. package/build/io/index.d.ts +1 -2
  60. package/build/io/index.js +1 -2
  61. package/build/logger/.tsbuildinfo +1 -1
  62. package/build/shared/.tsbuildinfo +1 -1
  63. package/eslint.config.js +48 -48
  64. package/examples/basic/client/404.tsx +11 -11
  65. package/examples/basic/client/components/.gitkeep +1 -1
  66. package/examples/basic/client/global-error.tsx +13 -13
  67. package/examples/basic/client/layout.tsx +25 -25
  68. package/examples/basic/client/public/images/.gitkeep +1 -1
  69. package/examples/basic/client/public/images/logo.svg +36 -36
  70. package/examples/basic/client/public/robots.txt +2 -2
  71. package/examples/basic/client/routes/docs/[...slug].tsx +12 -12
  72. package/examples/basic/client/routes/features/error/error.tsx +16 -16
  73. package/examples/basic/client/routes/features/index.tsx +1 -1
  74. package/examples/basic/client/routes/features/template/b.tsx +14 -14
  75. package/examples/basic/client/routes/files/[[...slug]].tsx +21 -21
  76. package/examples/basic/client/routes/gallery/layout.tsx +13 -13
  77. package/examples/basic/client/routes/io.tsx +23 -24
  78. package/examples/basic/client/routes/loader-demo/loading.tsx +13 -13
  79. package/examples/basic/client/routes/rest.tsx +74 -0
  80. package/examples/basic/client/routes/rpc.tsx +43 -0
  81. package/examples/basic/client/routes/search.tsx +61 -61
  82. package/examples/basic/client/toil.tsx +5 -5
  83. package/package.json +167 -148
  84. package/presets/eslint.js +88 -88
  85. package/presets/no-uint8array-tostring.js +200 -200
  86. package/presets/prettier-plugin.js +51 -0
  87. package/presets/prettier.json +19 -18
  88. package/presets/tsconfig.json +37 -37
  89. package/server/runtime/README.md +97 -0
  90. package/server/runtime/abort/abort.ts +27 -0
  91. package/server/runtime/env/Server.ts +61 -0
  92. package/server/runtime/envelope.ts +191 -0
  93. package/server/runtime/exports/index.ts +52 -0
  94. package/server/runtime/handlers/ToilHandler.ts +34 -0
  95. package/server/runtime/index.ts +26 -0
  96. package/server/runtime/lang/Potential.ts +5 -0
  97. package/server/runtime/memory.ts +81 -0
  98. package/server/runtime/request.ts +55 -0
  99. package/server/runtime/response.ts +86 -0
  100. package/server/runtime/rest/Rest.ts +39 -0
  101. package/server/runtime/rest/RestHandler.ts +20 -0
  102. package/server/runtime/rest/RouteContext.ts +82 -0
  103. package/server/runtime/rest/match.ts +48 -0
  104. package/server/runtime/tsconfig.json +7 -0
  105. package/src/backend/index.ts +202 -160
  106. package/src/cli/create.ts +15 -5
  107. package/src/cli/diagnostics.ts +81 -0
  108. package/src/cli/doctor.ts +384 -7
  109. package/src/cli/index.ts +11 -2
  110. package/src/cli/proc.ts +50 -50
  111. package/src/cli/updates.ts +69 -69
  112. package/src/cli/validate.ts +31 -31
  113. package/src/client/channel/channel.ts +146 -146
  114. package/src/client/components/Form.tsx +65 -65
  115. package/src/client/components/Script.tsx +113 -113
  116. package/src/client/components/Slot.tsx +21 -21
  117. package/src/client/dev/devtools.tsx +1018 -0
  118. package/src/client/dev/error-overlay.tsx +30 -4
  119. package/src/client/errors.ts +11 -0
  120. package/src/client/head/head.ts +167 -167
  121. package/src/client/head/metadata.ts +112 -112
  122. package/src/client/index.ts +91 -89
  123. package/src/client/navigation/NavLink.tsx +86 -86
  124. package/src/client/navigation/navigation.ts +235 -235
  125. package/src/client/navigation/prefetch.ts +169 -130
  126. package/src/client/navigation/scroll.ts +53 -53
  127. package/src/client/routing/Router.tsx +8 -2
  128. package/src/client/routing/action.ts +122 -122
  129. package/src/client/routing/error-boundary.tsx +43 -43
  130. package/src/client/routing/hooks.ts +21 -6
  131. package/src/client/routing/loader.ts +325 -235
  132. package/src/client/routing/match.ts +47 -47
  133. package/src/client/routing/mount.tsx +54 -52
  134. package/src/client/routing/params-context.ts +10 -10
  135. package/src/client/routing/slot-context.ts +7 -7
  136. package/src/client/rpc.ts +64 -0
  137. package/src/client/search/search.ts +189 -189
  138. package/src/client/search/use-page-search.ts +73 -73
  139. package/src/client/types.ts +73 -73
  140. package/src/compiler/config.ts +221 -182
  141. package/src/compiler/docs.ts +285 -228
  142. package/src/compiler/generate.ts +395 -394
  143. package/src/compiler/index.ts +66 -57
  144. package/src/compiler/pages.ts +70 -70
  145. package/src/compiler/plugin.ts +258 -2
  146. package/src/compiler/prerender.ts +156 -156
  147. package/src/compiler/seo.ts +417 -390
  148. package/src/compiler/ssg.ts +171 -126
  149. package/src/compiler/vite.ts +34 -0
  150. package/src/io/FastMap.ts +151 -127
  151. package/src/io/FastSet.ts +15 -1
  152. package/src/io/codec.ts +217 -0
  153. package/src/io/index.ts +10 -11
  154. package/src/io/lengths.ts +14 -14
  155. package/src/io/types.ts +19 -18
  156. package/src/logger/index.ts +22 -22
  157. package/src/shared/index.ts +10 -10
  158. package/std/client/index.d.ts +15 -15
  159. package/std/client/package.json +3 -3
  160. package/test/assembly/example.spec.ts +17 -7
  161. package/test/channel.test.ts +21 -21
  162. package/test/doctor.test.ts +65 -0
  163. package/test/dom/Link.test.tsx +47 -47
  164. package/test/dom/NavLink.test.tsx +37 -37
  165. package/test/dom/error-overlay.test.tsx +44 -44
  166. package/test/dom/loader.test.tsx +121 -121
  167. package/test/dom/navigation.test.ts +59 -59
  168. package/test/dom/revalidate.test.tsx +38 -38
  169. package/test/dom/route-head.test.tsx +78 -78
  170. package/test/dom/router-loading.test.tsx +44 -44
  171. package/test/dom/scroll.test.ts +56 -56
  172. package/test/dom/use-metadata.test.tsx +58 -58
  173. package/test/errors.test.ts +21 -0
  174. package/test/io.test.ts +117 -93
  175. package/test/navlink.test.ts +28 -28
  176. package/test/placeholder.test.ts +9 -9
  177. package/test/prettier-plugin.test.ts +46 -0
  178. package/test/routes.test.ts +76 -76
  179. package/test/rpc.test.ts +50 -0
  180. package/test/seo.test.ts +175 -164
  181. package/test/slot-layouts.test.ts +69 -69
  182. package/test/ssg.test.ts +36 -36
  183. package/test/update.test.ts +44 -44
  184. package/test/validate.test.ts +42 -42
  185. package/tests/data-parity/generated-parity.ts +99 -0
  186. package/tests/data-parity/parity.ts +80 -0
  187. package/tests/data-parity/spec.ts +46 -0
  188. package/toil-routes.d.ts +7 -0
  189. package/tsconfig.backend.json +13 -13
  190. package/tsconfig.base.json +35 -35
  191. package/tsconfig.cli.json +13 -13
  192. package/tsconfig.client.json +14 -14
  193. package/tsconfig.compiler.json +13 -13
  194. package/tsconfig.io.json +12 -12
  195. package/tsconfig.json +22 -22
  196. package/tsconfig.logger.json +12 -12
  197. package/tsconfig.server.json +10 -10
  198. package/tsconfig.shared.json +12 -12
  199. package/vitest.config.ts +26 -26
  200. package/.idea/codeStyles/Project.xml +0 -54
  201. package/.idea/codeStyles/codeStyleConfig.xml +0 -5
  202. package/.idea/inspectionProfiles/Project_Default.xml +0 -6
  203. package/.idea/modules.xml +0 -8
  204. package/.idea/prettier.xml +0 -7
  205. package/.idea/toiljs.iml +0 -8
  206. package/.idea/vcs.xml +0 -6
  207. package/.toil/entry.tsx +0 -9
  208. package/.toil/index.html +0 -12
  209. package/.toil/routes.ts +0 -9
  210. package/build/cli/configure.d.ts +0 -16
  211. package/build/cli/configure.js +0 -272
  212. package/build/cli/create.d.ts +0 -16
  213. package/build/cli/create.js +0 -420
  214. package/build/cli/diagnostics.d.ts +0 -55
  215. package/build/cli/diagnostics.js +0 -333
  216. package/build/cli/doctor.d.ts +0 -6
  217. package/build/cli/doctor.js +0 -249
  218. package/build/cli/features.d.ts +0 -25
  219. package/build/cli/features.js +0 -107
  220. package/build/cli/index.d.ts +0 -2
  221. package/build/cli/proc.d.ts +0 -6
  222. package/build/cli/proc.js +0 -31
  223. package/build/cli/ui.d.ts +0 -9
  224. package/build/cli/ui.js +0 -75
  225. package/build/cli/update.d.ts +0 -7
  226. package/build/cli/update.js +0 -117
  227. package/build/cli/updates.d.ts +0 -10
  228. package/build/cli/updates.js +0 -45
  229. package/build/cli/validate.d.ts +0 -4
  230. package/build/cli/validate.js +0 -19
  231. package/build/client/Link.d.ts +0 -8
  232. package/build/client/Link.js +0 -44
  233. package/build/client/NavLink.d.ts +0 -14
  234. package/build/client/NavLink.js +0 -37
  235. package/build/client/Router.d.ts +0 -7
  236. package/build/client/Router.js +0 -55
  237. package/build/client/channel.d.ts +0 -23
  238. package/build/client/channel.js +0 -94
  239. package/build/client/error-boundary.d.ts +0 -16
  240. package/build/client/error-boundary.js +0 -19
  241. package/build/client/head.d.ts +0 -26
  242. package/build/client/head.js +0 -87
  243. package/build/client/hooks.d.ts +0 -17
  244. package/build/client/hooks.js +0 -48
  245. package/build/client/lazy.d.ts +0 -16
  246. package/build/client/lazy.js +0 -53
  247. package/build/client/match.d.ts +0 -2
  248. package/build/client/match.js +0 -32
  249. package/build/client/mount.d.ts +0 -2
  250. package/build/client/mount.js +0 -13
  251. package/build/client/navigation.d.ts +0 -13
  252. package/build/client/navigation.js +0 -97
  253. package/build/client/params-context.d.ts +0 -2
  254. package/build/client/params-context.js +0 -2
  255. package/build/client/prefetch.d.ts +0 -11
  256. package/build/client/prefetch.js +0 -100
  257. package/build/client/runtime.d.ts +0 -31
  258. package/build/client/runtime.js +0 -112
  259. package/build/client/scroll.d.ts +0 -8
  260. package/build/client/scroll.js +0 -36
  261. package/build/io/BinaryReader.d.ts +0 -44
  262. package/build/io/BinaryReader.js +0 -244
  263. package/build/io/BinaryWriter.d.ts +0 -44
  264. package/build/io/BinaryWriter.js +0 -297
  265. package/build/server/release.wasm +0 -0
  266. package/build/server/release.wat +0 -9
  267. package/src/io/BinaryReader.ts +0 -340
  268. package/src/io/BinaryWriter.ts +0 -385
  269. package/src/server/index.ts +0 -10
  270. package/src/server/main.ts +0 -13
  271. package/src/server/tsconfig.json +0 -4
  272. package/toil-env.d.ts +0 -16
  273. package/toilconfig.json +0 -30
@@ -1,200 +1,200 @@
1
- /**
2
- * ESLint rule: disallow `.toString()` on Uint8Array (and branded byte types), which returns
3
- * comma-separated decimals instead of hex.
4
- */
5
- import { AST_NODE_TYPES, ESLintUtils } from '@typescript-eslint/utils';
6
- import { SyntaxKind } from 'typescript';
7
-
8
- function isUint8ArrayType(type, checker) {
9
- const symbol = type.getSymbol();
10
- if (symbol?.getName() === 'Uint8Array') {
11
- return true;
12
- }
13
-
14
- const baseTypes = type.getBaseTypes?.();
15
- if (baseTypes) {
16
- for (const baseType of baseTypes) {
17
- if (isUint8ArrayType(baseType, checker)) {
18
- return true;
19
- }
20
- }
21
- }
22
-
23
- if (type.isIntersection()) {
24
- for (const subType of type.types) {
25
- if (isUint8ArrayType(subType, checker)) {
26
- return true;
27
- }
28
- }
29
- }
30
-
31
- if (type.isUnion()) {
32
- return (
33
- type.types.length > 0 &&
34
- type.types.every((subType) => isUint8ArrayType(subType, checker))
35
- );
36
- }
37
-
38
- const constraint = type.getConstraint?.();
39
- if (constraint && isUint8ArrayType(constraint, checker)) {
40
- return true;
41
- }
42
-
43
- return false;
44
- }
45
-
46
- /**
47
- * Types whose toString() is the dangerous default behavior we want to catch.
48
- * If toString is declared on any type NOT in this set, it has been
49
- * intentionally overridden and we should leave it alone.
50
- */
51
- const DEFAULT_TOSTRING_OWNERS = new Set([
52
- 'Object',
53
- 'Uint8Array',
54
- 'Int8Array',
55
- 'Uint8ClampedArray',
56
- 'Int16Array',
57
- 'Uint16Array',
58
- 'Int32Array',
59
- 'Uint32Array',
60
- 'Float32Array',
61
- 'Float64Array',
62
- 'BigInt64Array',
63
- 'BigUint64Array',
64
- ]);
65
-
66
- /**
67
- * Given a declaration node, walk up the AST parents to find the enclosing
68
- * class or interface name. More reliable than checker.getTypeAtLocation(decl.parent),
69
- * which can return odd results for .d.ts files.
70
- */
71
- function getEnclosingClassName(decl) {
72
- let current = decl.parent;
73
- while (current) {
74
- if (
75
- current.kind === SyntaxKind.ClassDeclaration ||
76
- current.kind === SyntaxKind.ClassExpression ||
77
- current.kind === SyntaxKind.InterfaceDeclaration
78
- ) {
79
- if (current.name) {
80
- return current.name.text;
81
- }
82
- }
83
-
84
- current = current.parent;
85
- }
86
-
87
- return undefined;
88
- }
89
-
90
- /**
91
- * Checks whether the resolved toString() on this type is a custom override
92
- * rather than the default Uint8Array/Object prototype version.
93
- */
94
- function hasCustomToString(type, checker) {
95
- const toStringSymbol = type.getProperty('toString');
96
- if (!toStringSymbol) {
97
- return false;
98
- }
99
-
100
- const declarations = toStringSymbol.getDeclarations();
101
- if (!declarations || declarations.length === 0) {
102
- return false;
103
- }
104
-
105
- for (const decl of declarations) {
106
- const ownerName = getEnclosingClassName(decl);
107
- if (ownerName && !DEFAULT_TOSTRING_OWNERS.has(ownerName)) {
108
- return true;
109
- }
110
- }
111
-
112
- const apparentType = checker.getApparentType(type);
113
- if (apparentType !== type) {
114
- const apparentToString = apparentType.getProperty('toString');
115
- if (apparentToString && apparentToString !== toStringSymbol) {
116
- const apparentDecls = apparentToString.getDeclarations();
117
- if (apparentDecls) {
118
- for (const decl of apparentDecls) {
119
- const ownerName = getEnclosingClassName(decl);
120
- if (ownerName && !DEFAULT_TOSTRING_OWNERS.has(ownerName)) {
121
- return true;
122
- }
123
- }
124
- }
125
- }
126
- }
127
-
128
- return false;
129
- }
130
-
131
- const createRule = ESLintUtils.RuleCreator(
132
- (name) => `https://github.com/dacely-cloud/toiljs/tree/main/presets#${name}`,
133
- );
134
-
135
- const rule = createRule({
136
- name: 'no-uint8array-tostring',
137
- meta: {
138
- type: 'problem',
139
- docs: {
140
- description:
141
- 'Disallow .toString() on Uint8Array and branded types (Script, Bytes32, etc.) which produces comma-separated decimals instead of hex',
142
- },
143
- messages: {
144
- noUint8ArrayToString:
145
- '{{typeName}}.toString() returns comma-separated decimals (e.g. "0,32,70,107"), not a hex string. ' +
146
- 'Use Buffer.from(arr).toString("hex") or toHex() instead.',
147
- },
148
- schema: [],
149
- },
150
- defaultOptions: [],
151
- create(context) {
152
- const services = ESLintUtils.getParserServices(context);
153
- const checker = services.program.getTypeChecker();
154
-
155
- return {
156
- CallExpression(node) {
157
- if (
158
- node.callee.type !== AST_NODE_TYPES.MemberExpression ||
159
- node.callee.property.type !== AST_NODE_TYPES.Identifier ||
160
- node.callee.property.name !== 'toString' ||
161
- node.arguments.length > 0
162
- ) {
163
- return;
164
- }
165
-
166
- const objectNode = node.callee.object;
167
- const tsNode = services.esTreeNodeToTSNodeMap.get(objectNode);
168
- const type = checker.getTypeAtLocation(tsNode);
169
-
170
- if (!isUint8ArrayType(type, checker)) {
171
- return;
172
- }
173
-
174
- if (hasCustomToString(type, checker)) {
175
- return;
176
- }
177
-
178
- const typeName = checker.typeToString(type);
179
- context.report({
180
- node,
181
- messageId: 'noUint8ArrayToString',
182
- data: { typeName },
183
- });
184
- },
185
- };
186
- },
187
- });
188
-
189
- const plugin = {
190
- meta: {
191
- name: 'eslint-plugin-no-uint8array-tostring',
192
- version: '1.0.0',
193
- },
194
- rules: {
195
- 'no-uint8array-tostring': rule,
196
- },
197
- };
198
-
199
- export default plugin;
200
- export { rule };
1
+ /**
2
+ * ESLint rule: disallow `.toString()` on Uint8Array (and branded byte types), which returns
3
+ * comma-separated decimals instead of hex.
4
+ */
5
+ import { AST_NODE_TYPES, ESLintUtils } from '@typescript-eslint/utils';
6
+ import { SyntaxKind } from 'typescript';
7
+
8
+ function isUint8ArrayType(type, checker) {
9
+ const symbol = type.getSymbol();
10
+ if (symbol?.getName() === 'Uint8Array') {
11
+ return true;
12
+ }
13
+
14
+ const baseTypes = type.getBaseTypes?.();
15
+ if (baseTypes) {
16
+ for (const baseType of baseTypes) {
17
+ if (isUint8ArrayType(baseType, checker)) {
18
+ return true;
19
+ }
20
+ }
21
+ }
22
+
23
+ if (type.isIntersection()) {
24
+ for (const subType of type.types) {
25
+ if (isUint8ArrayType(subType, checker)) {
26
+ return true;
27
+ }
28
+ }
29
+ }
30
+
31
+ if (type.isUnion()) {
32
+ return (
33
+ type.types.length > 0 &&
34
+ type.types.every((subType) => isUint8ArrayType(subType, checker))
35
+ );
36
+ }
37
+
38
+ const constraint = type.getConstraint?.();
39
+ if (constraint && isUint8ArrayType(constraint, checker)) {
40
+ return true;
41
+ }
42
+
43
+ return false;
44
+ }
45
+
46
+ /**
47
+ * Types whose toString() is the dangerous default behavior we want to catch.
48
+ * If toString is declared on any type NOT in this set, it has been
49
+ * intentionally overridden and we should leave it alone.
50
+ */
51
+ const DEFAULT_TOSTRING_OWNERS = new Set([
52
+ 'Object',
53
+ 'Uint8Array',
54
+ 'Int8Array',
55
+ 'Uint8ClampedArray',
56
+ 'Int16Array',
57
+ 'Uint16Array',
58
+ 'Int32Array',
59
+ 'Uint32Array',
60
+ 'Float32Array',
61
+ 'Float64Array',
62
+ 'BigInt64Array',
63
+ 'BigUint64Array',
64
+ ]);
65
+
66
+ /**
67
+ * Given a declaration node, walk up the AST parents to find the enclosing
68
+ * class or interface name. More reliable than checker.getTypeAtLocation(decl.parent),
69
+ * which can return odd results for .d.ts files.
70
+ */
71
+ function getEnclosingClassName(decl) {
72
+ let current = decl.parent;
73
+ while (current) {
74
+ if (
75
+ current.kind === SyntaxKind.ClassDeclaration ||
76
+ current.kind === SyntaxKind.ClassExpression ||
77
+ current.kind === SyntaxKind.InterfaceDeclaration
78
+ ) {
79
+ if (current.name) {
80
+ return current.name.text;
81
+ }
82
+ }
83
+
84
+ current = current.parent;
85
+ }
86
+
87
+ return undefined;
88
+ }
89
+
90
+ /**
91
+ * Checks whether the resolved toString() on this type is a custom override
92
+ * rather than the default Uint8Array/Object prototype version.
93
+ */
94
+ function hasCustomToString(type, checker) {
95
+ const toStringSymbol = type.getProperty('toString');
96
+ if (!toStringSymbol) {
97
+ return false;
98
+ }
99
+
100
+ const declarations = toStringSymbol.getDeclarations();
101
+ if (!declarations || declarations.length === 0) {
102
+ return false;
103
+ }
104
+
105
+ for (const decl of declarations) {
106
+ const ownerName = getEnclosingClassName(decl);
107
+ if (ownerName && !DEFAULT_TOSTRING_OWNERS.has(ownerName)) {
108
+ return true;
109
+ }
110
+ }
111
+
112
+ const apparentType = checker.getApparentType(type);
113
+ if (apparentType !== type) {
114
+ const apparentToString = apparentType.getProperty('toString');
115
+ if (apparentToString && apparentToString !== toStringSymbol) {
116
+ const apparentDecls = apparentToString.getDeclarations();
117
+ if (apparentDecls) {
118
+ for (const decl of apparentDecls) {
119
+ const ownerName = getEnclosingClassName(decl);
120
+ if (ownerName && !DEFAULT_TOSTRING_OWNERS.has(ownerName)) {
121
+ return true;
122
+ }
123
+ }
124
+ }
125
+ }
126
+ }
127
+
128
+ return false;
129
+ }
130
+
131
+ const createRule = ESLintUtils.RuleCreator(
132
+ (name) => `https://github.com/dacely-cloud/toiljs/tree/main/presets#${name}`,
133
+ );
134
+
135
+ const rule = createRule({
136
+ name: 'no-uint8array-tostring',
137
+ meta: {
138
+ type: 'problem',
139
+ docs: {
140
+ description:
141
+ 'Disallow .toString() on Uint8Array and branded types (Script, Bytes32, etc.) which produces comma-separated decimals instead of hex',
142
+ },
143
+ messages: {
144
+ noUint8ArrayToString:
145
+ '{{typeName}}.toString() returns comma-separated decimals (e.g. "0,32,70,107"), not a hex string. ' +
146
+ 'Use Buffer.from(arr).toString("hex") or toHex() instead.',
147
+ },
148
+ schema: [],
149
+ },
150
+ defaultOptions: [],
151
+ create(context) {
152
+ const services = ESLintUtils.getParserServices(context);
153
+ const checker = services.program.getTypeChecker();
154
+
155
+ return {
156
+ CallExpression(node) {
157
+ if (
158
+ node.callee.type !== AST_NODE_TYPES.MemberExpression ||
159
+ node.callee.property.type !== AST_NODE_TYPES.Identifier ||
160
+ node.callee.property.name !== 'toString' ||
161
+ node.arguments.length > 0
162
+ ) {
163
+ return;
164
+ }
165
+
166
+ const objectNode = node.callee.object;
167
+ const tsNode = services.esTreeNodeToTSNodeMap.get(objectNode);
168
+ const type = checker.getTypeAtLocation(tsNode);
169
+
170
+ if (!isUint8ArrayType(type, checker)) {
171
+ return;
172
+ }
173
+
174
+ if (hasCustomToString(type, checker)) {
175
+ return;
176
+ }
177
+
178
+ const typeName = checker.typeToString(type);
179
+ context.report({
180
+ node,
181
+ messageId: 'noUint8ArrayToString',
182
+ data: { typeName },
183
+ });
184
+ },
185
+ };
186
+ },
187
+ });
188
+
189
+ const plugin = {
190
+ meta: {
191
+ name: 'eslint-plugin-no-uint8array-tostring',
192
+ version: '1.0.0',
193
+ },
194
+ rules: {
195
+ 'no-uint8array-tostring': rule,
196
+ },
197
+ };
198
+
199
+ export default plugin;
200
+ export { rule };
@@ -0,0 +1,51 @@
1
+ /**
2
+ * Prettier plugin that lets prettier format toilscript server code, which uses native
3
+ * decorators on free functions (`@main`, `@remote function ...`). Those are valid
4
+ * toilscript but not valid ECMAScript/TypeScript grammar, so prettier's parser rejects
5
+ * them outright.
6
+ *
7
+ * The fix is a parse-time/print-time round-trip: in `preprocess` each function decorator
8
+ * is rewritten to a marker block comment (which the TS parser accepts), and the estree
9
+ * printer's `printComment` renders that marker back as the original `@decorator`. Class
10
+ * and method decorators are already valid grammar and pass through untouched.
11
+ */
12
+ import * as tsPlugin from 'prettier/plugins/typescript';
13
+ import * as estreePlugin from 'prettier/plugins/estree';
14
+
15
+ const baseTs = tsPlugin.parsers.typescript;
16
+ const baseEstree = estreePlugin.printers.estree;
17
+
18
+ const MARKER = '::toil-decorator ';
19
+ // One-or-more bare decorators (`@name`, no args) immediately before a function declaration.
20
+ const FN_DECORATORS =
21
+ /((?:@[A-Za-z_$][\w$]*[ \t]*\r?\n[ \t]*)+)((?:export[ \t]+)?(?:default[ \t]+)?(?:async[ \t]+)?function\b)/g;
22
+ const ONE_DECORATOR = /@([A-Za-z_$][\w$]*)([ \t]*\r?\n[ \t]*)/g;
23
+
24
+ function preprocess(text, options) {
25
+ const pre = baseTs.preprocess ? baseTs.preprocess(text, options) : text;
26
+ return pre.replace(FN_DECORATORS, (_match, decorators, fn) => {
27
+ const masked = decorators.replace(
28
+ ONE_DECORATOR,
29
+ (_d, name, gap) => `/*${MARKER}${name}*/${gap}`,
30
+ );
31
+ return masked + fn;
32
+ });
33
+ }
34
+
35
+ export const parsers = {
36
+ typescript: { ...baseTs, preprocess },
37
+ };
38
+
39
+ export const printers = {
40
+ estree: {
41
+ ...baseEstree,
42
+ printComment(path, options) {
43
+ const comment = path.node ?? path.getValue();
44
+ const value = comment?.value;
45
+ if (typeof value === 'string' && value.startsWith(MARKER)) {
46
+ return '@' + value.slice(MARKER.length).trim();
47
+ }
48
+ return baseEstree.printComment(path, options);
49
+ },
50
+ },
51
+ };
@@ -1,18 +1,19 @@
1
- {
2
- "printWidth": 120,
3
- "tabWidth": 4,
4
- "useTabs": false,
5
- "semi": true,
6
- "singleQuote": true,
7
- "trailingComma": "none",
8
- "bracketSpacing": true,
9
- "bracketSameLine": true,
10
- "arrowParens": "always",
11
- "htmlWhitespaceSensitivity": "css",
12
- "overrides": [
13
- {
14
- "files": "*.html",
15
- "options": { "parser": "html" }
16
- }
17
- ]
18
- }
1
+ {
2
+ "plugins": ["toiljs/prettier-plugin"],
3
+ "printWidth": 120,
4
+ "tabWidth": 4,
5
+ "useTabs": false,
6
+ "semi": true,
7
+ "singleQuote": true,
8
+ "trailingComma": "none",
9
+ "bracketSpacing": true,
10
+ "bracketSameLine": true,
11
+ "arrowParens": "always",
12
+ "htmlWhitespaceSensitivity": "css",
13
+ "overrides": [
14
+ {
15
+ "files": "*.html",
16
+ "options": { "parser": "html" }
17
+ }
18
+ ]
19
+ }
@@ -1,37 +1,37 @@
1
- // toiljs shared client tsconfig, opinionated, strict.
2
- // Extend it from your project: { "extends": "toiljs/tsconfig", "include": ["client", ".toil"] }
3
- {
4
- "compilerOptions": {
5
- "strict": true,
6
- "noImplicitAny": true,
7
- "strictNullChecks": true,
8
- "strictFunctionTypes": true,
9
- "strictBindCallApply": true,
10
- "strictPropertyInitialization": true,
11
- "noImplicitThis": true,
12
- "useUnknownInCatchVariables": true,
13
- "alwaysStrict": true,
14
- "noUnusedLocals": true,
15
- "noUnusedParameters": true,
16
- "exactOptionalPropertyTypes": false,
17
- "noImplicitReturns": false,
18
- "noFallthroughCasesInSwitch": true,
19
- "noUncheckedIndexedAccess": false,
20
- "noImplicitOverride": true,
21
- "noPropertyAccessFromIndexSignature": false,
22
- "module": "ES2020",
23
- "target": "ES2020",
24
- "moduleResolution": "Bundler",
25
- "jsx": "react-jsx",
26
- "lib": ["ESNext", "DOM", "DOM.Iterable", "DOM.AsyncIterable"],
27
- "isolatedModules": true,
28
- "verbatimModuleSyntax": false,
29
- "allowImportingTsExtensions": true,
30
- "esModuleInterop": true,
31
- "resolveJsonModule": true,
32
- "forceConsistentCasingInFileNames": true,
33
- "skipLibCheck": true,
34
- "moduleDetection": "force",
35
- "noEmit": true
36
- }
37
- }
1
+ // toiljs shared client tsconfig, opinionated, strict.
2
+ // Extend it from your project: { "extends": "toiljs/tsconfig", "include": ["client", ".toil"] }
3
+ {
4
+ "compilerOptions": {
5
+ "strict": true,
6
+ "noImplicitAny": true,
7
+ "strictNullChecks": true,
8
+ "strictFunctionTypes": true,
9
+ "strictBindCallApply": true,
10
+ "strictPropertyInitialization": true,
11
+ "noImplicitThis": true,
12
+ "useUnknownInCatchVariables": true,
13
+ "alwaysStrict": true,
14
+ "noUnusedLocals": true,
15
+ "noUnusedParameters": true,
16
+ "exactOptionalPropertyTypes": false,
17
+ "noImplicitReturns": false,
18
+ "noFallthroughCasesInSwitch": true,
19
+ "noUncheckedIndexedAccess": false,
20
+ "noImplicitOverride": true,
21
+ "noPropertyAccessFromIndexSignature": false,
22
+ "module": "ES2020",
23
+ "target": "ES2020",
24
+ "moduleResolution": "Bundler",
25
+ "jsx": "react-jsx",
26
+ "lib": ["ESNext", "DOM", "DOM.Iterable", "DOM.AsyncIterable"],
27
+ "isolatedModules": true,
28
+ "verbatimModuleSyntax": false,
29
+ "allowImportingTsExtensions": true,
30
+ "esModuleInterop": true,
31
+ "resolveJsonModule": true,
32
+ "forceConsistentCasingInFileNames": true,
33
+ "skipLibCheck": true,
34
+ "moduleDetection": "force",
35
+ "noEmit": true
36
+ }
37
+ }
@@ -0,0 +1,97 @@
1
+ # toiljs server runtime
2
+
3
+ In-tree SDK that bridges a toilscript handler to the toil-backend
4
+ edge's wasm ABI.
5
+
6
+ ## What it does
7
+
8
+ The edge calls `handle(req_ofs: i32, req_len: i32) -> i64` on every
9
+ request. This runtime gives you:
10
+
11
+ - `Request` / `Response` AssemblyScript types
12
+ - A byte-for-byte envelope codec matching
13
+ `toil-backend/src/http/envelope.rs`
14
+ - A `ToilHandler` base class you extend, plus a `Server` singleton you
15
+ assign `Server.handler = () => new MyHandler()`. The `handle` wasm
16
+ export (re-exported from `toiljs/server/runtime/exports`) decodes the
17
+ request, runs your handler, encodes the response, and returns the
18
+ packed i64 the host expects.
19
+
20
+ ## Wire contract
21
+
22
+ Source of truth: `toil-backend/src/http/envelope.rs`.
23
+
24
+ ```
25
+ request envelope (LE, no padding):
26
+ u8 method 0=GET 1=POST 2=PUT 3=DELETE 4=PATCH 5=HEAD 6=OPTIONS
27
+ u16 path_len
28
+ [u8] path
29
+ u16 n_headers
30
+ for each header: u16 name_len, u16 val_len, [u8] name, [u8] val
31
+ u32 body_len
32
+ [u8] body
33
+ ```
34
+
35
+ The response envelope is the same shape with the first `u8 method +
36
+ u16 path_len + path` replaced by `u16 status`.
37
+
38
+ The handler must return a packed `i64`:
39
+
40
+ ```
41
+ (resp_ofs << 32) | resp_len
42
+ ```
43
+
44
+ The host reads `resp_len` bytes starting at `resp_ofs` in linear
45
+ memory and decodes them as a response envelope.
46
+
47
+ ## Memory layout
48
+
49
+ - `[0, req_len)` — request envelope, written by the host before
50
+ `handle` is called.
51
+ - `[65536, 65536 + resp_len)` — response envelope, written by
52
+ `dispatch` (the response base is the second 64 KiB page so the
53
+ request and response never overlap).
54
+
55
+ The edge enforces a 1024-page (64 MiB) linear memory cap via
56
+ `LimitingTunables`, so leaving the first page for the request is
57
+ fine.
58
+
59
+ ## Example
60
+
61
+ A user app extends `ToilHandler` and wires it up in `server/main.ts`.
62
+ The runtime is consumed as the `toiljs/server/runtime` library export:
63
+
64
+ ```ts
65
+ // server/HelloHandler.ts
66
+ import { ToilHandler, Request, Response } from 'toiljs/server/runtime';
67
+
68
+ export class HelloHandler extends ToilHandler {
69
+ public handle(req: Request): Response {
70
+ if (req.path == '/') return Response.text('hello\n');
71
+ if (req.path == '/json') return Response.json('{"ok":true}');
72
+ return Response.notFound();
73
+ }
74
+ }
75
+ ```
76
+
77
+ ```ts
78
+ // server/main.ts
79
+ import { Server } from 'toiljs/server/runtime';
80
+ import { revertOnError } from 'toiljs/server/runtime/abort/abort';
81
+ import { HelloHandler } from './HelloHandler';
82
+
83
+ Server.handler = () => new HelloHandler();
84
+
85
+ // Surface the wasm `handle(i32, i32) -> i64` entry the edge calls.
86
+ export * from 'toiljs/server/runtime/exports';
87
+
88
+ // Forward AS runtime panics to the host's env::abort import.
89
+ export function abort(message: string, fileName: string, line: u32, column: u32): void {
90
+ revertOnError(message, fileName, line, column);
91
+ }
92
+ ```
93
+
94
+ Compile with `toilscript --target release`, drop the resulting
95
+ `build/server/release.wasm` at `<toil-backend>/hosts/<hostname>.wasm`,
96
+ and the edge will route requests with that `Host:` header to it. A
97
+ complete app lives in `examples/basic`.