@forthix/forthic 0.7.0 → 0.7.2

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 (95) hide show
  1. package/dist/cjs/common/type_utils.js.map +1 -1
  2. package/dist/cjs/forthic/interpreter.d.ts +2 -1
  3. package/dist/cjs/forthic/interpreter.js +10 -0
  4. package/dist/cjs/forthic/interpreter.js.map +1 -1
  5. package/dist/cjs/forthic/literals.d.ts +0 -1
  6. package/dist/cjs/forthic/literals.js +14 -15
  7. package/dist/cjs/forthic/literals.js.map +1 -1
  8. package/dist/cjs/forthic/modules/standard/datetime_module.d.ts +0 -1
  9. package/dist/cjs/forthic/modules/standard/datetime_module.js +19 -20
  10. package/dist/cjs/forthic/modules/standard/datetime_module.js.map +1 -1
  11. package/dist/cjs/forthic/utils.d.ts +0 -1
  12. package/dist/cjs/forthic/utils.js +1 -2
  13. package/dist/cjs/forthic/utils.js.map +1 -1
  14. package/dist/cjs/grpc/serializer.js +3 -4
  15. package/dist/cjs/grpc/serializer.js.map +1 -1
  16. package/dist/cjs/grpc/server.test.d.ts +1 -0
  17. package/dist/cjs/grpc/server.test.js +156 -0
  18. package/dist/cjs/grpc/server.test.js.map +1 -0
  19. package/dist/cjs/grpc/temporal_utils.d.ts +36 -0
  20. package/dist/cjs/grpc/temporal_utils.js +80 -0
  21. package/dist/cjs/grpc/temporal_utils.js.map +1 -0
  22. package/dist/cjs/test-setup.d.ts +1 -0
  23. package/dist/cjs/test-setup.js +4 -0
  24. package/dist/cjs/test-setup.js.map +1 -0
  25. package/dist/cjs/websocket/action_cable_client.d.ts +106 -0
  26. package/dist/cjs/websocket/action_cable_client.js +269 -0
  27. package/dist/cjs/websocket/action_cable_client.js.map +1 -0
  28. package/dist/cjs/websocket/client.d.ts +103 -0
  29. package/dist/cjs/websocket/client.js +266 -0
  30. package/dist/cjs/websocket/client.js.map +1 -0
  31. package/dist/cjs/websocket/remote_module.d.ts +68 -0
  32. package/dist/cjs/websocket/remote_module.js +107 -0
  33. package/dist/cjs/websocket/remote_module.js.map +1 -0
  34. package/dist/cjs/websocket/remote_word.d.ts +53 -0
  35. package/dist/cjs/websocket/remote_word.js +93 -0
  36. package/dist/cjs/websocket/remote_word.js.map +1 -0
  37. package/dist/cjs/websocket/runtime_manager.d.ts +69 -0
  38. package/dist/cjs/websocket/runtime_manager.js +112 -0
  39. package/dist/cjs/websocket/runtime_manager.js.map +1 -0
  40. package/dist/cjs/websocket/serializer.js +3 -4
  41. package/dist/cjs/websocket/serializer.js.map +1 -1
  42. package/dist/esm/common/type_utils.js.map +1 -1
  43. package/dist/esm/forthic/interpreter.d.ts +2 -1
  44. package/dist/esm/forthic/interpreter.js +11 -1
  45. package/dist/esm/forthic/interpreter.js.map +1 -1
  46. package/dist/esm/forthic/literals.d.ts +0 -1
  47. package/dist/esm/forthic/literals.js +0 -1
  48. package/dist/esm/forthic/literals.js.map +1 -1
  49. package/dist/esm/forthic/modules/standard/datetime_module.d.ts +0 -1
  50. package/dist/esm/forthic/modules/standard/datetime_module.js +0 -1
  51. package/dist/esm/forthic/modules/standard/datetime_module.js.map +1 -1
  52. package/dist/esm/forthic/utils.d.ts +0 -1
  53. package/dist/esm/forthic/utils.js +0 -1
  54. package/dist/esm/forthic/utils.js.map +1 -1
  55. package/dist/esm/grpc/serializer.js +0 -1
  56. package/dist/esm/grpc/serializer.js.map +1 -1
  57. package/dist/esm/grpc/server.test.d.ts +1 -0
  58. package/dist/esm/grpc/server.test.js +121 -0
  59. package/dist/esm/grpc/server.test.js.map +1 -0
  60. package/dist/esm/grpc/temporal_utils.d.ts +36 -0
  61. package/dist/esm/grpc/temporal_utils.js +72 -0
  62. package/dist/esm/grpc/temporal_utils.js.map +1 -0
  63. package/dist/esm/test-setup.d.ts +1 -0
  64. package/dist/esm/test-setup.js +2 -0
  65. package/dist/esm/test-setup.js.map +1 -0
  66. package/dist/esm/websocket/action_cable_client.d.ts +106 -0
  67. package/dist/esm/websocket/action_cable_client.js +265 -0
  68. package/dist/esm/websocket/action_cable_client.js.map +1 -0
  69. package/dist/esm/websocket/client.d.ts +103 -0
  70. package/dist/esm/websocket/client.js +262 -0
  71. package/dist/esm/websocket/client.js.map +1 -0
  72. package/dist/esm/websocket/remote_module.d.ts +68 -0
  73. package/dist/esm/websocket/remote_module.js +103 -0
  74. package/dist/esm/websocket/remote_module.js.map +1 -0
  75. package/dist/esm/websocket/remote_word.d.ts +53 -0
  76. package/dist/esm/websocket/remote_word.js +89 -0
  77. package/dist/esm/websocket/remote_word.js.map +1 -0
  78. package/dist/esm/websocket/runtime_manager.d.ts +69 -0
  79. package/dist/esm/websocket/runtime_manager.js +108 -0
  80. package/dist/esm/websocket/runtime_manager.js.map +1 -0
  81. package/dist/esm/websocket/serializer.js +0 -1
  82. package/dist/esm/websocket/serializer.js.map +1 -1
  83. package/package.json +3 -2
  84. package/dist/cjs/forthic/decorators/schemaUtils.d.ts +0 -70
  85. package/dist/cjs/forthic/decorators/schemaUtils.js +0 -77
  86. package/dist/cjs/forthic/decorators/schemaUtils.js.map +0 -1
  87. package/dist/cjs/forthic/decorators/stackEffect.d.ts +0 -63
  88. package/dist/cjs/forthic/decorators/stackEffect.js +0 -179
  89. package/dist/cjs/forthic/decorators/stackEffect.js.map +0 -1
  90. package/dist/esm/forthic/decorators/schemaUtils.d.ts +0 -70
  91. package/dist/esm/forthic/decorators/schemaUtils.js +0 -72
  92. package/dist/esm/forthic/decorators/schemaUtils.js.map +0 -1
  93. package/dist/esm/forthic/decorators/stackEffect.d.ts +0 -63
  94. package/dist/esm/forthic/decorators/stackEffect.js +0 -174
  95. package/dist/esm/forthic/decorators/stackEffect.js.map +0 -1
@@ -0,0 +1,89 @@
1
+ /**
2
+ * WebSocketRemoteWord - Word that executes in a remote runtime via ActionCable
3
+ * Mirrors RemoteWord from gRPC implementation
4
+ */
5
+ import { Word } from '../forthic/module.js';
6
+ /**
7
+ * WebSocketRemoteWord - Proxy word that delegates execution to a remote runtime
8
+ *
9
+ * When executed:
10
+ * 1. Captures current interpreter stack
11
+ * 2. Sends word name + stack to remote runtime via ActionCable
12
+ * 3. Replaces local stack with result stack from remote execution
13
+ *
14
+ * This allows seamless integration of remote runtime words
15
+ * into the local TypeScript interpreter.
16
+ */
17
+ export class WebSocketRemoteWord extends Word {
18
+ client;
19
+ runtimeName;
20
+ moduleName;
21
+ stackEffect;
22
+ description;
23
+ /**
24
+ * @param name - Word name (e.g., "DF_FROM_RECORDS")
25
+ * @param client - ActionCable client connected to remote runtime
26
+ * @param runtimeName - Name of remote runtime (e.g., "rails", "ruby")
27
+ * @param moduleName - Module name (e.g., "pandas")
28
+ * @param stackEffect - Stack notation (e.g., "( records:array -- df:DataFrame )")
29
+ * @param description - Human-readable description
30
+ */
31
+ constructor(name, client, runtimeName, moduleName, stackEffect = '( -- )', description = '') {
32
+ super(name);
33
+ this.client = client;
34
+ this.runtimeName = runtimeName;
35
+ this.moduleName = moduleName;
36
+ this.stackEffect = stackEffect;
37
+ this.description = description;
38
+ }
39
+ /**
40
+ * Execute word in remote runtime
41
+ *
42
+ * Captures entire stack, sends to remote runtime, and replaces stack with result.
43
+ */
44
+ async execute(interp) {
45
+ try {
46
+ // Capture current stack state
47
+ const stack = interp.get_stack();
48
+ const stackItems = stack.get_items();
49
+ // Execute word in remote runtime
50
+ const resultStack = await this.client.executeWord(this.name, stackItems);
51
+ // Clear local stack and replace with result
52
+ while (interp.get_stack().length > 0) {
53
+ interp.stack_pop();
54
+ }
55
+ // Push all result items
56
+ for (const item of resultStack) {
57
+ interp.stack_push(item);
58
+ }
59
+ }
60
+ catch (error) {
61
+ throw new Error(`Error executing remote word ${this.moduleName}.${this.name} in ${this.runtimeName} runtime: ${error.message}`);
62
+ }
63
+ }
64
+ /**
65
+ * Get runtime name for debugging/introspection
66
+ */
67
+ getRuntimeName() {
68
+ return this.runtimeName;
69
+ }
70
+ /**
71
+ * Get module name for debugging/introspection
72
+ */
73
+ getModuleName() {
74
+ return this.moduleName;
75
+ }
76
+ /**
77
+ * Get runtime execution information
78
+ * RemoteWords are runtime-specific and can only execute in their designated runtime
79
+ */
80
+ getRuntimeInfo() {
81
+ return {
82
+ runtime: this.runtimeName,
83
+ isRemote: true,
84
+ isStandard: false,
85
+ availableIn: [this.runtimeName]
86
+ };
87
+ }
88
+ }
89
+ //# sourceMappingURL=remote_word.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"remote_word.js","sourceRoot":"","sources":["../../../src/websocket/remote_word.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,OAAO,EAAE,IAAI,EAAe,MAAM,sBAAsB,CAAC;AAIzD;;;;;;;;;;GAUG;AACH,MAAM,OAAO,mBAAoB,SAAQ,IAAI;IACnC,MAAM,CAAoB;IAC1B,WAAW,CAAS;IACpB,UAAU,CAAS;IACpB,WAAW,CAAS;IACpB,WAAW,CAAS;IAE3B;;;;;;;OAOG;IACH,YACE,IAAY,EACZ,MAAyB,EACzB,WAAmB,EACnB,UAAkB,EAClB,cAAsB,QAAQ,EAC9B,cAAsB,EAAE;QAExB,KAAK,CAAC,IAAI,CAAC,CAAC;QACZ,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC;QACrB,IAAI,CAAC,WAAW,GAAG,WAAW,CAAC;QAC/B,IAAI,CAAC,UAAU,GAAG,UAAU,CAAC;QAC7B,IAAI,CAAC,WAAW,GAAG,WAAW,CAAC;QAC/B,IAAI,CAAC,WAAW,GAAG,WAAW,CAAC;IACjC,CAAC;IAED;;;;OAIG;IACH,KAAK,CAAC,OAAO,CAAC,MAAmB;QAC/B,IAAI,CAAC;YACH,8BAA8B;YAC9B,MAAM,KAAK,GAAG,MAAM,CAAC,SAAS,EAAE,CAAC;YACjC,MAAM,UAAU,GAAG,KAAK,CAAC,SAAS,EAAE,CAAC;YAErC,iCAAiC;YACjC,MAAM,WAAW,GAAG,MAAM,IAAI,CAAC,MAAM,CAAC,WAAW,CAAC,IAAI,CAAC,IAAI,EAAE,UAAU,CAAC,CAAC;YAEzE,4CAA4C;YAC5C,OAAO,MAAM,CAAC,SAAS,EAAE,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;gBACrC,MAAM,CAAC,SAAS,EAAE,CAAC;YACrB,CAAC;YAED,wBAAwB;YACxB,KAAK,MAAM,IAAI,IAAI,WAAW,EAAE,CAAC;gBAC/B,MAAM,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC;YAC1B,CAAC;QACH,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,MAAM,IAAI,KAAK,CACb,+BAA+B,IAAI,CAAC,UAAU,IAAI,IAAI,CAAC,IAAI,OAAO,IAAI,CAAC,WAAW,aAAc,KAAe,CAAC,OAAO,EAAE,CAC1H,CAAC;QACJ,CAAC;IACH,CAAC;IAED;;OAEG;IACH,cAAc;QACZ,OAAO,IAAI,CAAC,WAAW,CAAC;IAC1B,CAAC;IAED;;OAEG;IACH,aAAa;QACX,OAAO,IAAI,CAAC,UAAU,CAAC;IACzB,CAAC;IAED;;;OAGG;IACH,cAAc;QACZ,OAAO;YACL,OAAO,EAAE,IAAI,CAAC,WAAW;YACzB,QAAQ,EAAE,IAAI;YACd,UAAU,EAAE,KAAK;YACjB,WAAW,EAAE,CAAC,IAAI,CAAC,WAAW,CAAC;SAChC,CAAC;IACJ,CAAC;CACF"}
@@ -0,0 +1,69 @@
1
+ /**
2
+ * WebSocketRuntimeManager - Singleton for managing ActionCable connections to remote runtimes
3
+ *
4
+ * Provides centralized access to ActionCable clients for different runtimes
5
+ * Mirrors the gRPC RuntimeManager API for compatibility
6
+ */
7
+ import { ActionCableClient, ActionCableClientConfig } from './action_cable_client.js';
8
+ /**
9
+ * WebSocketRuntimeManager - Manages ActionCable connections to remote Forthic runtimes
10
+ */
11
+ export declare class WebSocketRuntimeManager {
12
+ private static instance;
13
+ private clients;
14
+ private constructor();
15
+ /**
16
+ * Get the singleton instance
17
+ */
18
+ static getInstance(): WebSocketRuntimeManager;
19
+ /**
20
+ * Connect to a runtime and register the client
21
+ *
22
+ * @param runtimeName - Name of the runtime (e.g., "rails", "ruby")
23
+ * @param url - ActionCable URL (e.g., "ws://localhost:3000/cable")
24
+ * @param config - Optional additional configuration
25
+ * @returns ActionCableClient instance
26
+ */
27
+ connectRuntime(runtimeName: string, url: string, config?: Partial<ActionCableClientConfig>): ActionCableClient;
28
+ /**
29
+ * Register an ActionCable client for a specific runtime
30
+ *
31
+ * @param runtimeName - Name of the runtime (e.g., "rails", "ruby")
32
+ * @param client - ActionCableClient instance connected to that runtime
33
+ */
34
+ registerClient(runtimeName: string, client: ActionCableClient): void;
35
+ /**
36
+ * Get the ActionCable client for a specific runtime
37
+ *
38
+ * @param runtimeName - Name of the runtime
39
+ * @returns ActionCableClient instance or undefined if not registered
40
+ */
41
+ getClient(runtimeName: string): ActionCableClient | undefined;
42
+ /**
43
+ * Check if a runtime has a registered client
44
+ *
45
+ * @param runtimeName - Name of the runtime
46
+ * @returns True if client is registered
47
+ */
48
+ hasClient(runtimeName: string): boolean;
49
+ /**
50
+ * Get all registered runtime names
51
+ *
52
+ * @returns Array of runtime names
53
+ */
54
+ getRegisteredRuntimes(): string[];
55
+ /**
56
+ * Disconnect a specific runtime
57
+ *
58
+ * @param runtimeName - Name of the runtime to disconnect
59
+ */
60
+ disconnectRuntime(runtimeName: string): void;
61
+ /**
62
+ * Clear all registered clients (useful for testing)
63
+ */
64
+ clearAll(): void;
65
+ /**
66
+ * Reset the singleton (useful for testing)
67
+ */
68
+ static reset(): void;
69
+ }
@@ -0,0 +1,108 @@
1
+ /**
2
+ * WebSocketRuntimeManager - Singleton for managing ActionCable connections to remote runtimes
3
+ *
4
+ * Provides centralized access to ActionCable clients for different runtimes
5
+ * Mirrors the gRPC RuntimeManager API for compatibility
6
+ */
7
+ import { ActionCableClient } from './action_cable_client.js';
8
+ /**
9
+ * WebSocketRuntimeManager - Manages ActionCable connections to remote Forthic runtimes
10
+ */
11
+ export class WebSocketRuntimeManager {
12
+ static instance = null;
13
+ clients;
14
+ constructor() {
15
+ this.clients = new Map();
16
+ }
17
+ /**
18
+ * Get the singleton instance
19
+ */
20
+ static getInstance() {
21
+ if (!WebSocketRuntimeManager.instance) {
22
+ WebSocketRuntimeManager.instance = new WebSocketRuntimeManager();
23
+ }
24
+ return WebSocketRuntimeManager.instance;
25
+ }
26
+ /**
27
+ * Connect to a runtime and register the client
28
+ *
29
+ * @param runtimeName - Name of the runtime (e.g., "rails", "ruby")
30
+ * @param url - ActionCable URL (e.g., "ws://localhost:3000/cable")
31
+ * @param config - Optional additional configuration
32
+ * @returns ActionCableClient instance
33
+ */
34
+ connectRuntime(runtimeName, url, config) {
35
+ // Create a new client for the runtime
36
+ const client = new ActionCableClient({ url, ...config });
37
+ // Register it
38
+ this.clients.set(runtimeName, client);
39
+ return client;
40
+ }
41
+ /**
42
+ * Register an ActionCable client for a specific runtime
43
+ *
44
+ * @param runtimeName - Name of the runtime (e.g., "rails", "ruby")
45
+ * @param client - ActionCableClient instance connected to that runtime
46
+ */
47
+ registerClient(runtimeName, client) {
48
+ this.clients.set(runtimeName, client);
49
+ }
50
+ /**
51
+ * Get the ActionCable client for a specific runtime
52
+ *
53
+ * @param runtimeName - Name of the runtime
54
+ * @returns ActionCableClient instance or undefined if not registered
55
+ */
56
+ getClient(runtimeName) {
57
+ return this.clients.get(runtimeName);
58
+ }
59
+ /**
60
+ * Check if a runtime has a registered client
61
+ *
62
+ * @param runtimeName - Name of the runtime
63
+ * @returns True if client is registered
64
+ */
65
+ hasClient(runtimeName) {
66
+ return this.clients.has(runtimeName);
67
+ }
68
+ /**
69
+ * Get all registered runtime names
70
+ *
71
+ * @returns Array of runtime names
72
+ */
73
+ getRegisteredRuntimes() {
74
+ return Array.from(this.clients.keys());
75
+ }
76
+ /**
77
+ * Disconnect a specific runtime
78
+ *
79
+ * @param runtimeName - Name of the runtime to disconnect
80
+ */
81
+ disconnectRuntime(runtimeName) {
82
+ const client = this.clients.get(runtimeName);
83
+ if (client) {
84
+ client.close();
85
+ this.clients.delete(runtimeName);
86
+ }
87
+ }
88
+ /**
89
+ * Clear all registered clients (useful for testing)
90
+ */
91
+ clearAll() {
92
+ // Close all clients
93
+ for (const client of this.clients.values()) {
94
+ client.close();
95
+ }
96
+ this.clients.clear();
97
+ }
98
+ /**
99
+ * Reset the singleton (useful for testing)
100
+ */
101
+ static reset() {
102
+ if (WebSocketRuntimeManager.instance) {
103
+ WebSocketRuntimeManager.instance.clearAll();
104
+ WebSocketRuntimeManager.instance = null;
105
+ }
106
+ }
107
+ }
108
+ //# sourceMappingURL=runtime_manager.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"runtime_manager.js","sourceRoot":"","sources":["../../../src/websocket/runtime_manager.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,OAAO,EAAE,iBAAiB,EAA2B,MAAM,0BAA0B,CAAC;AAEtF;;GAEG;AACH,MAAM,OAAO,uBAAuB;IAC1B,MAAM,CAAC,QAAQ,GAAmC,IAAI,CAAC;IACvD,OAAO,CAAiC;IAEhD;QACE,IAAI,CAAC,OAAO,GAAG,IAAI,GAAG,EAAE,CAAC;IAC3B,CAAC;IAED;;OAEG;IACH,MAAM,CAAC,WAAW;QAChB,IAAI,CAAC,uBAAuB,CAAC,QAAQ,EAAE,CAAC;YACtC,uBAAuB,CAAC,QAAQ,GAAG,IAAI,uBAAuB,EAAE,CAAC;QACnE,CAAC;QACD,OAAO,uBAAuB,CAAC,QAAQ,CAAC;IAC1C,CAAC;IAED;;;;;;;OAOG;IACH,cAAc,CACZ,WAAmB,EACnB,GAAW,EACX,MAAyC;QAEzC,sCAAsC;QACtC,MAAM,MAAM,GAAG,IAAI,iBAAiB,CAAC,EAAE,GAAG,EAAE,GAAG,MAAM,EAAE,CAAC,CAAC;QAEzD,cAAc;QACd,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,WAAW,EAAE,MAAM,CAAC,CAAC;QAEtC,OAAO,MAAM,CAAC;IAChB,CAAC;IAED;;;;;OAKG;IACH,cAAc,CAAC,WAAmB,EAAE,MAAyB;QAC3D,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,WAAW,EAAE,MAAM,CAAC,CAAC;IACxC,CAAC;IAED;;;;;OAKG;IACH,SAAS,CAAC,WAAmB;QAC3B,OAAO,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,WAAW,CAAC,CAAC;IACvC,CAAC;IAED;;;;;OAKG;IACH,SAAS,CAAC,WAAmB;QAC3B,OAAO,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,WAAW,CAAC,CAAC;IACvC,CAAC;IAED;;;;OAIG;IACH,qBAAqB;QACnB,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,IAAI,EAAE,CAAC,CAAC;IACzC,CAAC;IAED;;;;OAIG;IACH,iBAAiB,CAAC,WAAmB;QACnC,MAAM,MAAM,GAAG,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,WAAW,CAAC,CAAC;QAC7C,IAAI,MAAM,EAAE,CAAC;YACX,MAAM,CAAC,KAAK,EAAE,CAAC;YACf,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,WAAW,CAAC,CAAC;QACnC,CAAC;IACH,CAAC;IAED;;OAEG;IACH,QAAQ;QACN,oBAAoB;QACpB,KAAK,MAAM,MAAM,IAAI,IAAI,CAAC,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC;YAC3C,MAAM,CAAC,KAAK,EAAE,CAAC;QACjB,CAAC;QACD,IAAI,CAAC,OAAO,CAAC,KAAK,EAAE,CAAC;IACvB,CAAC;IAED;;OAEG;IACH,MAAM,CAAC,KAAK;QACV,IAAI,uBAAuB,CAAC,QAAQ,EAAE,CAAC;YACrC,uBAAuB,CAAC,QAAQ,CAAC,QAAQ,EAAE,CAAC;YAC5C,uBAAuB,CAAC,QAAQ,GAAG,IAAI,CAAC;QAC1C,CAAC;IACH,CAAC"}
@@ -4,7 +4,6 @@
4
4
  * Handles: int, float, string, bool, null, array, record, temporal types
5
5
  * Uses shared type detection from common/type_utils
6
6
  */
7
- import { Temporal } from "temporal-polyfill";
8
7
  import { getForthicType } from "../common/type_utils.js";
9
8
  /**
10
9
  * Serialize a JavaScript value to a JSON StackValue
@@ -1 +1 @@
1
- {"version":3,"file":"serializer.js","sourceRoot":"","sources":["../../../src/websocket/serializer.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"serializer.js","sourceRoot":"","sources":["../../../src/websocket/serializer.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@forthix/forthic",
3
- "version": "0.7.0",
3
+ "version": "0.7.2",
4
4
  "description": "Stack-based, concatenative language for composable transformations - TypeScript/JavaScript runtime",
5
5
  "main": "dist/cjs/index.js",
6
6
  "module": "dist/esm/index.js",
@@ -81,7 +81,6 @@
81
81
  },
82
82
  "homepage": "https://github.com/forthix/forthic-ts#readme",
83
83
  "dependencies": {
84
- "temporal-polyfill": "^0.3.0",
85
84
  "yaml": "^2.8.1"
86
85
  },
87
86
  "optionalDependencies": {
@@ -104,6 +103,8 @@
104
103
  "ts-node": "^10.9.0",
105
104
  "tsx": "^4.20.6",
106
105
  "typescript": "^5.7.2",
106
+ "temporal-polyfill": "^0.3.0",
107
+ "temporal-spec": "^0.3.0",
107
108
  "typescript-eslint": "^8.45.0"
108
109
  },
109
110
  "browserslist": {
@@ -1,70 +0,0 @@
1
- import { z } from "zod";
2
- /**
3
- * Registry metadata types for stack objects and class instances.
4
- */
5
- type StackObjectMetadata = {
6
- objectType: "stackObject";
7
- stackObjectType: string;
8
- className?: undefined;
9
- OriginalClass?: undefined;
10
- } | {
11
- objectType: "class";
12
- OriginalClass: new (...args: any[]) => any;
13
- className: string;
14
- stackObjectType?: undefined;
15
- };
16
- /**
17
- * Track metadata for schema comparison in tests and documentation.
18
- * Only required for schemas that can't be compared out of the box,
19
- * like custom schemas or instanceof schemas.
20
- */
21
- export declare const stackObjectRegistry: z.core.$ZodRegistry<StackObjectMetadata, z.core.$ZodType<unknown, unknown, z.core.$ZodTypeInternals<unknown, unknown>>>;
22
- /**
23
- * Creates a Zod schema for stack objects that have a stackObjectType property.
24
- * This is a helper to reduce boilerplate when creating custom stack object schemas.
25
- * It also ensures the schema is registered in stackObjectRegistry, which enables
26
- * proper type string generation in stack effects.
27
- *
28
- * Use this instead of z.custom() directly for stack objects.
29
- *
30
- * @example
31
- * ```ts
32
- * interface StackEmail {
33
- * stackObjectType: "email";
34
- * to: string;
35
- * subject: string;
36
- * body: string;
37
- * }
38
- *
39
- * const stackEmailSchema = createStackObjectSchema<StackEmail>("email");
40
- *
41
- * // Use in stack effect:
42
- * @ForthicWord(se`(email:${stackEmailSchema} -- sent:${z.boolean()})`, "Send email")
43
- * async SEND(email: StackEmail): Promise<boolean> { ... }
44
- * ```
45
- */
46
- export declare function createStackObjectSchema<T extends {
47
- stackObjectType: string;
48
- }>(stackObjectType: string, errorMessage?: string): z.ZodCustom<T>;
49
- /**
50
- * Creates a Zod instanceof schema with automatic metadata registration.
51
- * This ensures the schema is registered in stackObjectRegistry, which enables
52
- * proper type string generation in stack effects.
53
- *
54
- * Use this instead of z.instanceof() directly.
55
- *
56
- * @example
57
- * ```ts
58
- * import { Temporal } from "temporal-polyfill";
59
- *
60
- * const plainDateSchema = createInstanceOfSchema(Temporal.PlainDate);
61
- *
62
- * // Use in stack effect:
63
- * @ForthicWord(se`(date:${plainDateSchema} -- formatted:${z.string()})`, "Format date")
64
- * async FORMAT(date: Temporal.PlainDate): Promise<string> { ... }
65
- * ```
66
- */
67
- export declare function createInstanceOfSchema<T extends abstract new (...args: any[]) => any>(ClassToSchematize: T,
68
- /** If not passed, falls back to class.name */
69
- className?: string): z.ZodType<InstanceType<T>>;
70
- export {};
@@ -1,77 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.stackObjectRegistry = void 0;
4
- exports.createStackObjectSchema = createStackObjectSchema;
5
- exports.createInstanceOfSchema = createInstanceOfSchema;
6
- const zod_1 = require("zod");
7
- /**
8
- * Track metadata for schema comparison in tests and documentation.
9
- * Only required for schemas that can't be compared out of the box,
10
- * like custom schemas or instanceof schemas.
11
- */
12
- exports.stackObjectRegistry = zod_1.z.registry();
13
- /**
14
- * Creates a Zod schema for stack objects that have a stackObjectType property.
15
- * This is a helper to reduce boilerplate when creating custom stack object schemas.
16
- * It also ensures the schema is registered in stackObjectRegistry, which enables
17
- * proper type string generation in stack effects.
18
- *
19
- * Use this instead of z.custom() directly for stack objects.
20
- *
21
- * @example
22
- * ```ts
23
- * interface StackEmail {
24
- * stackObjectType: "email";
25
- * to: string;
26
- * subject: string;
27
- * body: string;
28
- * }
29
- *
30
- * const stackEmailSchema = createStackObjectSchema<StackEmail>("email");
31
- *
32
- * // Use in stack effect:
33
- * @ForthicWord(se`(email:${stackEmailSchema} -- sent:${z.boolean()})`, "Send email")
34
- * async SEND(email: StackEmail): Promise<boolean> { ... }
35
- * ```
36
- */
37
- function createStackObjectSchema(stackObjectType, errorMessage) {
38
- const schema = zod_1.z.custom((maybeStackObject) => maybeStackObject?.stackObjectType === stackObjectType, errorMessage ?? `expected ${stackObjectType} stackObjectType`);
39
- // Register schema with metadata
40
- exports.stackObjectRegistry.add(schema, {
41
- objectType: "stackObject",
42
- stackObjectType,
43
- });
44
- return schema;
45
- }
46
- /**
47
- * Creates a Zod instanceof schema with automatic metadata registration.
48
- * This ensures the schema is registered in stackObjectRegistry, which enables
49
- * proper type string generation in stack effects.
50
- *
51
- * Use this instead of z.instanceof() directly.
52
- *
53
- * @example
54
- * ```ts
55
- * import { Temporal } from "temporal-polyfill";
56
- *
57
- * const plainDateSchema = createInstanceOfSchema(Temporal.PlainDate);
58
- *
59
- * // Use in stack effect:
60
- * @ForthicWord(se`(date:${plainDateSchema} -- formatted:${z.string()})`, "Format date")
61
- * async FORMAT(date: Temporal.PlainDate): Promise<string> { ... }
62
- * ```
63
- */
64
- function createInstanceOfSchema(ClassToSchematize,
65
- /** If not passed, falls back to class.name */
66
- className) {
67
- const schema = zod_1.z.instanceof(ClassToSchematize);
68
- // Register schema with metadata
69
- const resolvedClassName = className ?? ClassToSchematize.name;
70
- exports.stackObjectRegistry.add(schema, {
71
- objectType: "class",
72
- OriginalClass: ClassToSchematize,
73
- className: resolvedClassName,
74
- });
75
- return schema;
76
- }
77
- //# sourceMappingURL=schemaUtils.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"schemaUtils.js","sourceRoot":"","sources":["../../../../src/forthic/decorators/schemaUtils.ts"],"names":[],"mappings":";;;AAkDA,0DAgBC;AAoBD,wDAgBC;AAtGD,6BAAwB;AAmBxB;;;;GAIG;AACU,QAAA,mBAAmB,GAAG,OAAC,CAAC,QAAQ,EAAuB,CAAC;AAErE;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,SAAgB,uBAAuB,CACrC,eAAuB,EACvB,YAAqB;IAErB,MAAM,MAAM,GAAG,OAAC,CAAC,MAAM,CACrB,CAAC,gBAAgB,EAAE,EAAE,CAAE,gBAAkC,EAAE,eAAe,KAAK,eAAe,EAC9F,YAAY,IAAI,YAAY,eAAe,kBAAkB,CAC9D,CAAC;IAEF,gCAAgC;IAChC,2BAAmB,CAAC,GAAG,CAAC,MAAM,EAAE;QAC9B,UAAU,EAAE,aAAa;QACzB,eAAe;KAChB,CAAC,CAAC;IAEH,OAAO,MAAM,CAAC;AAChB,CAAC;AAED;;;;;;;;;;;;;;;;;GAiBG;AACH,SAAgB,sBAAsB,CACpC,iBAAoB;AACpB,8CAA8C;AAC9C,SAAkB;IAElB,MAAM,MAAM,GAAG,OAAC,CAAC,UAAU,CAAC,iBAAiB,CAAC,CAAC;IAE/C,gCAAgC;IAChC,MAAM,iBAAiB,GAAG,SAAS,IAAI,iBAAiB,CAAC,IAAI,CAAC;IAC9D,2BAAmB,CAAC,GAAG,CAAC,MAAM,EAAE;QAC9B,UAAU,EAAE,OAAO;QACnB,aAAa,EAAE,iBAAiB;QAChC,SAAS,EAAE,iBAAiB;KAC7B,CAAC,CAAC;IAEH,OAAO,MAAM,CAAC;AAChB,CAAC"}
@@ -1,63 +0,0 @@
1
- import { z } from "zod";
2
- import type { util as zodUtil } from "zod/v4/core";
3
- /**
4
- * Map the set of Zod types to the strings we use in Forthic stack effects.
5
- * Uses Zod's internal def.type for comprehensive type detection.
6
- */
7
- export declare const mapZodToStackEffectType: (zodType: z.ZodTypeAny) => string;
8
- type InferTupleTypes<T extends zodUtil.TupleItems> = {
9
- [K in keyof T]: T[K] extends z.ZodTypeAny ? z.infer<T[K]> : never;
10
- };
11
- /**
12
- * Represents a type-safe stack effect with Zod schemas for validation.
13
- *
14
- * @template Args - Tuple of Zod schemas for input parameters
15
- * @template Return - Zod schema for the return type
16
- */
17
- export type TaggedStackEffect<Args extends zodUtil.TupleItems, Return extends z.core.$ZodFunctionOut = z.core.$ZodFunctionOut> = {
18
- /** The human-readable stack effect string (e.g., "( a:number b:string -- result:string )") */
19
- stackEffect: string;
20
- /** Zod schemas for runtime validation */
21
- schema: {
22
- inputSchemas: z.ZodTypeAny[];
23
- outputSchema: z.ZodTypeAny;
24
- };
25
- /**
26
- * Phantom property to convey the expected function signature, constructed from the input + output types.
27
- * DO NOT USE AT RUNTIME - it's only used for type inference.
28
- */
29
- _implType: (...args: InferTupleTypes<Args>) => Promise<z.infer<Return>>;
30
- };
31
- /**
32
- * Tagged template literal for stack effects. Use with the @ForthicWord decorator to
33
- * create a type-safe stack effect.
34
- *
35
- * @example
36
- * ```ts
37
- * // Type-safe stack effect with Zod validation
38
- * @ForthicWord(se`(a:${z.number()} b:${z.string()} -- result:${z.string()})`, "Concatenate number and string")
39
- * async CONCAT(a: number, b: string): Promise<string> {
40
- * return `${a}${b}`;
41
- * }
42
- * ```
43
- *
44
- * @example
45
- * ```ts
46
- * // No parameters, returns string
47
- * @ForthicWord(se`( -- message:${z.string()})`, "Get greeting")
48
- * async GREET(): Promise<string> {
49
- * return "Hello!";
50
- * }
51
- * ```
52
- *
53
- * @example
54
- * ```ts
55
- * // Takes string, no return (void)
56
- * @ForthicWord(se`(input:${z.string()} -- ${z.void()})`, "Log to console")
57
- * async LOG(input: string): Promise<void> {
58
- * console.log(input);
59
- * }
60
- * ```
61
- */
62
- export declare const se: <Args extends zodUtil.TupleItems, Return extends z.core.$ZodFunctionOut>(template: TemplateStringsArray, ...values: [...Args, Return]) => TaggedStackEffect<Args, Return>;
63
- export {};