hbs-magic 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (33) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +386 -0
  3. package/bin/cli.ts +48 -0
  4. package/dist/bin/cli.js +25 -0
  5. package/dist/src/cli-messages.js +84 -0
  6. package/dist/src/file-helpers.js +94 -0
  7. package/dist/src/formatting-helpers.js +63 -0
  8. package/dist/src/hbs-process-helpers.js +22 -0
  9. package/dist/src/process-helpers.js +50 -0
  10. package/examples/advanced_csharp-url-helpers/Result.gen.cs +455 -0
  11. package/examples/advanced_csharp-url-helpers/external-input/links.ts +182 -0
  12. package/examples/advanced_csharp-url-helpers/input/hbs-helpers.ts +93 -0
  13. package/examples/advanced_csharp-url-helpers/input/input-data.json +244 -0
  14. package/examples/advanced_csharp-url-helpers/input/preparation-script.ts +175 -0
  15. package/examples/advanced_csharp-url-helpers/input/template.hbs +44 -0
  16. package/examples/advanced_csharp-url-helpers/input/template_partial_node.hbs +32 -0
  17. package/examples/from-api_ts-api-client/Result.gen.ts +189 -0
  18. package/examples/from-api_ts-api-client/input/hbs-helpers.ts +53 -0
  19. package/examples/from-api_ts-api-client/input/template.hbs +30 -0
  20. package/examples/simple_assets-helper/Result.gen.ts +36 -0
  21. package/examples/simple_assets-helper/external-input/dummy_audio_1.mp3 +0 -0
  22. package/examples/simple_assets-helper/external-input/dummy_audio_2.mp3 +0 -0
  23. package/examples/simple_assets-helper/external-input/dummy_audio_3.mp3 +0 -0
  24. package/examples/simple_assets-helper/input/preparation-script.ts +45 -0
  25. package/examples/simple_assets-helper/input/template.hbs +31 -0
  26. package/package.json +52 -0
  27. package/src/cli-messages.ts +88 -0
  28. package/src/file-helpers.ts +108 -0
  29. package/src/formatting-helpers.ts +81 -0
  30. package/src/hbs-process-helpers.ts +36 -0
  31. package/src/process-helpers.ts +78 -0
  32. package/tsconfig.json +14 -0
  33. package/tsconfig.node.json +8 -0
@@ -0,0 +1,63 @@
1
+ import { execSync } from "node:child_process";
2
+ import path from "path";
3
+ import prettier from "prettier";
4
+ import fs from "fs";
5
+ const jsExtensions = [".ts", ".tsx", ".js", ".jsx"];
6
+ export async function formatJsFileWithPrettier(sourcePath) {
7
+ const filePath = path.resolve(sourcePath);
8
+ const source = fs.readFileSync(filePath, "utf8");
9
+ const options = await prettier.resolveConfig(filePath);
10
+ const formatted = await prettier.format(source, {
11
+ ...options,
12
+ filepath: filePath,
13
+ });
14
+ if (formatted !== source) {
15
+ fs.writeFileSync(filePath, formatted, "utf8");
16
+ }
17
+ }
18
+ const csExtensions = [".cs"];
19
+ function formatCsFileWithCSharpier(filePath) {
20
+ const resolved = path.resolve(filePath);
21
+ const toolDir = path.join(process.cwd(), ".csharpier");
22
+ if (!fs.existsSync(toolDir)) {
23
+ fs.mkdirSync(toolDir);
24
+ execSync("dotnet new tool-manifest", { cwd: toolDir, stdio: "ignore" });
25
+ execSync("dotnet tool install csharpier", {
26
+ cwd: toolDir,
27
+ stdio: "ignore",
28
+ });
29
+ }
30
+ execSync(`dotnet tool run csharpier format "${resolved}"`, {
31
+ cwd: toolDir,
32
+ stdio: "inherit",
33
+ });
34
+ }
35
+ var OutputFileType;
36
+ (function (OutputFileType) {
37
+ OutputFileType[OutputFileType["JavaScript"] = 0] = "JavaScript";
38
+ OutputFileType[OutputFileType["Csharp"] = 1] = "Csharp";
39
+ })(OutputFileType || (OutputFileType = {}));
40
+ const outputFileTypeMap = {
41
+ [OutputFileType.JavaScript]: {
42
+ extensions: jsExtensions,
43
+ formatterFunc: formatJsFileWithPrettier,
44
+ },
45
+ [OutputFileType.Csharp]: {
46
+ extensions: csExtensions,
47
+ formatterFunc: formatCsFileWithCSharpier,
48
+ },
49
+ };
50
+ /*
51
+ * Detects the file type based on extension and formats it with the appropriate formatter.
52
+ * Currently supports JavaScript/TypeScript files with Prettier and C# files with CSharpier.
53
+ */
54
+ export async function formatSourceFile(filePath) {
55
+ const ext = filePath.slice(filePath.lastIndexOf("."));
56
+ for (const formatter of Object.values(outputFileTypeMap)) {
57
+ if (formatter.extensions.includes(ext)) {
58
+ await formatter.formatterFunc(filePath);
59
+ return;
60
+ }
61
+ }
62
+ throw new Error(`Unsupported output file type: ${ext}`);
63
+ }
@@ -0,0 +1,22 @@
1
+ import fs from "fs";
2
+ import Handlebars from "handlebars";
3
+ import { getDefaultExport } from "./file-helpers.js";
4
+ export async function registerHbsHelpersFromFile(fullPath) {
5
+ const hbsHelpers = await getDefaultExport(fullPath);
6
+ for (const [name, value] of Object.entries(hbsHelpers)) {
7
+ if (typeof value === "function") {
8
+ Handlebars.registerHelper(name, value);
9
+ }
10
+ }
11
+ }
12
+ export async function registerHbsPartials(partials) {
13
+ for (const partial of partials) {
14
+ Handlebars.registerPartial(partial.name, partial.content);
15
+ }
16
+ }
17
+ export async function compileHbsTemplateAndWriteToFile(templatePath, inputObject, outputFilePath) {
18
+ const template = fs.readFileSync(templatePath, "utf8");
19
+ const compiled = Handlebars.compile(template);
20
+ const result = compiled(inputObject);
21
+ fs.writeFileSync(outputFilePath, result);
22
+ }
@@ -0,0 +1,50 @@
1
+ import { hbsMagicCliUsage, hbsMagicHelp, inputDataNotFound, multipleSourcesDetected, positionalArgumentsNotAllowed, } from "./cli-messages.js";
2
+ import { getJson } from "./file-helpers.js";
3
+ export function extractArguments(process, required) {
4
+ const raw = process.argv.slice(2);
5
+ if (raw.length === 1 && raw[0] === "--help") {
6
+ console.log(hbsMagicHelp);
7
+ process.exit(1);
8
+ }
9
+ const args = {};
10
+ for (const arg of raw) {
11
+ if (arg.startsWith("--")) {
12
+ const [key, value] = arg.slice(2).split("=");
13
+ args[key] = value ?? true;
14
+ }
15
+ else {
16
+ throw new Error(positionalArgumentsNotAllowed);
17
+ }
18
+ }
19
+ for (const req of required) {
20
+ if (!(req in args)) {
21
+ console.error(`Missing required argument: --${req}`);
22
+ console.error(hbsMagicCliUsage);
23
+ process.exit(1);
24
+ }
25
+ }
26
+ return args;
27
+ }
28
+ export function extractFlag(process, flagName) {
29
+ const arg = process.argv.find((a) => a.startsWith(`--${flagName}`));
30
+ return !!arg;
31
+ }
32
+ export function extractArgument(process, argumentName) {
33
+ const arg = process.argv.find((a) => a.startsWith(`--${argumentName}=`));
34
+ return arg?.split("=")[1] ?? undefined;
35
+ }
36
+ export async function getInputObject(externalJson, preparationScriptResult, inputPath) {
37
+ if (!externalJson && !preparationScriptResult && !inputPath)
38
+ throw new Error(inputDataNotFound);
39
+ const sourcesCount = (externalJson ? 1 : 0) +
40
+ (preparationScriptResult ? 1 : 0) +
41
+ (inputPath ? 1 : 0);
42
+ if (sourcesCount > 1)
43
+ console.warn(multipleSourcesDetected);
44
+ if (externalJson)
45
+ return await getJson(externalJson);
46
+ if (preparationScriptResult)
47
+ return preparationScriptResult;
48
+ if (inputPath)
49
+ return await getJson(inputPath);
50
+ }
@@ -0,0 +1,455 @@
1
+ using System;
2
+ using System.Collections.Generic;
3
+
4
+ namespace ExampleProject.Common.FrontendUrlHelpers;
5
+
6
+ //--------------------------------------------------------------------------------------------------------------
7
+ // <auto-generated>
8
+ // This file was auto-generated by "hbs-magic" CLI.
9
+ // Do not modify this file manually. Instead, modify the template and regenerate the code.
10
+ // </auto-generated>
11
+ //--------------------------------------------------------------------------------------------------------------
12
+
13
+ public static class Routes
14
+ {
15
+ public static class Unauthorized
16
+ {
17
+ public static class Login
18
+ {
19
+ public static string Link(string siteUrl, LoginQueryParams queryParams) =>
20
+ siteUrl + "/login" + "?" + queryParams.GetQueryString();
21
+ }
22
+
23
+ public static class Register
24
+ {
25
+ public static string Link(string siteUrl, RegisterQueryParams queryParams) =>
26
+ siteUrl + "/register" + "?" + queryParams.GetQueryString();
27
+ }
28
+
29
+ public static class ConfirmEmail
30
+ {
31
+ public static string Link(string siteUrl, string userId, string token) =>
32
+ siteUrl
33
+ + "/confirm-email/:userId/:token"
34
+ .Replace(":userId", userId.ToString())
35
+ .Replace(":token", token.ToString());
36
+ }
37
+
38
+ public static class ForgotPassword
39
+ {
40
+ public static string Link(string siteUrl) => siteUrl + "/forgot-password";
41
+ }
42
+ }
43
+
44
+ public static class Authorized
45
+ {
46
+ public static class Dashboard
47
+ {
48
+ public static string Link(string siteUrl, DashboardQueryParams queryParams) =>
49
+ siteUrl + "/" + "?" + queryParams.GetQueryString();
50
+ }
51
+
52
+ public static class Profile
53
+ {
54
+ public static string Link(string siteUrl, int userId, string section) =>
55
+ siteUrl
56
+ + "/profile/:userId"
57
+ .Replace(":userId", userId.ToString())
58
+ .Replace(":section", section.ToString());
59
+ }
60
+
61
+ public static class Settings
62
+ {
63
+ public static string Link(string siteUrl, SettingsQueryParams queryParams) =>
64
+ siteUrl + "/settings" + "?" + queryParams.GetQueryString();
65
+ }
66
+
67
+ public static class Courses
68
+ {
69
+ public static string Link(string siteUrl, CoursesQueryParams queryParams) =>
70
+ siteUrl + "/courses" + "?" + queryParams.GetQueryString();
71
+ }
72
+
73
+ public static class CourseDetails
74
+ {
75
+ public static string Link(string siteUrl, int courseId, string tab) =>
76
+ siteUrl
77
+ + "/courses/:courseId"
78
+ .Replace(":courseId", courseId.ToString())
79
+ .Replace(":tab", tab.ToString());
80
+ }
81
+
82
+ public static class CourseNotFound
83
+ {
84
+ public static string Link(string siteUrl, int courseId) =>
85
+ siteUrl + "/courses/:courseId/not-found".Replace(":courseId", courseId.ToString());
86
+ }
87
+
88
+ public static class CourseAccessDenied
89
+ {
90
+ public static string Link(string siteUrl, int courseId) =>
91
+ siteUrl
92
+ + "/courses/:courseId/access-denied".Replace(":courseId", courseId.ToString());
93
+ }
94
+
95
+ public static class CourseStudents
96
+ {
97
+ public static string Link(string siteUrl, int courseId, int page, List<string> roles) =>
98
+ siteUrl
99
+ + "/courses/:courseId/students"
100
+ .Replace(":courseId", courseId.ToString())
101
+ .Replace(":page", page.ToString())
102
+ .Replace(":roles", roles.ToString());
103
+ }
104
+
105
+ public static class AssignmentList
106
+ {
107
+ public static string Link(
108
+ string siteUrl,
109
+ int courseId,
110
+ string status,
111
+ string dueBefore
112
+ ) =>
113
+ siteUrl
114
+ + "/courses/:courseId/assignments"
115
+ .Replace(":courseId", courseId.ToString())
116
+ .Replace(":status", status.ToString())
117
+ .Replace(":dueBefore", dueBefore.ToString());
118
+ }
119
+
120
+ public static class AssignmentDetails
121
+ {
122
+ public static string Link(string siteUrl, int courseId, int assignmentId, string tab) =>
123
+ siteUrl
124
+ + "/courses/:courseId/assignments/:assignmentId"
125
+ .Replace(":courseId", courseId.ToString())
126
+ .Replace(":assignmentId", assignmentId.ToString())
127
+ .Replace(":tab", tab.ToString());
128
+ }
129
+
130
+ public static class AssignmentSubmissions
131
+ {
132
+ public static string Link(
133
+ string siteUrl,
134
+ int courseId,
135
+ int assignmentId,
136
+ int page,
137
+ List<string> userIds
138
+ ) =>
139
+ siteUrl
140
+ + "/courses/:courseId/assignments/:assignmentId/submissions"
141
+ .Replace(":courseId", courseId.ToString())
142
+ .Replace(":assignmentId", assignmentId.ToString())
143
+ .Replace(":page", page.ToString())
144
+ .Replace(":userIds", userIds.ToString());
145
+ }
146
+
147
+ public static class Announcements
148
+ {
149
+ public static string Link(string siteUrl, int courseId, int page) =>
150
+ siteUrl
151
+ + "/courses/:courseId/announcements"
152
+ .Replace(":courseId", courseId.ToString())
153
+ .Replace(":page", page.ToString());
154
+ }
155
+
156
+ public static class AnnouncementDetails
157
+ {
158
+ public static string Link(
159
+ string siteUrl,
160
+ int courseId,
161
+ int announcementId,
162
+ string highlight
163
+ ) =>
164
+ siteUrl
165
+ + "/courses/:courseId/announcements/:announcementId"
166
+ .Replace(":courseId", courseId.ToString())
167
+ .Replace(":announcementId", announcementId.ToString())
168
+ .Replace(":highlight", highlight.ToString());
169
+ }
170
+
171
+ public static class Products
172
+ {
173
+ public static string Link(string siteUrl, ProductsQueryParams queryParams) =>
174
+ siteUrl + "/products" + "?" + queryParams.GetQueryString();
175
+ }
176
+
177
+ public static class ProductDetails
178
+ {
179
+ public static string Link(string siteUrl, int id) =>
180
+ siteUrl + "/products/:id".Replace(":id", id.ToString());
181
+ }
182
+
183
+ public static class CreateProduct
184
+ {
185
+ public static string Link(string siteUrl, CreateProductQueryParams queryParams) =>
186
+ siteUrl + "/products/create" + "?" + queryParams.GetQueryString();
187
+ }
188
+
189
+ public static class EditProduct
190
+ {
191
+ public static string Link(string siteUrl, int id, string mode) =>
192
+ siteUrl
193
+ + "/products/:id/edit"
194
+ .Replace(":id", id.ToString())
195
+ .Replace(":mode", mode.ToString());
196
+ }
197
+
198
+ public static class Admin
199
+ {
200
+ public static string Link(string siteUrl, AdminQueryParams queryParams) =>
201
+ siteUrl + "/admin" + "?" + queryParams.GetQueryString();
202
+ }
203
+
204
+ public static class AdminUsers
205
+ {
206
+ public static string Link(string siteUrl, AdminUsersQueryParams queryParams) =>
207
+ siteUrl + "/admin/users" + "?" + queryParams.GetQueryString();
208
+ }
209
+
210
+ public static class AdminUserDetails
211
+ {
212
+ public static string Link(string siteUrl, int userId, string tab) =>
213
+ siteUrl
214
+ + "/admin/users/:userId"
215
+ .Replace(":userId", userId.ToString())
216
+ .Replace(":tab", tab.ToString());
217
+ }
218
+
219
+ public static class Notifications
220
+ {
221
+ public static string Link(string siteUrl, NotificationsQueryParams queryParams) =>
222
+ siteUrl + "/notifications" + "?" + queryParams.GetQueryString();
223
+ }
224
+
225
+ public static class Search
226
+ {
227
+ public static string Link(string siteUrl, SearchQueryParams queryParams) =>
228
+ siteUrl + "/search" + "?" + queryParams.GetQueryString();
229
+ }
230
+
231
+ public static class UiKit
232
+ {
233
+ public static string Link(string siteUrl, UiKitQueryParams queryParams) =>
234
+ siteUrl + "/uikit" + "?" + queryParams.GetQueryString();
235
+ }
236
+ }
237
+ }
238
+
239
+ public interface IRouteQueryParams
240
+ {
241
+ public string GetQueryString();
242
+ }
243
+
244
+ public class LoginQueryParams : IRouteQueryParams
245
+ {
246
+ public string? Redirect { get; init; }
247
+
248
+ public string GetQueryString()
249
+ {
250
+ var queryParams = new List<string>();
251
+
252
+ if (!string.IsNullOrEmpty(Redirect))
253
+ queryParams.Add($"redirect={Redirect}");
254
+
255
+ return string.Join("&", queryParams);
256
+ }
257
+ }
258
+
259
+ public class RegisterQueryParams : IRouteQueryParams
260
+ {
261
+ public string? Ref { get; init; }
262
+
263
+ public string GetQueryString()
264
+ {
265
+ var queryParams = new List<string>();
266
+
267
+ if (!string.IsNullOrEmpty(Ref))
268
+ queryParams.Add($"ref={Ref}");
269
+
270
+ return string.Join("&", queryParams);
271
+ }
272
+ }
273
+
274
+ public class DashboardQueryParams : IRouteQueryParams
275
+ {
276
+ public string? Tab { get; init; }
277
+
278
+ public string GetQueryString()
279
+ {
280
+ var queryParams = new List<string>();
281
+
282
+ if (!string.IsNullOrEmpty(Tab))
283
+ queryParams.Add($"tab={Tab}");
284
+
285
+ return string.Join("&", queryParams);
286
+ }
287
+ }
288
+
289
+ public class SettingsQueryParams : IRouteQueryParams
290
+ {
291
+ public string? Page { get; init; }
292
+
293
+ public string GetQueryString()
294
+ {
295
+ var queryParams = new List<string>();
296
+
297
+ if (!string.IsNullOrEmpty(Page))
298
+ queryParams.Add($"page={Page}");
299
+
300
+ return string.Join("&", queryParams);
301
+ }
302
+ }
303
+
304
+ public class CoursesQueryParams : IRouteQueryParams
305
+ {
306
+ public int? Page { get; init; }
307
+ public int? PageSize { get; init; }
308
+ public string? Search { get; init; }
309
+ public List<string>? Tags { get; init; }
310
+
311
+ public string GetQueryString()
312
+ {
313
+ var queryParams = new List<string>();
314
+
315
+ if (Page != null)
316
+ queryParams.Add($"page={Page.Value}");
317
+ if (PageSize != null)
318
+ queryParams.Add($"pageSize={PageSize.Value}");
319
+ if (!string.IsNullOrEmpty(Search))
320
+ queryParams.Add($"search={Search}");
321
+ if (Tags is { Count: > 0 })
322
+ queryParams.Add($"tags={string.Join(",", Tags)}");
323
+
324
+ return string.Join("&", queryParams);
325
+ }
326
+ }
327
+
328
+ public class ProductsQueryParams : IRouteQueryParams
329
+ {
330
+ public int? Page { get; init; }
331
+ public int? PageSize { get; init; }
332
+ public string? SortBy { get; init; }
333
+ public List<string>? Categories { get; init; }
334
+ public int? MinPrice { get; init; }
335
+ public int? MaxPrice { get; init; }
336
+
337
+ public string GetQueryString()
338
+ {
339
+ var queryParams = new List<string>();
340
+
341
+ if (Page != null)
342
+ queryParams.Add($"page={Page.Value}");
343
+ if (PageSize != null)
344
+ queryParams.Add($"pageSize={PageSize.Value}");
345
+ if (!string.IsNullOrEmpty(SortBy))
346
+ queryParams.Add($"sortBy={SortBy}");
347
+ if (Categories is { Count: > 0 })
348
+ queryParams.Add($"categories={string.Join(",", Categories)}");
349
+ if (MinPrice != null)
350
+ queryParams.Add($"minPrice={MinPrice.Value}");
351
+ if (MaxPrice != null)
352
+ queryParams.Add($"maxPrice={MaxPrice.Value}");
353
+
354
+ return string.Join("&", queryParams);
355
+ }
356
+ }
357
+
358
+ public class CreateProductQueryParams : IRouteQueryParams
359
+ {
360
+ public int? TemplateId { get; init; }
361
+
362
+ public string GetQueryString()
363
+ {
364
+ var queryParams = new List<string>();
365
+
366
+ if (TemplateId != null)
367
+ queryParams.Add($"templateId={TemplateId.Value}");
368
+
369
+ return string.Join("&", queryParams);
370
+ }
371
+ }
372
+
373
+ public class AdminQueryParams : IRouteQueryParams
374
+ {
375
+ public string? Tab { get; init; }
376
+
377
+ public string GetQueryString()
378
+ {
379
+ var queryParams = new List<string>();
380
+
381
+ if (!string.IsNullOrEmpty(Tab))
382
+ queryParams.Add($"tab={Tab}");
383
+
384
+ return string.Join("&", queryParams);
385
+ }
386
+ }
387
+
388
+ public class AdminUsersQueryParams : IRouteQueryParams
389
+ {
390
+ public int? Page { get; init; }
391
+ public List<string>? Roles { get; init; }
392
+ public string? Search { get; init; }
393
+
394
+ public string GetQueryString()
395
+ {
396
+ var queryParams = new List<string>();
397
+
398
+ if (Page != null)
399
+ queryParams.Add($"page={Page.Value}");
400
+ if (Roles is { Count: > 0 })
401
+ queryParams.Add($"roles={string.Join(",", Roles)}");
402
+ if (!string.IsNullOrEmpty(Search))
403
+ queryParams.Add($"search={Search}");
404
+
405
+ return string.Join("&", queryParams);
406
+ }
407
+ }
408
+
409
+ public class NotificationsQueryParams : IRouteQueryParams
410
+ {
411
+ public bool? UnreadOnly { get; init; }
412
+
413
+ public string GetQueryString()
414
+ {
415
+ var queryParams = new List<string>();
416
+
417
+ if (UnreadOnly != null)
418
+ queryParams.Add($"unreadOnly={UnreadOnly.Value}");
419
+
420
+ return string.Join("&", queryParams);
421
+ }
422
+ }
423
+
424
+ public class SearchQueryParams : IRouteQueryParams
425
+ {
426
+ public List<string>? Types { get; init; }
427
+ public int? Page { get; init; }
428
+
429
+ public string GetQueryString()
430
+ {
431
+ var queryParams = new List<string>();
432
+
433
+ if (Types is { Count: > 0 })
434
+ queryParams.Add($"types={string.Join(",", Types)}");
435
+ if (Page != null)
436
+ queryParams.Add($"page={Page.Value}");
437
+
438
+ return string.Join("&", queryParams);
439
+ }
440
+ }
441
+
442
+ public class UiKitQueryParams : IRouteQueryParams
443
+ {
444
+ public string? Component { get; init; }
445
+
446
+ public string GetQueryString()
447
+ {
448
+ var queryParams = new List<string>();
449
+
450
+ if (!string.IsNullOrEmpty(Component))
451
+ queryParams.Add($"component={Component}");
452
+
453
+ return string.Join("&", queryParams);
454
+ }
455
+ }