@polytric/openws-sdkgen 0.0.4 → 0.0.5

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.
package/dist/main.cjs CHANGED
@@ -204,7 +204,11 @@ function buildIr(ctx) {
204
204
  description: handlerSpec.description
205
205
  });
206
206
  irNetwork.models.push(
207
- ...buildIrModels(hostRoleSpec.name, handlerName, handlerSpec.payload)
207
+ ...buildIrModels(
208
+ hostRoleSpec.name,
209
+ handlerName + "Payload",
210
+ handlerSpec.payload
211
+ )
208
212
  );
209
213
  }
210
214
  }
@@ -222,7 +226,9 @@ function buildIr(ctx) {
222
226
  handlerName,
223
227
  description: handlerSpec.description
224
228
  });
225
- irNetwork.models.push(...buildIrModels(roleName, handlerName, handlerSpec.payload));
229
+ irNetwork.models.push(
230
+ ...buildIrModels(roleName, handlerName + "Payload", handlerSpec.payload)
231
+ );
226
232
  }
227
233
  }
228
234
  ir.networks.push(irNetwork);
@@ -257,6 +263,16 @@ async function dispatchBuildPlan(ctx) {
257
263
  var import_node_path = __toESM(require("path"), 1);
258
264
  var import_node_process = __toESM(require("process"), 1);
259
265
  var import_schema2 = __toESM(require("@pocketgems/schema"), 1);
266
+
267
+ // src/utils.ts
268
+ function toCamelCase(str) {
269
+ return str.replace(/[-_\s]+/g, " ").replace(/([a-z])([A-Z])/g, "$1 $2").replace(/([A-Z]+)([A-Z][a-z])/g, "$1 $2").split(/\s+/).filter(Boolean).map((word, index) => {
270
+ const lower = word.toLowerCase();
271
+ return index === 0 ? lower : lower.charAt(0).toUpperCase() + lower.slice(1);
272
+ }).join("");
273
+ }
274
+
275
+ // src/build-request.ts
260
276
  var validateBuildRequest = import_schema2.default.obj({
261
277
  specPath: import_schema2.default.str,
262
278
  outputPath: import_schema2.default.str,
@@ -276,12 +292,11 @@ var validateBuildRequest = import_schema2.default.obj({
276
292
  function buildRequest(ctx) {
277
293
  const { rawInput } = ctx;
278
294
  if (!rawInput) throw new Error("rawInput is required");
279
- console.log("Host roles:", rawInput.hostRole);
280
295
  const request = {
281
296
  specPath: import_node_path.default.join(import_node_process.default.cwd(), rawInput.spec),
282
297
  outputPath: import_node_path.default.join(import_node_process.default.cwd(), rawInput.out),
283
298
  project: rawInput.project,
284
- hostRoles: rawInput.hostRole,
299
+ hostRoles: rawInput.hostRole.map((r) => toCamelCase(r)),
285
300
  target: {
286
301
  [rawInput.language]: {
287
302
  environment: rawInput.environment,
@@ -341,6 +356,27 @@ function loadSpec(ctx) {
341
356
  if (!request) throw new Error("request is required");
342
357
  const { specPath } = request;
343
358
  const spec = JSON.parse(import_node_fs2.default.readFileSync(specPath, "utf8"));
359
+ spec.name = toCamelCase(spec.name);
360
+ for (const [networkName, networkSpec] of Object.entries(spec.networks)) {
361
+ for (const [roleName, roleSpec] of Object.entries(networkSpec.roles)) {
362
+ for (const [messageName, messageSpec] of Object.entries(roleSpec.messages)) {
363
+ delete roleSpec.messages[messageName];
364
+ roleSpec.messages[toCamelCase(messageName)] = {
365
+ ...messageSpec
366
+ };
367
+ }
368
+ delete spec.networks[networkName];
369
+ networkSpec.roles[toCamelCase(roleName)] = {
370
+ ...roleSpec,
371
+ name: toCamelCase(roleName)
372
+ };
373
+ }
374
+ delete spec.networks[networkName];
375
+ spec.networks[toCamelCase(networkName)] = {
376
+ ...networkSpec,
377
+ name: toCamelCase(networkName)
378
+ };
379
+ }
344
380
  return {
345
381
  ...ctx,
346
382
  spec
package/dist/main.js CHANGED
@@ -181,7 +181,11 @@ function buildIr(ctx) {
181
181
  description: handlerSpec.description
182
182
  });
183
183
  irNetwork.models.push(
184
- ...buildIrModels(hostRoleSpec.name, handlerName, handlerSpec.payload)
184
+ ...buildIrModels(
185
+ hostRoleSpec.name,
186
+ handlerName + "Payload",
187
+ handlerSpec.payload
188
+ )
185
189
  );
186
190
  }
187
191
  }
@@ -199,7 +203,9 @@ function buildIr(ctx) {
199
203
  handlerName,
200
204
  description: handlerSpec.description
201
205
  });
202
- irNetwork.models.push(...buildIrModels(roleName, handlerName, handlerSpec.payload));
206
+ irNetwork.models.push(
207
+ ...buildIrModels(roleName, handlerName + "Payload", handlerSpec.payload)
208
+ );
203
209
  }
204
210
  }
205
211
  ir.networks.push(irNetwork);
@@ -234,6 +240,16 @@ async function dispatchBuildPlan(ctx) {
234
240
  import path from "path";
235
241
  import process2 from "process";
236
242
  import S2 from "@pocketgems/schema";
243
+
244
+ // src/utils.ts
245
+ function toCamelCase(str) {
246
+ return str.replace(/[-_\s]+/g, " ").replace(/([a-z])([A-Z])/g, "$1 $2").replace(/([A-Z]+)([A-Z][a-z])/g, "$1 $2").split(/\s+/).filter(Boolean).map((word, index) => {
247
+ const lower = word.toLowerCase();
248
+ return index === 0 ? lower : lower.charAt(0).toUpperCase() + lower.slice(1);
249
+ }).join("");
250
+ }
251
+
252
+ // src/build-request.ts
237
253
  var validateBuildRequest = S2.obj({
238
254
  specPath: S2.str,
239
255
  outputPath: S2.str,
@@ -253,12 +269,11 @@ var validateBuildRequest = S2.obj({
253
269
  function buildRequest(ctx) {
254
270
  const { rawInput } = ctx;
255
271
  if (!rawInput) throw new Error("rawInput is required");
256
- console.log("Host roles:", rawInput.hostRole);
257
272
  const request = {
258
273
  specPath: path.join(process2.cwd(), rawInput.spec),
259
274
  outputPath: path.join(process2.cwd(), rawInput.out),
260
275
  project: rawInput.project,
261
- hostRoles: rawInput.hostRole,
276
+ hostRoles: rawInput.hostRole.map((r) => toCamelCase(r)),
262
277
  target: {
263
278
  [rawInput.language]: {
264
279
  environment: rawInput.environment,
@@ -318,6 +333,27 @@ function loadSpec(ctx) {
318
333
  if (!request) throw new Error("request is required");
319
334
  const { specPath } = request;
320
335
  const spec = JSON.parse(fs2.readFileSync(specPath, "utf8"));
336
+ spec.name = toCamelCase(spec.name);
337
+ for (const [networkName, networkSpec] of Object.entries(spec.networks)) {
338
+ for (const [roleName, roleSpec] of Object.entries(networkSpec.roles)) {
339
+ for (const [messageName, messageSpec] of Object.entries(roleSpec.messages)) {
340
+ delete roleSpec.messages[messageName];
341
+ roleSpec.messages[toCamelCase(messageName)] = {
342
+ ...messageSpec
343
+ };
344
+ }
345
+ delete spec.networks[networkName];
346
+ networkSpec.roles[toCamelCase(roleName)] = {
347
+ ...roleSpec,
348
+ name: toCamelCase(roleName)
349
+ };
350
+ }
351
+ delete spec.networks[networkName];
352
+ spec.networks[toCamelCase(networkName)] = {
353
+ ...networkSpec,
354
+ name: toCamelCase(networkName)
355
+ };
356
+ }
321
357
  return {
322
358
  ...ctx,
323
359
  spec
@@ -132,12 +132,12 @@ function createPlan(ctx) {
132
132
  }
133
133
  }
134
134
  for (const handlerIr of networkIr.handlers) {
135
- handlerIr.modelClassName = pascalCase(handlerIr.handlerName);
135
+ handlerIr.modelClassName = pascalCase(handlerIr.handlerName) + "Payload";
136
136
  handlerIr.messageName = handlerIr.handlerName;
137
137
  handlerIr.methodName = pascalCase(handlerIr.handlerName);
138
138
  }
139
139
  for (const messageIr of networkIr.messages) {
140
- messageIr.modelClassName = pascalCase(messageIr.handlerName);
140
+ messageIr.modelClassName = pascalCase(messageIr.handlerName) + "Payload";
141
141
  messageIr.messageName = messageIr.handlerName;
142
142
  messageIr.methodName = pascalCase(messageIr.handlerName);
143
143
  }
@@ -1,8 +1,10 @@
1
+ import { Spec, Endpoint } from '@polytric/openws-spec/types';
2
+
1
3
  interface PipelineContext {
2
4
  argv: string[];
3
5
  rawInput?: RawInput;
4
6
  request?: BuildRequest;
5
- spec?: OpenWsSpec;
7
+ spec?: Spec;
6
8
  ir?: IR;
7
9
  plan?: PlanStep[];
8
10
  }
@@ -31,42 +33,6 @@ interface BuildRequest {
31
33
  };
32
34
  };
33
35
  }
34
- interface OpenWsSpec {
35
- name: string;
36
- description?: string;
37
- version?: string;
38
- networks: Record<string, NetworkSpec>;
39
- }
40
- interface NetworkSpec {
41
- name: string;
42
- description?: string;
43
- version?: string;
44
- roles: Record<string, RoleSpec>;
45
- }
46
- interface RoleSpec {
47
- name: string;
48
- description?: string;
49
- endpoints?: Endpoint[];
50
- messages: Record<string, MessageSpec>;
51
- }
52
- interface Endpoint {
53
- scheme: 'ws' | 'wss';
54
- host: string;
55
- port: number;
56
- path: string;
57
- }
58
- interface MessageSpec {
59
- description?: string;
60
- from?: string[];
61
- payload: JsonSchema;
62
- }
63
- interface JsonSchema {
64
- type: string;
65
- description?: string;
66
- properties?: Record<string, JsonSchema>;
67
- items?: JsonSchema;
68
- required?: string[];
69
- }
70
36
  interface IR {
71
37
  package: IRPackage;
72
38
  networks: IRNetwork[];
@@ -1,8 +1,10 @@
1
+ import { Spec, Endpoint } from '@polytric/openws-spec/types';
2
+
1
3
  interface PipelineContext {
2
4
  argv: string[];
3
5
  rawInput?: RawInput;
4
6
  request?: BuildRequest;
5
- spec?: OpenWsSpec;
7
+ spec?: Spec;
6
8
  ir?: IR;
7
9
  plan?: PlanStep[];
8
10
  }
@@ -31,42 +33,6 @@ interface BuildRequest {
31
33
  };
32
34
  };
33
35
  }
34
- interface OpenWsSpec {
35
- name: string;
36
- description?: string;
37
- version?: string;
38
- networks: Record<string, NetworkSpec>;
39
- }
40
- interface NetworkSpec {
41
- name: string;
42
- description?: string;
43
- version?: string;
44
- roles: Record<string, RoleSpec>;
45
- }
46
- interface RoleSpec {
47
- name: string;
48
- description?: string;
49
- endpoints?: Endpoint[];
50
- messages: Record<string, MessageSpec>;
51
- }
52
- interface Endpoint {
53
- scheme: 'ws' | 'wss';
54
- host: string;
55
- port: number;
56
- path: string;
57
- }
58
- interface MessageSpec {
59
- description?: string;
60
- from?: string[];
61
- payload: JsonSchema;
62
- }
63
- interface JsonSchema {
64
- type: string;
65
- description?: string;
66
- properties?: Record<string, JsonSchema>;
67
- items?: JsonSchema;
68
- required?: string[];
69
- }
70
36
  interface IR {
71
37
  package: IRPackage;
72
38
  networks: IRNetwork[];
@@ -92,12 +92,12 @@ function createPlan(ctx) {
92
92
  }
93
93
  }
94
94
  for (const handlerIr of networkIr.handlers) {
95
- handlerIr.modelClassName = pascalCase(handlerIr.handlerName);
95
+ handlerIr.modelClassName = pascalCase(handlerIr.handlerName) + "Payload";
96
96
  handlerIr.messageName = handlerIr.handlerName;
97
97
  handlerIr.methodName = pascalCase(handlerIr.handlerName);
98
98
  }
99
99
  for (const messageIr of networkIr.messages) {
100
- messageIr.modelClassName = pascalCase(messageIr.handlerName);
100
+ messageIr.modelClassName = pascalCase(messageIr.handlerName) + "Payload";
101
101
  messageIr.messageName = messageIr.handlerName;
102
102
  messageIr.methodName = pascalCase(messageIr.handlerName);
103
103
  }
@@ -1,3 +1,4 @@
1
+ using System;
1
2
  using System.Threading.Tasks;
2
3
  using Newtonsoft.Json.Linq;
3
4
  using Polytric.OpenWs.Core;
@@ -9,24 +10,24 @@ namespace <%= ctx.namespace %>
9
10
  {
10
11
  public partial class <%= ctx.className %> : <%= ctx.baseClassName %>
11
12
  {
12
- public override string Name { get; set; } = "<%= ctx.roleName %>";
13
- public override string Description { get; set; } = "<%= ctx.description ?? '' %>";
13
+ public string Name => "<%= ctx.roleName %>";
14
+ public string Description => "<%= ctx.description ?? '' %>";
14
15
 
15
- public override async Task HandleOpenAsync(RemoteRole remoteRole)
16
+ public override void HandleOpen(RemoteRole remoteRole)
16
17
  {
17
18
  <% for (const remoteRole of ctx.remoteRoles) { %>
18
19
  if (remoteRole is <%= remoteRole.className %> <%= remoteRole.varName %>)
19
20
  {
20
- await HandleOpenAsync(<%= remoteRole.varName %>).ConfigureAwait(false);
21
+ HandleOpen(<%= remoteRole.varName %>);
21
22
  }
22
23
  <% } -%>
23
24
  }
24
25
 
25
26
  <% for (const remoteRole of ctx.remoteRoles) { -%>
26
- private partial Task HandleOpenAsync(<%= remoteRole.className %> <%= remoteRole.varName %>);
27
+ partial void HandleOpen(<%= remoteRole.className %> <%= remoteRole.varName %>);
27
28
  <% } -%>
28
29
 
29
- public override async Task HandleMessageAsync(string messageName, JToken payload, RemoteRole remoteRole)
30
+ public override void HandleMessage(string messageName, JToken payload, RemoteRole remoteRole)
30
31
  {
31
32
  switch (messageName)
32
33
  {
@@ -34,8 +35,15 @@ namespace <%= ctx.namespace %>
34
35
  case "<%= handler.messageName %>":
35
36
  {
36
37
  var message = payload.ToObject<<%= handler.modelClassName %>>();
38
+ Handle<%= handler.methodName %>(payload);
39
+ Handle<%= handler.methodName %>(message);
40
+ On<%= handler.methodName %>?.Invoke(message);
41
+
37
42
  <% for (const remoteRole of ctx.remoteRoles) { %>
38
- await HandleMessageAsync(message, remoteRole as <%= remoteRole.className %>).ConfigureAwait(false);
43
+ Handle<%= handler.methodName %>(payload, remoteRole as <%= remoteRole.className %>);
44
+ HandleMessage(message, remoteRole as <%= remoteRole.className %>);
45
+ On<%= handler.methodName %>From<%= remoteRole.className %>?.Invoke(message, remoteRole as <%= remoteRole.className %>);
46
+
39
47
  <% } -%>
40
48
  break;
41
49
  }
@@ -44,8 +52,15 @@ namespace <%= ctx.namespace %>
44
52
  }
45
53
 
46
54
  <% for (const handler of ctx.handlers) { -%>
55
+ public event Action<<%= handler.modelClassName -%>> On<%= handler.methodName -%>;
56
+ partial void Handle<%= handler.methodName %>(JToken payload);
57
+ partial void Handle<%= handler.methodName %>(<%= handler.modelClassName -%> payload);
58
+
47
59
  <% for (const remoteRole of ctx.remoteRoles) { -%>
48
- private partial Task HandleMessageAsync(<%= handler.modelClassName %> payload, <%= remoteRole.className %> <%= remoteRole.varName %>);
60
+ public event Action<<%= handler.modelClassName -%>, <%= remoteRole.className -%>> On<%= handler.methodName -%>From<%= remoteRole.className -%>;
61
+ partial void Handle<%= handler.methodName %>(JToken payload, <%= remoteRole.className -%> <%= remoteRole.varName -%>);
62
+ partial void HandleMessage(<%= handler.modelClassName -%> payload, <%= remoteRole.className -%> <%= remoteRole.varName -%>);
63
+
49
64
  <% } -%>
50
65
  <% } -%>
51
66
  }
@@ -2,7 +2,7 @@ using Newtonsoft.Json;
2
2
 
3
3
  namespace <%= ctx.namespace %>
4
4
  {
5
- public class <%= ctx.className %>
5
+ public partial class <%= ctx.className %>
6
6
  {
7
7
  <% for (const property of ctx.properties) { -%>
8
8
  [JsonProperty("<%= property.modelName %>")]
@@ -14,7 +14,7 @@ namespace <%= ctx.namespace %>
14
14
  public override string Name { get; set; } = "<%= ctx.roleName %>";
15
15
  public override string Description { get; set; } = "<%= ctx.description ?? '' %>";
16
16
  <% if (ctx.endpoints && ctx.endpoints.length > 0) { -%>
17
- public override IReadOnlyList<Endpoint> Endpoints { get; set; } = new List<Endpoint>
17
+ public static IReadOnlyList<Endpoint> Endpoints => new List<Endpoint>
18
18
  {
19
19
  <% for (const ep of ctx.endpoints) { -%>
20
20
  new Endpoint { Scheme = "<%= ep.scheme %>", Host = "<%= ep.host %>", Port = <%= ep.port %>, Path = "<%= ep.path %>" },
@@ -25,7 +25,12 @@ namespace <%= ctx.namespace %>
25
25
  <% for (const message of ctx.messages) { -%>
26
26
  public async Task <%= message.methodName %>Async(string fromRole, <%= message.modelClassName %> message)
27
27
  {
28
- await SendMessageAsync(fromRole, "<%= message.messageName %>", message).ConfigureAwait(false);
28
+ await InternalSendMessageAsync(fromRole, "<%= message.messageName %>", message).ConfigureAwait(false);
29
+ }
30
+
31
+ public void <%= message.methodName %>(string fromRole, <%= message.modelClassName %> message)
32
+ {
33
+ InternalQueueMessage(fromRole, "<%= message.messageName %>", message);
29
34
  }
30
35
 
31
36
  <% } -%>
@@ -1,4 +1,5 @@
1
1
  using System.Threading.Tasks;
2
+ using Newtonsoft.Json.Linq;
2
3
  using Polytric.OpenWs.Core;
3
4
  <% for (const modelImport of ctx.modelImports) { -%>
4
5
  using <%= modelImport %>;
@@ -8,19 +9,40 @@ namespace <%= ctx.namespace %>
8
9
  public partial class <%= ctx.className %>
9
10
  {
10
11
  <% for (const remoteRole of ctx.remoteRoles) { -%>
11
- private partial Task HandleOpenAsync(<%= remoteRole.className %> <%= remoteRole.varName %>)
12
+ partial void HandleOpen(<%= remoteRole.className %> <%= remoteRole.varName %>)
12
13
  {
13
14
  // TODO: Implement connection handling for <%= remoteRole.className %>
14
- return Task.CompletedTask;
15
15
  }
16
16
 
17
17
  <% } -%>
18
18
  <% for (const handler of ctx.handlers) { -%>
19
+ partial void Handle<%= handler.methodName %>(JToken payload)
20
+ {
21
+ // TODO: Handle <%= handler.messageName %>
22
+ // Or implement the concrete payload method above. You only need to implement one.
23
+ // Removing this partial method will instruct the compiler to eliminate the call to save performance.
24
+ }
25
+
26
+ partial void Handle<%= handler.methodName %>(<%= handler.modelClassName %> payload)
27
+ {
28
+ // TODO: Handle <%= handler.messageName %>
29
+ // Or implement the JToken method above. You only need to implement one.
30
+ // Removing this partial method will instruct the compiler to eliminate the call to save performance.
31
+ }
32
+
19
33
  <% for (const remoteRole of ctx.remoteRoles) { -%>
20
- private partial Task HandleMessageAsync(<%= handler.modelClassName %> payload, <%= remoteRole.className %> <%= remoteRole.varName %>)
34
+ partial void HandleMessage(<%= handler.modelClassName %> payload, <%= remoteRole.className %> <%= remoteRole.varName %>)
35
+ {
36
+ // TODO: Handle <%= handler.messageName %> from <%= remoteRole.className %>
37
+ // Or implement the JToken method below. You only need to implement one.
38
+ // Removing this partial method will instruct the compiler to eliminate the call to save performance.
39
+ }
40
+
41
+ partial void Handle<%= handler.methodName %>(JToken payload, <%= remoteRole.className %> <%= remoteRole.varName %>)
21
42
  {
22
43
  // TODO: Handle <%= handler.messageName %> from <%= remoteRole.className %>
23
- return Task.CompletedTask;
44
+ // Or implement the concrete payload method above. You only need to implement one.
45
+ // Removing this partial method will instruct the compiler to eliminate the call to save performance.
24
46
  }
25
47
 
26
48
  <% } -%>
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@polytric/openws-sdkgen",
3
- "version": "0.0.4",
3
+ "version": "0.0.5",
4
4
  "description": "OpenWS SDK generator CLI",
5
5
  "type": "module",
6
6
  "bin": {
@@ -34,8 +34,10 @@
34
34
  },
35
35
  "dependencies": {
36
36
  "@pocketgems/schema": "^0.1.3",
37
+ "ajv": "^8.17.1",
37
38
  "ejs": "^3.1.10",
38
- "yargs": "^18.0.0"
39
+ "yargs": "^18.0.0",
40
+ "@polytric/openws-spec": "0.0.4"
39
41
  },
40
42
  "devDependencies": {
41
43
  "@types/ejs": "^3.1.5",