routesync 1.0.9 → 1.0.11

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 (2) hide show
  1. package/dist/cli.js +75 -6
  2. package/package.json +1 -1
package/dist/cli.js CHANGED
@@ -8611,14 +8611,29 @@ function toMethodName(route) {
8611
8611
  }
8612
8612
 
8613
8613
  // packages/cli/src/generators/SDKGenerator.ts
8614
- var SDKGenerator = class {
8615
- static async generate(manifest, outputDir) {
8614
+ var SDKGenerator = class _SDKGenerator {
8615
+ static async generate(manifest, outputDir, options = {}) {
8616
8616
  const grouped = buildGeneratedRoutes(manifest.routes);
8617
8617
  const lines = [];
8618
+ let usesZod = false;
8619
+ const zodRoutes = /* @__PURE__ */ new Set();
8620
+ if (options.zod) {
8621
+ for (const [group, routes] of Object.entries(grouped)) {
8622
+ for (const route of routes) {
8623
+ if (route.original.schema?.rules) {
8624
+ usesZod = true;
8625
+ zodRoutes.add(`${group}.${route.actionName}`);
8626
+ }
8627
+ }
8628
+ }
8629
+ }
8618
8630
  lines.push(`// Auto-generated by routesync. Do not edit manually.`);
8619
8631
  lines.push(`// Generated at: ${manifest.generatedAt}`);
8620
8632
  lines.push(``);
8621
8633
  lines.push(`import { defineApi } from 'routesync'`);
8634
+ if (usesZod) {
8635
+ lines.push(`import { z } from 'zod'`);
8636
+ }
8622
8637
  lines.push(``);
8623
8638
  lines.push(`export const api = defineApi({`);
8624
8639
  for (const [group, routes] of Object.entries(grouped)) {
@@ -8628,6 +8643,12 @@ var SDKGenerator = class {
8628
8643
  lines.push(` method: '${route.method}',`);
8629
8644
  lines.push(` path: '${route.runtimePath}',`);
8630
8645
  if (route.auth) lines.push(` auth: true,`);
8646
+ if (options.zod && route.original.schema?.rules) {
8647
+ const zodSchema = _SDKGenerator.translateRulesToZod(route.original.schema.rules);
8648
+ lines.push(` schema: {`);
8649
+ lines.push(` body: ${zodSchema}`);
8650
+ lines.push(` },`);
8651
+ }
8631
8652
  lines.push(` },`);
8632
8653
  }
8633
8654
  lines.push(` },`);
@@ -8637,6 +8658,54 @@ var SDKGenerator = class {
8637
8658
  lines.push(`export default api`);
8638
8659
  await import_fs_extra3.default.writeFile(import_path2.default.join(outputDir, "api.ts"), lines.join("\n"));
8639
8660
  }
8661
+ static translateRulesToZod(rules) {
8662
+ const fields = [];
8663
+ for (const [field, rawRules] of Object.entries(rules)) {
8664
+ let ruleArray = [];
8665
+ if (typeof rawRules === "string") {
8666
+ ruleArray = rawRules.split("|");
8667
+ } else if (Array.isArray(rawRules)) {
8668
+ ruleArray = rawRules;
8669
+ }
8670
+ let isRequired = false;
8671
+ let isNullable = false;
8672
+ let isString = false;
8673
+ let isNumeric = false;
8674
+ let isArray = false;
8675
+ let isBoolean = false;
8676
+ let isEmail = false;
8677
+ let min = null;
8678
+ let max = null;
8679
+ for (const rule of ruleArray) {
8680
+ if (typeof rule !== "string") continue;
8681
+ const r = rule.toLowerCase();
8682
+ if (r === "required") isRequired = true;
8683
+ if (r === "nullable") isNullable = true;
8684
+ if (r === "string") isString = true;
8685
+ if (r === "numeric" || r === "integer" || r === "int") isNumeric = true;
8686
+ if (r === "array") isArray = true;
8687
+ if (r === "boolean" || r === "bool") isBoolean = true;
8688
+ if (r === "email") isEmail = true;
8689
+ if (r.startsWith("min:")) min = r.split(":")[1];
8690
+ if (r.startsWith("max:")) max = r.split(":")[1];
8691
+ }
8692
+ let zType = "z.any()";
8693
+ if (isString) zType = "z.string()";
8694
+ else if (isNumeric) zType = "z.number()";
8695
+ else if (isBoolean) zType = "z.boolean()";
8696
+ else if (isArray) zType = "z.array(z.any())";
8697
+ else if (isEmail) zType = "z.string()";
8698
+ if (isEmail && zType === "z.string()") zType += ".email()";
8699
+ if (min && !isNaN(Number(min))) zType += `.min(${min})`;
8700
+ if (max && !isNaN(Number(max))) zType += `.max(${max})`;
8701
+ if (!isRequired) zType += ".optional()";
8702
+ if (isNullable) zType += ".nullable()";
8703
+ fields.push(` "${field}": ${zType}`);
8704
+ }
8705
+ return `z.object({
8706
+ ${fields.join(",\n")}
8707
+ })`;
8708
+ }
8640
8709
  };
8641
8710
 
8642
8711
  // packages/cli/src/generators/TypeGenerator.ts
@@ -8785,10 +8854,10 @@ var NextActionGenerator = class {
8785
8854
  lines.push(`import { cookies } from 'next/headers'`);
8786
8855
  lines.push(``);
8787
8856
  lines.push(`// Helper to auto-inject token from cookies if available`);
8788
- lines.push(`async function getAuthHeaders() {`);
8857
+ lines.push(`async function getAuthHeaders(): Promise<Record<string, string> | undefined> {`);
8789
8858
  lines.push(` const cookieStore = await cookies()`);
8790
8859
  lines.push(` const token = cookieStore.get('token')?.value`);
8791
- lines.push(` return token ? { Authorization: \`Bearer \${token}\` } : {}`);
8860
+ lines.push(` return token ? { Authorization: \`Bearer \${token}\` } : undefined`);
8792
8861
  lines.push(`}`);
8793
8862
  lines.push(``);
8794
8863
  const grouped = buildGeneratedRoutes(manifest.routes);
@@ -9071,7 +9140,7 @@ var LaravelChannelParser = class {
9071
9140
 
9072
9141
  // packages/cli/src/commands/sync.ts
9073
9142
  var import_fs_extra13 = __toESM(require_lib());
9074
- var syncCommand = new Command("sync").description("Scan routes and generate SDK in one step").option("-i, --input <path>", "Path to routes/api.php", "routes/api.php").option("-o, --output <path>", "Output directory", "src/api").option("-b, --baseURL <url>", "API base URL", "http://localhost/api").option("--no-hooks", "Skip generating React hooks").option("--next-actions", "Generate Next.js Server Actions").option("--msw", "Generate MSW Mock Handlers").option("--echo", "Generate Laravel Echo Hooks").option("--models", "Extract Database Schema via Eloquent Models").action(async (options) => {
9143
+ var syncCommand = new Command("sync").description("Scan routes and generate SDK in one step").option("-i, --input <path>", "Path to routes/api.php", "routes/api.php").option("-o, --output <path>", "Output directory", "src/api").option("-b, --baseURL <url>", "API base URL", "http://localhost/api").option("--no-hooks", "Skip generating React hooks").option("--next-actions", "Generate Next.js Server Actions").option("--msw", "Generate MSW Mock Handlers").option("--echo", "Generate Laravel Echo Hooks").option("--models", "Extract Database Schema via Eloquent Models").option("--zod", "Generate Zod Schemas for request validation").action(async (options) => {
9075
9144
  console.log(source_default.bold.blue("\n routesync sync\n"));
9076
9145
  const steps = [
9077
9146
  { text: "Scanning Laravel routes" },
@@ -9094,7 +9163,7 @@ var syncCommand = new Command("sync").description("Scan routes and generate SDK
9094
9163
  await TypeGenerator.generate(manifest, options.output);
9095
9164
  spinner.succeed(source_default.green(`\u2714 ${steps[1].text}`));
9096
9165
  spinner.start(steps[2].text);
9097
- await SDKGenerator.generate(manifest, options.output);
9166
+ await SDKGenerator.generate(manifest, options.output, options);
9098
9167
  spinner.succeed(source_default.green(`\u2714 ${steps[2].text}`));
9099
9168
  if (options.hooks !== false) {
9100
9169
  spinner.start(steps[3].text);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "routesync",
3
- "version": "1.0.9",
3
+ "version": "1.0.11",
4
4
  "description": "Laravel routes to typed frontend SDKs.",
5
5
  "main": "./dist/sdk.js",
6
6
  "module": "./dist/sdk.mjs",