swallowkit 1.0.0-beta.47 → 1.0.0-beta.48

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 (66) hide show
  1. package/dist/cli/commands/add-auth.d.ts +1 -0
  2. package/dist/cli/commands/add-auth.d.ts.map +1 -1
  3. package/dist/cli/commands/add-auth.js +136 -1
  4. package/dist/cli/commands/add-auth.js.map +1 -1
  5. package/dist/cli/commands/dev.js +5 -2
  6. package/dist/cli/commands/dev.js.map +1 -1
  7. package/dist/cli/commands/scaffold.d.ts +9 -0
  8. package/dist/cli/commands/scaffold.d.ts.map +1 -1
  9. package/dist/cli/commands/scaffold.js +56 -12
  10. package/dist/cli/commands/scaffold.js.map +1 -1
  11. package/dist/cli/index.d.ts.map +1 -1
  12. package/dist/cli/index.js +2 -0
  13. package/dist/cli/index.js.map +1 -1
  14. package/dist/core/config.d.ts +7 -2
  15. package/dist/core/config.d.ts.map +1 -1
  16. package/dist/core/config.js +81 -1
  17. package/dist/core/config.js.map +1 -1
  18. package/dist/core/mock/connector-mock-server.js +2 -2
  19. package/dist/core/mock/connector-mock-server.js.map +1 -1
  20. package/dist/core/project/manifest.js +2 -2
  21. package/dist/core/project/manifest.js.map +1 -1
  22. package/dist/core/project/validation.d.ts.map +1 -1
  23. package/dist/core/project/validation.js +17 -0
  24. package/dist/core/project/validation.js.map +1 -1
  25. package/dist/core/scaffold/auth-generator.d.ts +9 -2
  26. package/dist/core/scaffold/auth-generator.d.ts.map +1 -1
  27. package/dist/core/scaffold/auth-generator.js +230 -13
  28. package/dist/core/scaffold/auth-generator.js.map +1 -1
  29. package/dist/core/scaffold/connector-functions-generator.d.ts.map +1 -1
  30. package/dist/core/scaffold/connector-functions-generator.js +4 -2
  31. package/dist/core/scaffold/connector-functions-generator.js.map +1 -1
  32. package/dist/core/scaffold/functions-generator.d.ts.map +1 -1
  33. package/dist/core/scaffold/functions-generator.js +4 -2
  34. package/dist/core/scaffold/functions-generator.js.map +1 -1
  35. package/dist/core/scaffold/model-parser.d.ts.map +1 -1
  36. package/dist/core/scaffold/model-parser.js +8 -3
  37. package/dist/core/scaffold/model-parser.js.map +1 -1
  38. package/dist/core/scaffold/ui-generator.d.ts +3 -0
  39. package/dist/core/scaffold/ui-generator.d.ts.map +1 -1
  40. package/dist/core/scaffold/ui-generator.js +12 -8
  41. package/dist/core/scaffold/ui-generator.js.map +1 -1
  42. package/dist/types/index.d.ts +34 -4
  43. package/dist/types/index.d.ts.map +1 -1
  44. package/dist/utils/package-manager.d.ts.map +1 -1
  45. package/dist/utils/package-manager.js +1 -0
  46. package/dist/utils/package-manager.js.map +1 -1
  47. package/package.json +1 -1
  48. package/src/__tests__/auth.test.ts +4 -0
  49. package/src/__tests__/config.test.ts +22 -1
  50. package/src/__tests__/mcp.test.ts +2 -2
  51. package/src/__tests__/multi-auth.test.ts +133 -0
  52. package/src/cli/commands/add-auth.ts +112 -2
  53. package/src/cli/commands/dev.ts +6 -3
  54. package/src/cli/commands/scaffold.ts +58 -14
  55. package/src/cli/index.ts +2 -0
  56. package/src/core/config.ts +69 -2
  57. package/src/core/mock/connector-mock-server.ts +2 -2
  58. package/src/core/project/manifest.ts +3 -3
  59. package/src/core/project/validation.ts +16 -0
  60. package/src/core/scaffold/auth-generator.ts +236 -14
  61. package/src/core/scaffold/connector-functions-generator.ts +4 -2
  62. package/src/core/scaffold/functions-generator.ts +4 -2
  63. package/src/core/scaffold/model-parser.ts +9 -3
  64. package/src/core/scaffold/ui-generator.ts +15 -8
  65. package/src/types/index.ts +35 -4
  66. package/src/utils/package-manager.ts +1 -0
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/types/index.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/types/index.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"package-manager.d.ts","sourceRoot":"","sources":["../../src/utils/package-manager.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,eAAe,EAAE,MAAM,UAAU,CAAC;AAE3C;;GAEG;AACH,MAAM,MAAM,cAAc,GAAG,KAAK,GAAG,MAAM,CAAC;AAE5C;;GAEG;AACH,MAAM,WAAW,sBAAsB;IACrC,uCAAuC;IACvC,IAAI,EAAE,cAAc,CAAC;IACrB,+DAA+D;IAC/D,OAAO,EAAE,MAAM,CAAC;IAChB,yEAAyE;IACzE,EAAE,EAAE,MAAM,CAAC;IACX,mDAAmD;IACnD,GAAG,EAAE,MAAM,CAAC;IACZ,6DAA6D;IAC7D,MAAM,EAAE,MAAM,CAAC;IACf,gEAAgE;IAChE,SAAS,EAAE,MAAM,CAAC;IAClB,oDAAoD;IACpD,IAAI,EAAE,MAAM,CAAC;IACb,6CAA6C;IAC7C,GAAG,EAAE,MAAM,CAAC;IACZ,2CAA2C;IAC3C,GAAG,EAAE,MAAM,CAAC;IACZ,sFAAsF;IACtF,SAAS,EAAE,CAAC,SAAS,EAAE,MAAM,KAAK,MAAM,CAAC;IACzC,+CAA+C;IAC/C,KAAK,EAAE,MAAM,CAAC;IACd,qGAAqG;IACrG,WAAW,EAAE,MAAM,CAAC;IACpB,0DAA0D;IAC1D,iBAAiB,EAAE,MAAM,GAAG,IAAI,CAAC;CAClC;AAED;;GAEG;AACH,wBAAgB,WAAW,CAAC,EAAE,EAAE,cAAc,GAAG,sBAAsB,CAmCtE;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,mBAAmB,IAAI,cAAc,CAEpD;AAcD;;;;;GAKG;AACH,wBAAgB,iBAAiB,CAAC,UAAU,CAAC,EAAE,MAAM,GAAG,cAAc,CAYrE;AAED;;;;;;;GAOG;AACH,wBAAgB,SAAS,CACvB,EAAE,EAAE,cAAc,EAClB,IAAI,EAAE,MAAM,EAAE,GACb;IAAE,GAAG,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,EAAE,CAAA;CAAE,CAEjC;AAED;;GAEG;AACH,wBAAgB,kBAAkB,CAAC,EAAE,EAAE,cAAc,EAAE,UAAU,EAAE,MAAM,EAAE;IAGrE,oCAAoC;;;;;;;;;;;;EAazC;AAED;;GAEG;AACH,wBAAgB,cAAc,CAAC,EAAE,EAAE,cAAc,GAAG,MAAM,CASzD;AAED,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,cAAc,EAAE,SAAS,GAAE,cAAqB,GAAG,MAAM,CAKlG;AAED,wBAAgB,qBAAqB,CAAC,IAAI,EAAE,cAAc,EAAE,SAAS,GAAE,cAAqB,GAAG,MAAM,CAKpG;AAED;;GAEG;AACH,wBAAgB,sBAAsB,CAAC,EAAE,EAAE,cAAc,GAAG,MAAM,CASjE;AAED;;GAEG;AACH,wBAAgB,cAAc,CAAC,EAAE,EAAE,cAAc,GAAG,MAAM,CAOzD;AAED;;GAEG;AACH,wBAAgB,oBAAoB,CAAC,EAAE,EAAE,cAAc,GAAG,MAAM,CAK/D;AAED;;GAEG;AACH,wBAAgB,uBAAuB,CACrC,EAAE,EAAE,cAAc,EAClB,eAAe,GAAE,eAA8B,GAC9C,MAAM,CASR"}
1
+ {"version":3,"file":"package-manager.d.ts","sourceRoot":"","sources":["../../src/utils/package-manager.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,eAAe,EAAE,MAAM,UAAU,CAAC;AAE3C;;GAEG;AACH,MAAM,MAAM,cAAc,GAAG,KAAK,GAAG,MAAM,CAAC;AAE5C;;GAEG;AACH,MAAM,WAAW,sBAAsB;IACrC,uCAAuC;IACvC,IAAI,EAAE,cAAc,CAAC;IACrB,+DAA+D;IAC/D,OAAO,EAAE,MAAM,CAAC;IAChB,yEAAyE;IACzE,EAAE,EAAE,MAAM,CAAC;IACX,mDAAmD;IACnD,GAAG,EAAE,MAAM,CAAC;IACZ,6DAA6D;IAC7D,MAAM,EAAE,MAAM,CAAC;IACf,gEAAgE;IAChE,SAAS,EAAE,MAAM,CAAC;IAClB,oDAAoD;IACpD,IAAI,EAAE,MAAM,CAAC;IACb,6CAA6C;IAC7C,GAAG,EAAE,MAAM,CAAC;IACZ,2CAA2C;IAC3C,GAAG,EAAE,MAAM,CAAC;IACZ,sFAAsF;IACtF,SAAS,EAAE,CAAC,SAAS,EAAE,MAAM,KAAK,MAAM,CAAC;IACzC,+CAA+C;IAC/C,KAAK,EAAE,MAAM,CAAC;IACd,qGAAqG;IACrG,WAAW,EAAE,MAAM,CAAC;IACpB,0DAA0D;IAC1D,iBAAiB,EAAE,MAAM,GAAG,IAAI,CAAC;CAClC;AAED;;GAEG;AACH,wBAAgB,WAAW,CAAC,EAAE,EAAE,cAAc,GAAG,sBAAsB,CAmCtE;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,mBAAmB,IAAI,cAAc,CAEpD;AAcD;;;;;GAKG;AACH,wBAAgB,iBAAiB,CAAC,UAAU,CAAC,EAAE,MAAM,GAAG,cAAc,CAYrE;AAED;;;;;;;GAOG;AACH,wBAAgB,SAAS,CACvB,EAAE,EAAE,cAAc,EAClB,IAAI,EAAE,MAAM,EAAE,GACb;IAAE,GAAG,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,EAAE,CAAA;CAAE,CAEjC;AAED;;GAEG;AACH,wBAAgB,kBAAkB,CAAC,EAAE,EAAE,cAAc,EAAE,UAAU,EAAE,MAAM,EAAE;IAGrE,oCAAoC;;;;;;;;;;;;EAazC;AAED;;GAEG;AACH,wBAAgB,cAAc,CAAC,EAAE,EAAE,cAAc,GAAG,MAAM,CASzD;AAED,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,cAAc,EAAE,SAAS,GAAE,cAAqB,GAAG,MAAM,CAMlG;AAED,wBAAgB,qBAAqB,CAAC,IAAI,EAAE,cAAc,EAAE,SAAS,GAAE,cAAqB,GAAG,MAAM,CAKpG;AAED;;GAEG;AACH,wBAAgB,sBAAsB,CAAC,EAAE,EAAE,cAAc,GAAG,MAAM,CASjE;AAED;;GAEG;AACH,wBAAgB,cAAc,CAAC,EAAE,EAAE,cAAc,GAAG,MAAM,CAOzD;AAED;;GAEG;AACH,wBAAgB,oBAAoB,CAAC,EAAE,EAAE,cAAc,GAAG,MAAM,CAK/D;AAED;;GAEG;AACH,wBAAgB,uBAAuB,CACrC,EAAE,EAAE,cAAc,EAClB,eAAe,GAAE,eAA8B,GAC9C,MAAM,CASR"}
@@ -173,6 +173,7 @@ function getCiSetupStep(pm) {
173
173
  return "";
174
174
  }
175
175
  function getCiInstallCommand(ciPm, projectPm = ciPm) {
176
+ void projectPm; // Reserved for package-manager-specific CI bridging.
176
177
  if (ciPm === "pnpm") {
177
178
  return getCommands(ciPm).ci;
178
179
  }
@@ -1 +1 @@
1
- {"version":3,"file":"package-manager.js","sourceRoot":"","sources":["../../src/utils/package-manager.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"package-manager.js","sourceRoot":"","sources":["../../src/utils/package-manager.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "swallowkit",
3
- "version": "1.0.0-beta.47",
3
+ "version": "1.0.0-beta.48",
4
4
  "description": "Type-safe schema-driven development toolkit for Next.js applications on Azure",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
@@ -443,6 +443,10 @@ describe("generateAuthImportTS", () => {
443
443
  });
444
444
 
445
445
  describe("generateAuthGuardTS", () => {
446
+ it("generates a named read/write policy guard", () => {
447
+ expect(generateAuthGuardTS({ read: "adminOnly", write: "lineUserOnly" }, "read")).toContain("requireAuth(request, \"adminOnly\")");
448
+ expect(generateAuthGuardTS({ policy: "adminOnly" }, "write")).toContain("requireAuth(request, \"adminOnly\")");
449
+ });
446
450
  it("generates authentication-only guard for empty policy", () => {
447
451
  const policy: ModelAuthPolicy = {};
448
452
  const readGuard = generateAuthGuardTS(policy, "read");
@@ -1,7 +1,28 @@
1
- import { validateConfig, loadConfigFromEnv } from "../core/config";
1
+ import { validateConfig, loadConfigFromEnv, normalizeAuthConfig } from "../core/config";
2
2
  import { SwallowKitConfig } from "../types";
3
3
 
4
4
  describe("validateConfig", () => {
5
+ it("normalizes a legacy provider as the default scheme", () => {
6
+ const auth = normalizeAuthConfig({ provider: "external-token", authorization: { defaultPolicy: "authenticated" } });
7
+ expect(auth?.schemes.default.provider).toBe("external-token");
8
+ expect(auth?.authorization.defaultPolicy).toBe("authenticated");
9
+ });
10
+
11
+ it("accepts SWA and external token named schemes", () => {
12
+ const result = validateConfig({ auth: { schemes: { admin: { provider: "swa" }, lineUser: { provider: "external-token" } }, authorization: { defaultPolicy: "anonymous", policies: { adminOnly: { schemes: ["admin"] }, lineUserOnly: { schemes: ["lineUser"] } } } } });
13
+ expect(result).toEqual({ valid: true, errors: [] });
14
+ });
15
+
16
+ it("rejects undefined scheme references and ambiguous bearer schemes", () => {
17
+ const missing = validateConfig({ auth: { schemes: { admin: { provider: "swa" } }, authorization: { defaultPolicy: "anonymous", policies: { bad: { schemes: ["missing"] } } } } });
18
+ expect(missing.errors.join("\n")).toContain("auth.authorization.policies.bad.schemes");
19
+ const ambiguous = validateConfig({ auth: { schemes: { a: { provider: "external-token" }, b: { provider: "external-token" } }, authorization: { defaultPolicy: "anonymous", policies: { bad: { schemes: ["a", "b"] } } } } });
20
+ expect(ambiguous.errors.join("\n")).toContain("deterministic");
21
+ });
22
+
23
+ it("normalizes public to anonymous", () => {
24
+ expect(normalizeAuthConfig({ provider: "none", authorization: { defaultPolicy: "public" } })?.authorization.defaultPolicy).toBe("anonymous");
25
+ });
5
26
  it("returns valid for a complete config", () => {
6
27
  const config: SwallowKitConfig = {
7
28
  database: { connectionString: "AccountEndpoint=https://..." },
@@ -9,7 +9,7 @@ const itWhenBuiltEntrypointExists = fs.existsSync(builtMcpEntrypoint) ? it : it.
9
9
 
10
10
  describe("SwallowKit MCP tool definitions", () => {
11
11
  it("delegates inspect_project to the machine CLI", async () => {
12
- const runner = jest.fn(async (_args: Parameters<MachineCliRunner>[0]) => ({
12
+ const runner = jest.fn(async () => ({
13
13
  stdout: JSON.stringify({
14
14
  ok: true,
15
15
  command: "inspect-project",
@@ -48,7 +48,7 @@ describe("SwallowKit MCP tool definitions", () => {
48
48
  });
49
49
 
50
50
  it("delegates scaffold_model with explicit args", async () => {
51
- const runner = jest.fn(async (_args: Parameters<MachineCliRunner>[0]) => ({
51
+ const runner = jest.fn(async () => ({
52
52
  stdout: JSON.stringify({
53
53
  ok: true,
54
54
  command: "generate-scaffold",
@@ -0,0 +1,133 @@
1
+ import * as fs from "fs";
2
+ import * as os from "os";
3
+ import * as path from "path";
4
+ import { addAuthCommand } from "../cli/commands/add-auth";
5
+ import {
6
+ generateBFFCallFunctionWithMultipleAuth,
7
+ generateNamedAuthRouterCSharp,
8
+ generateNamedAuthRouterPython,
9
+ generateNamedAuthRouterTS,
10
+ } from "../core/scaffold/auth-generator";
11
+ import { normalizeAuthConfig } from "../core/config";
12
+ import { parseAuthPolicy } from "../core/scaffold/model-parser";
13
+ import { createBasicModelInfo } from "./fixtures";
14
+ import { generateCSharpAzureFunctionsCRUD, generateCompactAzureFunctionsCRUD, generatePythonAzureFunctionsCRUD } from "../core/scaffold/functions-generator";
15
+
16
+ const auth = normalizeAuthConfig({
17
+ schemes: {
18
+ admin: { provider: "swa" },
19
+ lineUser: { provider: "external-token" },
20
+ },
21
+ authorization: {
22
+ defaultPolicy: "anonymous",
23
+ policies: {
24
+ adminOnly: { schemes: ["admin"], roles: ["authenticated"] },
25
+ lineUserOnly: { schemes: ["lineUser"], roles: ["authenticated"] },
26
+ },
27
+ },
28
+ })!;
29
+
30
+ describe("named authentication routers", () => {
31
+ it("generates deterministic TypeScript policy routing and normalized principals", () => {
32
+ const code = generateNamedAuthRouterTS(auth);
33
+ expect(code).toContain("policy.schemes.filter");
34
+ expect(code).toContain("candidates.length !== 1");
35
+ expect(code).toContain("subject: value.userId");
36
+ expect(code).toContain("scheme + ':' + principal.subject");
37
+ expect(code).toContain("new AuthError(403");
38
+ expect(code).toContain("new AuthError(503");
39
+ expect(code).not.toContain("JWT_SECRET");
40
+ });
41
+
42
+ it("generates equivalent C# and Python named guards", () => {
43
+ const csharp = generateNamedAuthRouterCSharp(auth);
44
+ const python = generateNamedAuthRouterPython(auth);
45
+ expect(csharp).toContain("record AuthPrincipal(string Subject, string Scheme, string Issuer");
46
+ expect(csharp).toContain("candidates.Length != 1");
47
+ expect(csharp).toContain("HttpStatusCode.Forbidden");
48
+ expect(python).toContain('principal["scheme"] + ":" + principal["subject"]');
49
+ expect(python).toContain("len(candidates) != 1");
50
+ expect(python).toContain("AuthError(503");
51
+ });
52
+
53
+ it("generates valid branch structure for an SWA-only Python router", () => {
54
+ const swaOnly = normalizeAuthConfig({ schemes: { admin: { provider: "swa", swa: { allowedProviders: ["github"] } } }, authorization: { defaultPolicy: "anonymous", policies: { adminOnly: { schemes: ["admin"] } } } })!;
55
+ const python = generateNamedAuthRouterPython(swaOnly);
56
+ expect(python).toContain(' if PROVIDERS[scheme] == "swa":');
57
+ expect(python).not.toContain(' elif PROVIDERS[scheme] == "swa":');
58
+ expect(python).toContain("ALLOWED_PROVIDERS");
59
+ expect(generateNamedAuthRouterCSharp(swaOnly)).toContain("AllowedProviders[scheme]");
60
+ });
61
+
62
+ it("scaffolds named read/write guards for all Functions languages", () => {
63
+ const policy = { read: "adminOnly", write: "lineUserOnly" };
64
+ const model = createBasicModelInfo();
65
+ const ts = generateCompactAzureFunctionsCRUD(model, "@fixture/shared", policy);
66
+ const cs = generateCSharpAzureFunctionsCRUD(model, policy);
67
+ const py = generatePythonAzureFunctionsCRUD(model, policy).blueprint;
68
+ expect(ts).toContain("./auth/auth-router");
69
+ expect(ts).toContain('requireAuth(request, "adminOnly")');
70
+ expect(ts).toContain('requireAuth(request, "lineUserOnly")');
71
+ expect(cs).toContain('AuthRouter.Authorize(request, "adminOnly")');
72
+ expect(cs).toContain('AuthRouter.Authorize(request, "lineUserOnly")');
73
+ expect(py).toContain("from auth.auth_router import");
74
+ expect(py).toContain('require_auth(req, "adminOnly")');
75
+ expect(py).toContain('require_auth(req, "lineUserOnly")');
76
+ });
77
+
78
+ it("forwards both credential sources and the Functions host key", () => {
79
+ const code = generateBFFCallFunctionWithMultipleAuth();
80
+ expect(code).toContain("fetchHeaders['Authorization']");
81
+ expect(code).toContain("fetchHeaders['x-ms-client-principal']");
82
+ expect(code).toContain("'x-functions-key'");
83
+ expect(code).not.toMatch(/console\.log\([^\n]*(authorization|principal|cookie)/i);
84
+ });
85
+
86
+ it("parses model-wide and operation-specific named policies", () => {
87
+ expect(parseAuthPolicy("export const authPolicy = { policy: 'adminOnly' };"))
88
+ .toEqual({ policy: "adminOnly" });
89
+ expect(parseAuthPolicy("export const authPolicy = { read: 'adminOnly', write: 'lineUserOnly' };"))
90
+ .toEqual({ read: "adminOnly", write: "lineUserOnly" });
91
+ });
92
+ });
93
+
94
+ describe("add-auth named scheme CLI", () => {
95
+ const originalCwd = process.cwd();
96
+ let root: string;
97
+
98
+ beforeEach(() => {
99
+ root = fs.mkdtempSync(path.join(os.tmpdir(), "swallowkit-multi-auth-"));
100
+ fs.writeFileSync(path.join(root, "package.json"), JSON.stringify({ name: "fixture" }));
101
+ fs.writeFileSync(path.join(root, "swallowkit.config.json"), JSON.stringify({ backend: { language: "typescript" }, auth: { schemes: {}, authorization: { defaultPolicy: "anonymous", policies: {} } } }, null, 2));
102
+ process.chdir(root);
103
+ });
104
+
105
+ afterEach(() => {
106
+ process.chdir(originalCwd);
107
+ fs.rmSync(root, { recursive: true, force: true });
108
+ });
109
+
110
+ it("adds two schemes without overwriting the first verifier", async () => {
111
+ await addAuthCommand({ scheme: "admin", provider: "swa" });
112
+ await addAuthCommand({ scheme: "lineUser", provider: "external-token" });
113
+ const verifier = path.join(root, "functions", "src", "auth", "schemes", "line-user", "verifier.ts");
114
+ fs.writeFileSync(verifier, "// user verifier\n", "utf-8");
115
+ const config = JSON.parse(fs.readFileSync(path.join(root, "swallowkit.config.json"), "utf-8"));
116
+ expect(config.auth.schemes.admin.provider).toBe("swa");
117
+ expect(config.auth.schemes.lineUser.provider).toBe("external-token");
118
+ await expect(addAuthCommand({ scheme: "lineUser", provider: "external-token" })).rejects.toThrow("already exists");
119
+ expect(fs.readFileSync(verifier, "utf-8")).toBe("// user verifier\n");
120
+ expect(fs.readFileSync(path.join(root, "lib", "api", "call-function.ts"), "utf-8")).toContain("x-functions-key");
121
+ });
122
+
123
+ it("updates a JavaScript config that already has a trailing comma", async () => {
124
+ fs.rmSync(path.join(root, "swallowkit.config.json"));
125
+ fs.writeFileSync(path.join(root, "swallowkit.config.js"), "module.exports = {\n backend: { language: 'typescript' },\n api: { endpoint: '/api/test' },\n};\n");
126
+ await addAuthCommand({ scheme: "admin", provider: "swa" });
127
+ const content = fs.readFileSync(path.join(root, "swallowkit.config.js"), "utf-8");
128
+ expect(content).not.toContain(",,");
129
+ const configModule = { exports: {} as Record<string, unknown> };
130
+ new Function("module", content)(configModule);
131
+ expect((configModule.exports as { auth: { schemes: { admin: { provider: string } } } }).auth.schemes.admin.provider).toBe("swa");
132
+ });
133
+ });
@@ -5,7 +5,7 @@
5
5
 
6
6
  import * as fs from "fs";
7
7
  import * as path from "path";
8
- import { ensureSwallowKitProject, getBackendLanguage, getConnectorDefinition, getFullConfig } from "../../core/config";
8
+ import { ensureSwallowKitProject, getBackendLanguage, getConnectorDefinition, getValidatedFullConfig } from "../../core/config";
9
9
  import { AuthProvider, BackendLanguage, CustomJwtConfig, RdbConnectorConfig } from "../../types";
10
10
  import {
11
11
  generateAuthModels,
@@ -23,6 +23,7 @@ import {
23
23
  generateAuthContext,
24
24
  generateBFFCallFunctionWithAuth,
25
25
  generateBFFCallFunctionWithSwaAuth,
26
+ generateBFFCallFunctionWithMultipleAuth,
26
27
  generateSwaAuthHelperTS,
27
28
  generateSwaAuthHelperCSharp,
28
29
  generateSwaAuthHelperPython,
@@ -39,12 +40,15 @@ import {
39
40
  generateExternalTokenVerifierPython,
40
41
  generateExternalTokenHelperPython,
41
42
  generateExternalAuthMePython,
43
+ generateNamedExternalTokenVerifierCSharp,
44
+ generateNamedExternalTokenVerifierPython,
42
45
  } from "../../core/scaffold/auth-generator";
43
46
  import { syncProjectManifest } from "../../core/project/manifest";
44
47
  import { buildSharedTsConfig } from "./init";
45
48
 
46
49
  interface AddAuthOptions {
47
50
  provider?: string;
51
+ scheme?: string;
48
52
  }
49
53
 
50
54
  function writeIfMissing(filePath: string, content: string): void {
@@ -239,9 +243,18 @@ export async function addAuthCommand(options: AddAuthOptions) {
239
243
  }
240
244
 
241
245
  const backendLanguage = getBackendLanguage();
242
- const config = getFullConfig();
246
+ const config = getValidatedFullConfig();
243
247
  const cwd = process.cwd();
244
248
 
249
+ if (options.scheme) {
250
+ if (!/^[A-Za-z][A-Za-z0-9_-]*$/.test(options.scheme)) throw new Error("--scheme must start with a letter and contain only letters, digits, '_' or '-'");
251
+ if (provider === "none" || provider === "swa-custom") throw new Error(`Provider '${provider}' cannot be added as a named scheme`);
252
+ addNamedScheme(cwd, options.scheme, provider, backendLanguage);
253
+ await syncProjectManifest();
254
+ console.log(`\n Named authentication scheme '${options.scheme}' added.`);
255
+ return;
256
+ }
257
+
245
258
  if (provider === "swa-custom") {
246
259
  throw new Error("The swa-custom provider is not implemented. Use --provider swa or --provider custom-jwt.");
247
260
  }
@@ -364,6 +377,103 @@ export async function addAuthCommand(options: AddAuthOptions) {
364
377
  console.log(` 5. Run scaffold to regenerate functions with auth guards`);
365
378
  }
366
379
 
380
+ function findObjectEnd(content: string, open: number): number {
381
+ let depth = 0, quote = "";
382
+ for (let i = open; i < content.length; i++) {
383
+ const ch = content[i];
384
+ if (quote) { if (ch === quote && content[i - 1] !== "\\") quote = ""; continue; }
385
+ if (ch === "'" || ch === '"' || ch === "`") { quote = ch; continue; }
386
+ if (ch === "{") depth++;
387
+ if (ch === "}" && --depth === 0) return i;
388
+ }
389
+ return -1;
390
+ }
391
+
392
+ function updateConfigWithNamedScheme(cwd: string, scheme: string, provider: AuthProvider): void {
393
+ const jsPath = path.join(cwd, "swallowkit.config.js");
394
+ const jsonPath = path.join(cwd, "swallowkit.config.json");
395
+ const configPath = fs.existsSync(jsPath) ? jsPath : jsonPath;
396
+ if (!fs.existsSync(configPath)) throw new Error("swallowkit.config.js or swallowkit.config.json is required");
397
+ if (configPath.endsWith(".json")) {
398
+ const value = JSON.parse(fs.readFileSync(configPath, "utf-8"));
399
+ value.auth ??= {};
400
+ value.auth.schemes ??= {};
401
+ if (value.auth.schemes[scheme]) throw new Error(`auth.schemes.${scheme} already exists; no files were changed`);
402
+ value.auth.schemes[scheme] = provider === "custom-jwt" ? { provider, customJwt: defaultCustomJwtConfig() } : { provider };
403
+ value.auth.authorization ??= { defaultPolicy: "anonymous", policies: {} };
404
+ fs.writeFileSync(configPath, JSON.stringify(value, null, 2) + "\n", "utf-8");
405
+ return;
406
+ }
407
+ let content = fs.readFileSync(configPath, "utf-8");
408
+ const authMatch = /\bauth\s*:\s*\{/.exec(content);
409
+ const customJwt = defaultCustomJwtConfig();
410
+ const entry = provider === "custom-jwt"
411
+ ? `\n ${scheme}: { provider: 'custom-jwt', customJwt: ${JSON.stringify(customJwt)} },`
412
+ : `\n ${scheme}: { provider: '${provider}' },`;
413
+ if (!authMatch) {
414
+ const rootEnd = content.lastIndexOf("}");
415
+ const beforeRootEnd = content.slice(0, rootEnd).trimEnd();
416
+ const separator = beforeRootEnd.endsWith(",") || beforeRootEnd.endsWith("{") ? "" : ",";
417
+ content = `${beforeRootEnd}${separator}\n auth: {\n schemes: {${entry}\n },\n authorization: { defaultPolicy: 'anonymous', policies: {} },\n },\n${content.slice(rootEnd)}`;
418
+ } else {
419
+ const authOpen = content.indexOf("{", authMatch.index);
420
+ const authEnd = findObjectEnd(content, authOpen);
421
+ const authBody = content.slice(authOpen + 1, authEnd);
422
+ const schemesMatch = /\bschemes\s*:\s*\{/.exec(authBody);
423
+ if (schemesMatch) {
424
+ const schemesOpen = authOpen + 1 + authBody.indexOf("{", schemesMatch.index);
425
+ const schemesEnd = findObjectEnd(content, schemesOpen);
426
+ const existing = content.slice(schemesOpen + 1, schemesEnd);
427
+ if (new RegExp(`(^|[,\\s])${scheme}\\s*:`).test(existing)) throw new Error(`auth.schemes.${scheme} already exists; no files were changed`);
428
+ content = content.slice(0, schemesEnd) + entry + "\n " + content.slice(schemesEnd);
429
+ } else {
430
+ content = content.slice(0, authOpen + 1) + `\n schemes: {${entry}\n },` + content.slice(authOpen + 1);
431
+ }
432
+ }
433
+ fs.writeFileSync(configPath, content, "utf-8");
434
+ }
435
+
436
+ function addNamedScheme(cwd: string, scheme: string, provider: AuthProvider, language: BackendLanguage): void {
437
+ // Validate/update config before creating files, so duplicate names stop safely.
438
+ updateConfigWithNamedScheme(cwd, scheme, provider);
439
+ const slug = scheme.replace(/([a-z0-9])([A-Z])/g, "$1-$2").replace(/_/g, "-").toLowerCase();
440
+ if (language === "typescript") {
441
+ const dir = path.join(cwd, "functions", "src", "auth", "schemes", slug);
442
+ if (provider === "external-token") writeIfMissing(path.join(dir, "verifier.ts"), generateExternalTokenVerifierTS());
443
+ else if (provider === "swa") writeIfMissing(path.join(dir, "adapter.ts"), generateSwaAuthHelperTS());
444
+ else writeIfMissing(path.join(dir, "jwt-helper.ts"), generateJwtHelperTS());
445
+ } else if (language === "csharp") {
446
+ const dir = path.join(cwd, "functions", "Auth", "Schemes", slug);
447
+ if (provider === "external-token") writeIfMissing(path.join(dir, "ExternalTokenVerifier.cs"), generateNamedExternalTokenVerifierCSharp(scheme));
448
+ else if (provider === "swa") writeIfMissing(path.join(dir, "SwaAdapter.cs"), generateSwaAuthHelperCSharp());
449
+ else writeIfMissing(path.join(dir, "JwtHelper.cs"), generateJwtHelperCSharp());
450
+ } else {
451
+ const dir = path.join(cwd, "functions", "auth", "schemes", slug.replace(/-/g, "_"));
452
+ if (provider === "external-token") writeIfMissing(path.join(dir, "verifier.py"), generateNamedExternalTokenVerifierPython(scheme));
453
+ else if (provider === "swa") writeIfMissing(path.join(dir, "adapter.py"), generateSwaAuthHelperPython());
454
+ else writeIfMissing(path.join(dir, "jwt_helper.py"), generateJwtHelperPython());
455
+ }
456
+ const clientDir = path.join(cwd, "lib", "auth", "schemes", slug);
457
+ if (provider === "external-token") {
458
+ writeIfMissing(path.join(clientDir, "token-adapter.ts"), generateExternalTokenAdapter());
459
+ writeIfMissing(path.join(clientDir, "authenticated-fetch.ts"), generateAuthenticatedFetch().replace("'./external-token-adapter'", "'./token-adapter'"));
460
+ writeIfMissing(path.join(clientDir, "auth-context.tsx"), generateExternalTokenAuthContext().replace(/external-token-adapter/g, "token-adapter"));
461
+ } else if (provider === "swa") {
462
+ writeIfMissing(path.join(clientDir, "auth-context.tsx"), generateSwaAuthContext());
463
+ } else if (provider === "custom-jwt") {
464
+ writeIfMissing(path.join(clientDir, "auth-context.tsx"), generateAuthContext());
465
+ }
466
+ const callFunctionPath = path.join(cwd, "lib", "api", "call-function.ts");
467
+ if (!fs.existsSync(callFunctionPath)) writeIfMissing(callFunctionPath, generateBFFCallFunctionWithMultipleAuth());
468
+ else {
469
+ const current = fs.readFileSync(callFunctionPath, "utf-8");
470
+ if (!current.includes("x-ms-client-principal") || !current.includes("fetchHeaders['Authorization']")) {
471
+ if (current.includes("SwallowKit BFF Call Function Helper")) fs.writeFileSync(callFunctionPath, generateBFFCallFunctionWithMultipleAuth(), "utf-8");
472
+ else console.warn(" Existing customized lib/api/call-function.ts was preserved. Ensure it forwards Bearer and SWA credentials without logging them.");
473
+ }
474
+ }
475
+ }
476
+
367
477
  /**
368
478
  * Ensure the shared package has proper build infrastructure
369
479
  * (tsconfig.json, build script, typescript devDependency).
@@ -7,7 +7,7 @@ import * as fs from 'fs';
7
7
  import * as os from 'os';
8
8
  import * as net from 'net';
9
9
  import { CosmosClient, PartitionKeyKind } from '@azure/cosmos';
10
- import { ensureSwallowKitProject, getBackendLanguage, getAuthConfig } from '../../core/config';
10
+ import { ensureSwallowKitProject, getBackendLanguage, getAuthConfig, normalizeAuthConfig } from '../../core/config';
11
11
  import { ModelInfo } from '../../core/scaffold/model-parser';
12
12
  import {
13
13
  applyDevSeedEnvironment,
@@ -648,7 +648,8 @@ async function startDevEnvironment(options: DevOptions) {
648
648
  const pmCmd = getCommands(pm);
649
649
  const backendLanguage = getBackendLanguage();
650
650
  const authConfig = getAuthConfig();
651
- const useSwaEmulator = authConfig?.provider === 'swa' && !options.noSwa;
651
+ const normalizedAuth = normalizeAuthConfig(authConfig);
652
+ const useSwaEmulator = Boolean(normalizedAuth && Object.values(normalizedAuth.schemes).some(scheme => scheme.provider === 'swa')) && !options.noSwa;
652
653
  const swaCommand = useSwaEmulator ? await resolveSwaCliCommand(process.cwd()) : null;
653
654
 
654
655
  if (useSwaEmulator && !swaCommand) {
@@ -981,7 +982,9 @@ async function startDevEnvironment(options: DevOptions) {
981
982
  passwordHashColumn: authConfig.customJwt.passwordHashColumn,
982
983
  rolesColumn: authConfig.customJwt.rolesColumn,
983
984
  },
984
- defaultPolicy: authConfig.authorization?.defaultPolicy,
985
+ defaultPolicy: authConfig.authorization?.defaultPolicy === "public" ? "anonymous" :
986
+ authConfig.authorization?.defaultPolicy === "authenticated" || authConfig.authorization?.defaultPolicy === "anonymous"
987
+ ? authConfig.authorization.defaultPolicy : undefined,
985
988
  };
986
989
  }
987
990
 
@@ -6,7 +6,7 @@
6
6
  import * as fs from "fs";
7
7
  import * as path from "path";
8
8
  import { spawnSync } from "child_process";
9
- import { getBackendLanguage, getConnectorDefinition, getAuthConfig, ensureSwallowKitProject } from "../../core/config";
9
+ import { getBackendLanguage, getConnectorDefinition, getAuthConfig, getFullConfig, getNormalizedAuthConfig, ensureSwallowKitProject, normalizeAuthConfig, validateConfig } from "../../core/config";
10
10
  import { ModelInfo, parseModelFile, toKebabCase, toPascalCase, toCamelCase } from "../../core/scaffold/model-parser";
11
11
  import {
12
12
  generateCSharpAzureFunctionsCRUD,
@@ -42,6 +42,7 @@ import {
42
42
  AuthConfig,
43
43
  } from "../../types";
44
44
  import { syncProjectManifest } from "../../core/project/manifest";
45
+ import { generateBFFCallFunctionWithAuth, generateBFFCallFunctionWithMultipleAuth, generateBFFCallFunctionWithSwaAuth, generateNamedAuthRouterCSharp, generateNamedAuthRouterPython, generateNamedAuthRouterTS } from "../../core/scaffold/auth-generator";
45
46
 
46
47
  interface ScaffoldOptions {
47
48
  model: string; // モデルファイルのパス(例: "lib/models/todo.ts" or "todo")
@@ -74,6 +75,9 @@ export async function scaffoldCommand(options: ScaffoldOptions) {
74
75
  // SwallowKit プロジェクトディレクトリかどうかを検証
75
76
  ensureSwallowKitProject("scaffold");
76
77
 
78
+ const configValidation = validateConfig(getFullConfig());
79
+ if (!configValidation.valid) throw new Error(`Invalid SwallowKit configuration:\n${configValidation.errors.map(error => `- ${error}`).join("\n")}`);
80
+
77
81
  console.log("🏗️ SwallowKit Scaffold: Generating CRUD operations...\n");
78
82
 
79
83
  try {
@@ -159,11 +163,11 @@ export async function scaffoldCommand(options: ScaffoldOptions) {
159
163
  const uiAuthPolicy = resolveAuthPolicy(modelInfo, uiAuthConfig);
160
164
  const uiAuthOptions: UIAuthOptions | undefined =
161
165
  uiAuthPolicy && uiAuthConfig && uiAuthConfig.provider !== 'none'
162
- ? { authPolicy: uiAuthPolicy }
166
+ ? createUIAuthOptions(uiAuthPolicy, uiAuthConfig)
163
167
  : undefined;
164
168
  await generateUIComponents(modelInfo, sharedPackageName, uiAuthOptions);
165
- if (uiAuthConfig?.provider === 'external-token') {
166
- applyExternalTokenFetchToGeneratedUi(modelInfo);
169
+ if (uiAuthOptions?.authenticatedFetchImport) {
170
+ applyExternalTokenFetchToGeneratedUi(modelInfo, uiAuthOptions.authenticatedFetchImport);
167
171
  }
168
172
  await updateNavigationMenu(modelInfo);
169
173
  }
@@ -193,7 +197,7 @@ export async function scaffoldCommand(options: ScaffoldOptions) {
193
197
  }
194
198
  }
195
199
 
196
- function applyExternalTokenFetchToGeneratedUi(modelInfo: ModelInfo): void {
200
+ function applyExternalTokenFetchToGeneratedUi(modelInfo: ModelInfo, importPath = '@/lib/auth/authenticated-fetch'): void {
197
201
  const uiRoot = path.join(process.cwd(), 'app', toKebabCase(modelInfo.name));
198
202
  if (!fs.existsSync(uiRoot)) return;
199
203
  const visit = (dir: string): void => {
@@ -208,9 +212,9 @@ function applyExternalTokenFetchToGeneratedUi(modelInfo: ModelInfo): void {
208
212
  /(if \(!res\.ok\) throw new Error\([^\n]+\);)/g,
209
213
  `if (res.status === 401) throw new Error('Authentication required');\n $1`
210
214
  );
211
- if (!content.includes("@/lib/auth/authenticated-fetch")) {
215
+ if (!content.includes(importPath)) {
212
216
  const directive = content.match(/^'use client';\s*\r?\n/)?.[0] ?? '';
213
- content = `${directive}import { authenticatedFetch } from '@/lib/auth/authenticated-fetch';\n${content.slice(directive.length)}`;
217
+ content = `${directive}import { authenticatedFetch } from '${importPath}';\n${content.slice(directive.length)}`;
214
218
  }
215
219
  fs.writeFileSync(target, content, 'utf-8');
216
220
  }
@@ -224,9 +228,13 @@ function applyExternalTokenFetchToGeneratedUi(modelInfo: ModelInfo): void {
224
228
  * - なければ auth.authorization.defaultPolicy に従う
225
229
  * - auth 設定がなければ undefined(ガードなし)
226
230
  */
227
- function resolveAuthPolicy(modelInfo: ModelInfo, authConfig: AuthConfig | undefined): ModelAuthPolicy | undefined {
231
+ export function resolveAuthPolicy(modelInfo: ModelInfo, authConfig: AuthConfig | undefined): ModelAuthPolicy | undefined {
228
232
  // モデルに明示的な authPolicy がある場合はそれを使用
229
233
  if (modelInfo.authPolicy) {
234
+ const normalized = normalizeAuthConfig(authConfig);
235
+ for (const policyName of [modelInfo.authPolicy.policy, typeof modelInfo.authPolicy.read === 'string' ? modelInfo.authPolicy.read : undefined, typeof modelInfo.authPolicy.write === 'string' ? modelInfo.authPolicy.write : undefined].filter((value): value is string => Boolean(value))) {
236
+ if (!normalized?.authorization.policies[policyName]) throw new Error(`Model '${modelInfo.name}' references undefined auth policy '${policyName}'. Define auth.authorization.policies.${policyName}.`);
237
+ }
230
238
  return modelInfo.authPolicy;
231
239
  }
232
240
 
@@ -236,11 +244,13 @@ function resolveAuthPolicy(modelInfo: ModelInfo, authConfig: AuthConfig | undefi
236
244
  }
237
245
 
238
246
  // defaultPolicy が 'authenticated' なら認証のみ(ロール指定なし)のポリシーを返す
239
- const defaultPolicy = authConfig.authorization?.defaultPolicy ?? 'authenticated';
247
+ const defaultPolicy = authConfig.authorization?.defaultPolicy === 'public' ? 'anonymous' : authConfig.authorization?.defaultPolicy ?? 'authenticated';
240
248
  if (defaultPolicy === 'authenticated') {
241
249
  return {}; // 空のポリシー = 認証のみ、ロール制限なし
242
250
  }
243
251
 
252
+ if (defaultPolicy !== 'anonymous') return { policy: defaultPolicy };
253
+
244
254
  // defaultPolicy が 'anonymous' なら認証不要
245
255
  return undefined;
246
256
  }
@@ -330,13 +340,14 @@ async function generateCallFunctionHelper(): Promise<void> {
330
340
 
331
341
  // auth 設定がある場合は Authorization ヘッダー転送版を生成
332
342
  const authConfig = getAuthConfig();
333
- const hasAuth = authConfig && authConfig.provider !== 'none';
343
+ const normalizedAuth = normalizeAuthConfig(authConfig);
344
+ const hasAuth = Boolean(normalizedAuth && Object.keys(normalizedAuth.schemes).length > 0);
334
345
  let helperCode: string;
335
346
  if (hasAuth) {
336
- const { generateBFFCallFunctionWithAuth, generateBFFCallFunctionWithSwaAuth } = await import("../../core/scaffold/auth-generator");
337
- helperCode = authConfig?.provider === "swa"
338
- ? generateBFFCallFunctionWithSwaAuth()
339
- : generateBFFCallFunctionWithAuth();
347
+ const providers = new Set(Object.values(normalizedAuth!.schemes).map(scheme => scheme.provider));
348
+ helperCode = normalizedAuth!.schemes.default && Object.keys(normalizedAuth!.schemes).length === 1
349
+ ? authConfig?.provider === "swa" ? generateBFFCallFunctionWithSwaAuth() : generateBFFCallFunctionWithAuth()
350
+ : providers.has("swa") ? generateBFFCallFunctionWithMultipleAuth() : generateBFFCallFunctionWithAuth();
340
351
  } else {
341
352
  helperCode = generateBFFCallFunction();
342
353
  }
@@ -365,6 +376,12 @@ async function generateFunctionsCode(
365
376
 
366
377
  const modelKebab = toKebabCase(modelInfo.name);
367
378
  if (backendLanguage === "typescript") {
379
+ const normalizedAuth = getNormalizedAuthConfig();
380
+ if (normalizedAuth && Object.keys(normalizedAuth.schemes).some(name => name !== "default")) {
381
+ const routerPath = path.join(process.cwd(), functionsDir, "src", "auth", "auth-router.ts");
382
+ fs.mkdirSync(path.dirname(routerPath), { recursive: true });
383
+ fs.writeFileSync(routerPath, generateNamedAuthRouterTS(normalizedAuth), "utf-8");
384
+ }
368
385
  const functionFilePath = path.join(
369
386
  process.cwd(),
370
387
  functionsDir,
@@ -384,6 +401,12 @@ async function generateFunctionsCode(
384
401
  }
385
402
 
386
403
  if (backendLanguage === "csharp") {
404
+ const normalizedAuth = getNormalizedAuthConfig();
405
+ if (normalizedAuth && Object.keys(normalizedAuth.schemes).some(name => name !== "default")) {
406
+ const routerPath = path.join(process.cwd(), functionsDir, "Auth", "AuthRouter.cs");
407
+ fs.mkdirSync(path.dirname(routerPath), { recursive: true });
408
+ fs.writeFileSync(routerPath, generateNamedAuthRouterCSharp(normalizedAuth), "utf-8");
409
+ }
387
410
  const crudDir = path.join(process.cwd(), functionsDir, "Crud");
388
411
  const functionFilePath = path.join(crudDir, `${modelInfo.name}CrudFunctions.cs`);
389
412
  fs.mkdirSync(crudDir, { recursive: true });
@@ -400,6 +423,13 @@ async function generateFunctionsCode(
400
423
  return;
401
424
  }
402
425
 
426
+ const normalizedAuth = getNormalizedAuthConfig();
427
+ if (normalizedAuth && Object.keys(normalizedAuth.schemes).some(name => name !== "default")) {
428
+ const routerPath = path.join(process.cwd(), functionsDir, "auth", "auth_router.py");
429
+ fs.mkdirSync(path.dirname(routerPath), { recursive: true });
430
+ fs.writeFileSync(routerPath, generateNamedAuthRouterPython(normalizedAuth), "utf-8");
431
+ }
432
+
403
433
  const blueprintsDir = path.join(process.cwd(), functionsDir, "blueprints");
404
434
  const blueprintPath = path.join(blueprintsDir, `${modelKebab.replace(/-/g, "_")}.py`);
405
435
  fs.mkdirSync(blueprintsDir, { recursive: true });
@@ -410,6 +440,20 @@ async function generateFunctionsCode(
410
440
  console.log(`✅ Created: ${blueprintPath}`);
411
441
  }
412
442
 
443
+ function createUIAuthOptions(policy: ModelAuthPolicy, authConfig: AuthConfig): UIAuthOptions {
444
+ const normalized = normalizeAuthConfig(authConfig);
445
+ const readPolicyName = typeof policy.read === 'string' ? policy.read : policy.policy;
446
+ const writePolicyName = typeof policy.write === 'string' ? policy.write : policy.policy;
447
+ const readNamed = readPolicyName ? normalized?.authorization.policies[readPolicyName] : undefined;
448
+ const named = writePolicyName ? normalized?.authorization.policies[writePolicyName] : undefined;
449
+ const writeRoles = named?.roles ?? (Array.isArray(policy.write) ? policy.write : policy.roles) ?? [];
450
+ const externalScheme = [...(readNamed?.schemes ?? []), ...(named?.schemes ?? [])].find(name => normalized?.schemes[name]?.provider === 'external-token');
451
+ const authScheme = readNamed?.schemes[0] ?? named?.schemes[0];
452
+ const authenticatedFetchImport = externalScheme ? `@/lib/auth/schemes/${toKebabCase(externalScheme)}/authenticated-fetch` : authConfig.provider === 'external-token' ? '@/lib/auth/authenticated-fetch' : undefined;
453
+ const authContextImport = authScheme ? `@/lib/auth/schemes/${toKebabCase(authScheme)}/auth-context` : '@/lib/auth/auth-context';
454
+ return { authPolicy: policy, writeRoles, authenticatedFetchImport, authContextImport };
455
+ }
456
+
413
457
  /**
414
458
  * コネクタモデル用 Azure Functions コード生成
415
459
  */
package/src/cli/index.ts CHANGED
@@ -171,9 +171,11 @@ export function createProgram(devCommandOverride: Command = devCommand): Command
171
171
  .command("add-auth")
172
172
  .description("Add authentication and authorization to the project")
173
173
  .option("--provider <provider>", "Auth provider: custom-jwt | swa | external-token | swa-custom | none", "custom-jwt")
174
+ .option("--scheme <name>", "Add a named authentication scheme")
174
175
  .action((options) => {
175
176
  addAuthCommand({
176
177
  provider: options.provider,
178
+ scheme: options.scheme,
177
179
  });
178
180
  });
179
181