toiljs 0.0.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 (86) hide show
  1. package/.babelrc +13 -0
  2. package/.gitattributes +2 -0
  3. package/.github/ISSUE_TEMPLATE/bug_report.md +38 -0
  4. package/.github/ISSUE_TEMPLATE/bug_report.yml +90 -0
  5. package/.github/ISSUE_TEMPLATE/config.yml +8 -0
  6. package/.github/ISSUE_TEMPLATE/feature_request.md +20 -0
  7. package/.github/PULL_REQUEST_TEMPLATE.md +43 -0
  8. package/.github/changelog-config.json +45 -0
  9. package/.github/dependabot.yml +27 -0
  10. package/.github/workflows/ci.yml +191 -0
  11. package/.idea/codeStyles/Project.xml +54 -0
  12. package/.idea/codeStyles/codeStyleConfig.xml +5 -0
  13. package/.idea/inspectionProfiles/Project_Default.xml +6 -0
  14. package/.idea/modules.xml +8 -0
  15. package/.idea/prettier.xml +6 -0
  16. package/.idea/toiljs.iml +8 -0
  17. package/.idea/vcs.xml +6 -0
  18. package/.prettierrc.json +12 -0
  19. package/.vscode/settings.json +10 -0
  20. package/CHANGELOG.md +5 -0
  21. package/LICENSE +188 -0
  22. package/README.md +1 -0
  23. package/as-pect.asconfig.json +34 -0
  24. package/as-pect.config.js +65 -0
  25. package/eslint.config.js +48 -0
  26. package/examples/basic/.prettierrc +1 -0
  27. package/examples/basic/client/404.tsx +14 -0
  28. package/examples/basic/client/layout.tsx +14 -0
  29. package/examples/basic/client/routes/about.tsx +13 -0
  30. package/examples/basic/client/routes/blog/[id].tsx +14 -0
  31. package/examples/basic/client/routes/docs/[...slug].tsx +15 -0
  32. package/examples/basic/client/routes/index.tsx +13 -0
  33. package/examples/basic/client/routes/io.tsx +28 -0
  34. package/examples/basic/eslint.config.js +3 -0
  35. package/examples/basic/package.json +24 -0
  36. package/examples/basic/toil.config.ts +7 -0
  37. package/examples/basic/tsconfig.json +4 -0
  38. package/package.json +141 -0
  39. package/presets/eslint.js +77 -0
  40. package/presets/no-uint8array-tostring.js +201 -0
  41. package/presets/prettier.json +11 -0
  42. package/presets/tsconfig.json +37 -0
  43. package/src/backend/index.ts +167 -0
  44. package/src/cli/create.ts +272 -0
  45. package/src/cli/index.ts +161 -0
  46. package/src/cli/ui.ts +79 -0
  47. package/src/client/channel.ts +146 -0
  48. package/src/client/index.ts +12 -0
  49. package/src/client/match.ts +39 -0
  50. package/src/client/runtime.tsx +190 -0
  51. package/src/compiler/config.ts +115 -0
  52. package/src/compiler/generate.ts +91 -0
  53. package/src/compiler/index.ts +49 -0
  54. package/src/compiler/plugin.ts +26 -0
  55. package/src/compiler/routes.ts +70 -0
  56. package/src/compiler/vite.ts +90 -0
  57. package/src/io/BinaryReader.ts +344 -0
  58. package/src/io/BinaryWriter.ts +385 -0
  59. package/src/io/FastMap.ts +127 -0
  60. package/src/io/FastSet.ts +96 -0
  61. package/src/io/index.ts +11 -0
  62. package/src/io/lengths.ts +14 -0
  63. package/src/io/types.ts +18 -0
  64. package/src/logger/index.ts +22 -0
  65. package/src/server/index.ts +11 -0
  66. package/src/server/main.ts +13 -0
  67. package/src/shared/index.ts +10 -0
  68. package/std/client/index.d.ts +15 -0
  69. package/std/client/package.json +3 -0
  70. package/test/channel.test.ts +21 -0
  71. package/test/io.test.ts +85 -0
  72. package/test/placeholder.test.ts +9 -0
  73. package/test/routes.test.ts +42 -0
  74. package/tests/server/example.spec.ts +7 -0
  75. package/toilconfig.json +30 -0
  76. package/tsconfig.backend.json +13 -0
  77. package/tsconfig.base.json +35 -0
  78. package/tsconfig.cli.json +13 -0
  79. package/tsconfig.client.json +14 -0
  80. package/tsconfig.compiler.json +13 -0
  81. package/tsconfig.io.json +12 -0
  82. package/tsconfig.json +22 -0
  83. package/tsconfig.logger.json +12 -0
  84. package/tsconfig.server.json +10 -0
  85. package/tsconfig.shared.json +12 -0
  86. package/vitest.config.ts +22 -0
@@ -0,0 +1,10 @@
1
+ /**
2
+ * Shared primitives used across every toiljs target (client, compiler, cli, server tooling).
3
+ * Placeholder — real shared types/utilities land here.
4
+ */
5
+
6
+ export const FRAMEWORK_NAME = 'toiljs';
7
+
8
+ export interface ToilTarget {
9
+ readonly name: 'client' | 'compiler' | 'cli' | 'server';
10
+ }
@@ -0,0 +1,15 @@
1
+ /**
2
+ * Ambient "native" types for the toiljs client framework.
3
+ *
4
+ * These are injected into the client target so users don't import them (a `declare global`
5
+ * block discovered via tsconfig). Placeholder declarations; real framework globals land here.
6
+ */
7
+
8
+ declare global {
9
+ /** Global toil client handle, available without imports inside client code. */
10
+ const toil: {
11
+ readonly version: string;
12
+ };
13
+ }
14
+
15
+ export {};
@@ -0,0 +1,3 @@
1
+ {
2
+ "types": "index.d.ts"
3
+ }
@@ -0,0 +1,21 @@
1
+ import { describe, expect, it } from 'vitest';
2
+
3
+ import { resolveChannelUrl } from '../src/client/channel';
4
+
5
+ describe('resolveChannelUrl', () => {
6
+ it('uses ws:// over http and the default /_toil path', () => {
7
+ expect(resolveChannelUrl(undefined, { protocol: 'http:', host: 'localhost:3000' })).toBe(
8
+ 'ws://localhost:3000/_toil',
9
+ );
10
+ });
11
+
12
+ it('uses wss:// over https', () => {
13
+ expect(resolveChannelUrl('/_toil', { protocol: 'https:', host: 'app.example.com' })).toBe(
14
+ 'wss://app.example.com/_toil',
15
+ );
16
+ });
17
+
18
+ it('normalizes a path without a leading slash', () => {
19
+ expect(resolveChannelUrl('live', { protocol: 'http:', host: 'h:1' })).toBe('ws://h:1/live');
20
+ });
21
+ });
@@ -0,0 +1,85 @@
1
+ import { describe, expect, it } from 'vitest';
2
+
3
+ import { BinaryReader } from '../src/io/BinaryReader';
4
+ import { BinaryWriter } from '../src/io/BinaryWriter';
5
+ import { FastMap } from '../src/io/FastMap';
6
+ import { FastSet } from '../src/io/FastSet';
7
+
8
+ describe('BinaryWriter / BinaryReader', () => {
9
+ it('round-trips fixed-width integers', () => {
10
+ const w = new BinaryWriter();
11
+ w.writeU8(255);
12
+ w.writeU16(65535);
13
+ w.writeU32(4294967295);
14
+ w.writeU64(18446744073709551615n);
15
+ w.writeI8(-128);
16
+ w.writeI32(-2147483648);
17
+
18
+ const r = new BinaryReader(w.getBuffer());
19
+ expect(r.readU8()).toBe(255);
20
+ expect(r.readU16()).toBe(65535);
21
+ expect(r.readU32()).toBe(4294967295);
22
+ expect(r.readU64()).toBe(18446744073709551615n);
23
+ expect(r.readI8()).toBe(-128);
24
+ expect(r.readI32()).toBe(-2147483648);
25
+ });
26
+
27
+ it('round-trips u256 and strings', () => {
28
+ const big = 123456789012345678901234567890n;
29
+ const w = new BinaryWriter();
30
+ w.writeU256(big);
31
+ w.writeStringWithLength('hello toil 🛠');
32
+ w.writeBoolean(true);
33
+
34
+ const r = new BinaryReader(w.getBuffer());
35
+ expect(r.readU256()).toBe(big);
36
+ expect(r.readStringWithLength()).toBe('hello toil 🛠');
37
+ expect(r.readBoolean()).toBe(true);
38
+ });
39
+
40
+ it('round-trips arrays', () => {
41
+ const w = new BinaryWriter();
42
+ w.writeU32Array([1, 2, 3]);
43
+ w.writeStringArray(['a', 'bb', 'ccc']);
44
+
45
+ const r = new BinaryReader(w.getBuffer());
46
+ expect(r.readU32Array()).toEqual([1, 2, 3]);
47
+ expect(r.readStringArray()).toEqual(['a', 'bb', 'ccc']);
48
+ });
49
+
50
+ it('rejects out-of-range values', () => {
51
+ const w = new BinaryWriter();
52
+ expect(() => w.writeU8(256)).toThrow();
53
+ expect(() => w.writeI8(128)).toThrow();
54
+ });
55
+
56
+ it('throws when reading past the end', () => {
57
+ const r = new BinaryReader(new Uint8Array(2));
58
+ expect(() => r.readU32()).toThrow();
59
+ });
60
+ });
61
+
62
+ describe('FastMap', () => {
63
+ it('supports bigint keys and basic ops', () => {
64
+ const m = new FastMap<bigint, string>();
65
+ m.set(1n, 'one').set(2n, 'two');
66
+ expect(m.size).toBe(2);
67
+ expect(m.get(1n)).toBe('one');
68
+ expect(m.has(2n)).toBe(true);
69
+ expect(m.delete(1n)).toBe(true);
70
+ expect(m.has(1n)).toBe(false);
71
+ expect([...m.entries()]).toEqual([[2n, 'two']]);
72
+ });
73
+ });
74
+
75
+ describe('FastSet', () => {
76
+ it('dedupes and preserves insertion order', () => {
77
+ const s = new FastSet<bigint>();
78
+ s.add(2n).add(1n).add(2n);
79
+ expect(s.size).toBe(2);
80
+ expect(s.has(1n)).toBe(true);
81
+ expect([...s.values()]).toEqual([2n, 1n]);
82
+ expect(s.delete(2n)).toBe(true);
83
+ expect([...s.values()]).toEqual([1n]);
84
+ });
85
+ });
@@ -0,0 +1,9 @@
1
+ import { describe, expect, it } from 'vitest';
2
+
3
+ import { FRAMEWORK_NAME } from '../src/shared/index';
4
+
5
+ describe('toiljs scaffold', () => {
6
+ it('exposes the framework name', () => {
7
+ expect(FRAMEWORK_NAME).toBe('toiljs');
8
+ });
9
+ });
@@ -0,0 +1,42 @@
1
+ import { describe, expect, it } from 'vitest';
2
+
3
+ import { matchRoute } from '../src/client/match';
4
+ import { filePathToRoute } from '../src/compiler/routes';
5
+
6
+ describe('filePathToRoute', () => {
7
+ it('maps index, static, nested, and dynamic files to patterns', () => {
8
+ expect(filePathToRoute('index.tsx')).toBe('/');
9
+ expect(filePathToRoute('about.tsx')).toBe('/about');
10
+ expect(filePathToRoute('blog/index.tsx')).toBe('/blog');
11
+ expect(filePathToRoute('blog/[id].tsx')).toBe('/blog/:id');
12
+ expect(filePathToRoute('docs/guide/intro.jsx')).toBe('/docs/guide/intro');
13
+ expect(filePathToRoute('docs/[...slug].tsx')).toBe('/docs/*slug');
14
+ });
15
+ });
16
+
17
+ describe('matchRoute', () => {
18
+ it('matches static routes', () => {
19
+ expect(matchRoute('/', '/')).toEqual({});
20
+ expect(matchRoute('/about', '/about')).toEqual({});
21
+ });
22
+
23
+ it('rejects non-matches', () => {
24
+ expect(matchRoute('/about', '/x')).toBeNull();
25
+ expect(matchRoute('/blog/:id', '/blog')).toBeNull();
26
+ expect(matchRoute('/', '/about')).toBeNull();
27
+ });
28
+
29
+ it('extracts dynamic params', () => {
30
+ expect(matchRoute('/blog/:id', '/blog/42')).toEqual({ id: '42' });
31
+ expect(matchRoute('/u/:user/p/:post', '/u/ann/p/7')).toEqual({ user: 'ann', post: '7' });
32
+ expect(matchRoute('/blog/:id', '/blog/a%20b')).toEqual({ id: 'a b' });
33
+ });
34
+
35
+ it('captures the tail with catch-all routes', () => {
36
+ expect(matchRoute('/docs/*slug', '/docs/a/b/c')).toEqual({ slug: 'a/b/c' });
37
+ expect(matchRoute('/docs/*slug', '/docs/intro')).toEqual({ slug: 'intro' });
38
+ expect(matchRoute('/files/*path', '/files/a%20b/c')).toEqual({ path: 'a b/c' });
39
+ // catch-all needs at least one trailing segment
40
+ expect(matchRoute('/docs/*slug', '/docs')).toBeNull();
41
+ });
42
+ });
@@ -0,0 +1,7 @@
1
+ import { add } from '../../src/server';
2
+
3
+ describe('server', () => {
4
+ it('adds two integers', () => {
5
+ expect<i32>(add(1, 2)).toBe(3);
6
+ });
7
+ });
@@ -0,0 +1,30 @@
1
+ {
2
+ "entries": ["src/server/main.ts"],
3
+ "targets": {
4
+ "release": {
5
+ "outFile": "build/server/release.wasm",
6
+ "textFile": "build/server/release.wat"
7
+ }
8
+ },
9
+ "options": {
10
+ "sourceMap": false,
11
+ "optimizeLevel": 3,
12
+ "shrinkLevel": 1,
13
+ "converge": true,
14
+ "noAssert": false,
15
+ "enable": [
16
+ "sign-extension",
17
+ "mutable-globals",
18
+ "nontrapping-f2i",
19
+ "bulk-memory",
20
+ "simd",
21
+ "reference-types",
22
+ "multi-value"
23
+ ],
24
+ "runtime": "stub",
25
+ "memoryBase": 0,
26
+ "initialMemory": 1,
27
+ "debug": false,
28
+ "trapMode": "allow"
29
+ }
30
+ }
@@ -0,0 +1,13 @@
1
+ {
2
+ "extends": "./tsconfig.base.json",
3
+ "compilerOptions": {
4
+ "module": "ESNext",
5
+ "target": "ESNext",
6
+ "moduleResolution": "bundler",
7
+ "rootDir": "src/backend",
8
+ "outDir": "build/backend",
9
+ "types": ["node"],
10
+ "tsBuildInfoFile": "build/backend/.tsbuildinfo"
11
+ },
12
+ "include": ["src/backend/**/*"]
13
+ }
@@ -0,0 +1,35 @@
1
+ {
2
+ "compilerOptions": {
3
+ "declaration": true,
4
+ "noImplicitAny": true,
5
+ "removeComments": true,
6
+ "suppressImplicitAnyIndexErrors": false,
7
+ "preserveConstEnums": true,
8
+ "resolveJsonModule": true,
9
+ "skipLibCheck": true,
10
+ "sourceMap": false,
11
+ "moduleDetection": "force",
12
+ "experimentalDecorators": true,
13
+ "lib": [
14
+ "ESNext",
15
+ "DOM",
16
+ "DOM.Iterable",
17
+ "DOM.AsyncIterable",
18
+ "WebWorker",
19
+ "WebWorker.AsyncIterable",
20
+ "WebWorker.ImportScripts"
21
+ ],
22
+ "strict": true,
23
+ "strictNullChecks": true,
24
+ "strictFunctionTypes": true,
25
+ "strictBindCallApply": true,
26
+ "strictPropertyInitialization": true,
27
+ "alwaysStrict": true,
28
+ "moduleResolution": "bundler",
29
+ "allowJs": true,
30
+ "incremental": true,
31
+ "allowSyntheticDefaultImports": true,
32
+ "esModuleInterop": true
33
+ },
34
+ "include": ["src/**/*.ts", "src/*", "src/**/*.js", "src/*.ts", "src/*.js", "src/*.cjs"]
35
+ }
@@ -0,0 +1,13 @@
1
+ {
2
+ "extends": "./tsconfig.base.json",
3
+ "compilerOptions": {
4
+ "module": "ESNext",
5
+ "target": "ESNext",
6
+ "moduleResolution": "bundler",
7
+ "rootDir": "src/cli",
8
+ "outDir": "build/cli",
9
+ "types": ["node"],
10
+ "tsBuildInfoFile": "build/cli/.tsbuildinfo"
11
+ },
12
+ "include": ["src/cli/**/*"]
13
+ }
@@ -0,0 +1,14 @@
1
+ {
2
+ "extends": "./tsconfig.base.json",
3
+ "compilerOptions": {
4
+ "module": "ESNext",
5
+ "target": "ESNext",
6
+ "moduleResolution": "bundler",
7
+ "jsx": "react-jsx",
8
+ "lib": ["ESNext", "DOM", "DOM.Iterable"],
9
+ "rootDir": "src/client",
10
+ "outDir": "build/client",
11
+ "tsBuildInfoFile": "build/client/.tsbuildinfo"
12
+ },
13
+ "include": ["src/client/**/*"]
14
+ }
@@ -0,0 +1,13 @@
1
+ {
2
+ "extends": "./tsconfig.base.json",
3
+ "compilerOptions": {
4
+ "module": "ESNext",
5
+ "target": "ESNext",
6
+ "moduleResolution": "bundler",
7
+ "rootDir": "src/compiler",
8
+ "outDir": "build/compiler",
9
+ "types": ["node"],
10
+ "tsBuildInfoFile": "build/compiler/.tsbuildinfo"
11
+ },
12
+ "include": ["src/compiler/**/*"]
13
+ }
@@ -0,0 +1,12 @@
1
+ {
2
+ "extends": "./tsconfig.base.json",
3
+ "compilerOptions": {
4
+ "module": "ESNext",
5
+ "target": "ESNext",
6
+ "moduleResolution": "bundler",
7
+ "rootDir": "src/io",
8
+ "outDir": "build/io",
9
+ "tsBuildInfoFile": "build/io/.tsbuildinfo"
10
+ },
11
+ "include": ["src/io/**/*"]
12
+ }
package/tsconfig.json ADDED
@@ -0,0 +1,22 @@
1
+ {
2
+ "extends": "./tsconfig.base.json",
3
+ "compilerOptions": {
4
+ "module": "ESNext",
5
+ "target": "ESNext",
6
+ "moduleResolution": "bundler",
7
+ "jsx": "react-jsx",
8
+ "noEmit": true,
9
+ "incremental": false
10
+ },
11
+ "include": [
12
+ "src/**/*.ts",
13
+ "src/**/*.tsx",
14
+ "test/**/*.ts",
15
+ "std/client/index.d.ts"
16
+ ],
17
+ "exclude": [
18
+ "node_modules",
19
+ "build",
20
+ "src/server"
21
+ ]
22
+ }
@@ -0,0 +1,12 @@
1
+ {
2
+ "extends": "./tsconfig.base.json",
3
+ "compilerOptions": {
4
+ "module": "ESNext",
5
+ "target": "ESNext",
6
+ "moduleResolution": "bundler",
7
+ "rootDir": "src/logger",
8
+ "outDir": "build/logger",
9
+ "tsBuildInfoFile": "build/logger/.tsbuildinfo"
10
+ },
11
+ "include": ["src/logger/**/*"]
12
+ }
@@ -0,0 +1,10 @@
1
+ {
2
+ "extends": "toilscript/std/assembly.json",
3
+ "compilerOptions": {
4
+ "experimentalDecorators": true,
5
+ "noEmit": true
6
+ },
7
+ "include": [
8
+ "src/server/**/*.ts"
9
+ ]
10
+ }
@@ -0,0 +1,12 @@
1
+ {
2
+ "extends": "./tsconfig.base.json",
3
+ "compilerOptions": {
4
+ "module": "ESNext",
5
+ "target": "ESNext",
6
+ "moduleResolution": "bundler",
7
+ "rootDir": "src/shared",
8
+ "outDir": "build/shared",
9
+ "tsBuildInfoFile": "build/shared/.tsbuildinfo"
10
+ },
11
+ "include": ["src/shared/**/*"]
12
+ }
@@ -0,0 +1,22 @@
1
+ import { defineConfig } from 'vitest/config';
2
+
3
+ export default defineConfig({
4
+ test: {
5
+ globals: true,
6
+ environment: 'node',
7
+ include: ['test/**/*.test.ts', 'test/**/*.spec.ts'],
8
+ coverage: {
9
+ provider: 'v8',
10
+ reporter: ['text', 'json', 'html'],
11
+ exclude: [
12
+ 'node_modules/',
13
+ 'build/',
14
+ 'browser/',
15
+ 'test/',
16
+ '**/*.d.ts',
17
+ '**/*.config.*',
18
+ '**/mockData',
19
+ ],
20
+ },
21
+ },
22
+ });