swallowkit 1.0.0-beta.57 → 1.0.0-beta.59
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/README.ja.md +1 -0
- package/README.md +1 -0
- package/dist/cli/commands/add-auth.d.ts +3 -1
- package/dist/cli/commands/add-auth.d.ts.map +1 -1
- package/dist/cli/commands/add-auth.js +55 -21
- package/dist/cli/commands/add-auth.js.map +1 -1
- package/dist/cli/commands/init.d.ts.map +1 -1
- package/dist/cli/commands/init.js +12 -498
- package/dist/cli/commands/init.js.map +1 -1
- package/dist/cli/index.d.ts.map +1 -1
- package/dist/cli/index.js +2 -0
- package/dist/cli/index.js.map +1 -1
- package/dist/core/operations/auth-operations.d.ts +4 -0
- package/dist/core/operations/auth-operations.d.ts.map +1 -1
- package/dist/core/operations/auth-operations.js +5 -2
- package/dist/core/operations/auth-operations.js.map +1 -1
- package/dist/core/operations/create-model.d.ts.map +1 -1
- package/dist/core/operations/create-model.js +6 -2
- package/dist/core/operations/create-model.js.map +1 -1
- package/dist/core/project/agent-instructions.d.ts +29 -0
- package/dist/core/project/agent-instructions.d.ts.map +1 -0
- package/dist/core/project/agent-instructions.js +159 -0
- package/dist/core/project/agent-instructions.js.map +1 -0
- package/dist/core/project/capabilities.d.ts +58 -0
- package/dist/core/project/capabilities.d.ts.map +1 -0
- package/dist/core/project/capabilities.js +135 -0
- package/dist/core/project/capabilities.js.map +1 -0
- package/dist/core/project/validation.d.ts.map +1 -1
- package/dist/core/project/validation.js +48 -0
- package/dist/core/project/validation.js.map +1 -1
- package/dist/core/project/workflows.d.ts.map +1 -1
- package/dist/core/project/workflows.js +46 -2
- package/dist/core/project/workflows.js.map +1 -1
- package/dist/core/scaffold/auth-generator.d.ts.map +1 -1
- package/dist/core/scaffold/auth-generator.js +6 -2
- package/dist/core/scaffold/auth-generator.js.map +1 -1
- package/dist/core/verify/index.d.ts +7 -0
- package/dist/core/verify/index.d.ts.map +1 -1
- package/dist/core/verify/index.js +69 -0
- package/dist/core/verify/index.js.map +1 -1
- package/dist/machine/index.d.ts.map +1 -1
- package/dist/machine/index.js +117 -41
- package/dist/machine/index.js.map +1 -1
- package/dist/mcp/index.d.ts.map +1 -1
- package/dist/mcp/index.js +32 -10
- package/dist/mcp/index.js.map +1 -1
- package/package.json +1 -1
- package/src/__tests__/agent-instructions.test.ts +237 -0
- package/src/__tests__/agent-loop-phase34.test.ts +66 -2
- package/src/__tests__/auth.test.ts +9 -0
- package/src/__tests__/init.test.ts +2 -0
- package/src/__tests__/machine.test.ts +15 -0
- package/src/__tests__/multi-auth.test.ts +12 -0
- package/src/__tests__/plan-apply.test.ts +38 -0
- package/src/cli/commands/add-auth.ts +59 -21
- package/src/cli/commands/init.ts +19 -525
- package/src/cli/index.ts +2 -0
- package/src/core/operations/auth-operations.ts +9 -2
- package/src/core/operations/create-model.ts +7 -2
- package/src/core/project/agent-instructions.ts +167 -0
- package/src/core/project/agent-templates/AGENTS.md +502 -0
- package/src/core/project/agent-templates/CLAUDE.md +31 -0
- package/src/core/project/agent-templates/azure-functions.instructions.md +22 -0
- package/src/core/project/agent-templates/bff-routes.instructions.md +18 -0
- package/src/core/project/agent-templates/copilot-instructions.md +27 -0
- package/src/core/project/agent-templates/shared-models.instructions.md +72 -0
- package/src/core/project/capabilities.ts +193 -0
- package/src/core/project/validation.ts +50 -0
- package/src/core/project/workflows.ts +48 -2
- package/src/core/scaffold/auth-generator.ts +7 -2
- package/src/core/verify/index.ts +76 -0
- package/src/machine/index.ts +133 -45
- package/src/mcp/index.ts +28 -10
package/src/cli/commands/init.ts
CHANGED
|
@@ -18,6 +18,7 @@ import {
|
|
|
18
18
|
} from "../../utils/package-manager";
|
|
19
19
|
import { syncProjectManifest } from "../../core/project/manifest";
|
|
20
20
|
import { writeWorkflowDocs, writeAgentSkills } from "../../core/project/workflows";
|
|
21
|
+
import { writeAgentInstructionFiles } from "../../core/project/agent-instructions";
|
|
21
22
|
import {
|
|
22
23
|
buildCSharpCodegenToolManifestSource,
|
|
23
24
|
buildPythonCodegenRequirementsSource,
|
|
@@ -789,7 +790,7 @@ function runSimple(command: string, args: string[], cwd: string): Promise<void>
|
|
|
789
790
|
export function injectSwallowKitNextConfig(nextConfigContent: string, projectName: string): string {
|
|
790
791
|
return nextConfigContent.replace(
|
|
791
792
|
/(const\s+nextConfig[:\s]*(?::\s*NextConfig\s*)?=\s*\{)(\s*\/\*[^*]*\*\/)?/,
|
|
792
|
-
`$1\n output: 'standalone',\n transpilePackages: ['@${projectName}/shared'],\n serverExternalPackages: ['applicationinsights', 'diagnostic-channel-publishers'],$2`
|
|
793
|
+
`$1\n output: 'standalone',\n agentRules: false, // SwallowKit owns the canonical root AGENTS.md contract\n transpilePackages: ['@${projectName}/shared'],\n serverExternalPackages: ['applicationinsights', 'diagnostic-channel-publishers'],$2`
|
|
793
794
|
);
|
|
794
795
|
}
|
|
795
796
|
|
|
@@ -2105,532 +2106,34 @@ This project was generated by SwallowKit. If you encounter any issues or have su
|
|
|
2105
2106
|
console.log('✅ README.md created\n');
|
|
2106
2107
|
}
|
|
2107
2108
|
|
|
2108
|
-
function createAiAgentFiles(
|
|
2109
|
+
function createAiAgentFiles(
|
|
2110
|
+
projectDir: string,
|
|
2111
|
+
projectName: string,
|
|
2112
|
+
backendLanguage: BackendLanguage,
|
|
2113
|
+
pm: PackageManager
|
|
2114
|
+
) {
|
|
2109
2115
|
console.log('🤖 Creating AI agent instruction files...\n');
|
|
2110
|
-
const backendLanguageLabel = getBackendLanguageLabel(backendLanguage);
|
|
2111
2116
|
const runCmd = pm === 'pnpm' ? 'pnpm' : 'npx';
|
|
2112
|
-
const projectMcpConfigSource = buildSwallowKitMcpProjectConfigSource(pm);
|
|
2113
|
-
const functionsStructureLine = backendLanguage === 'typescript'
|
|
2114
|
-
? `│ └── src/ # HTTP trigger handlers with Cosmos DB bindings`
|
|
2115
|
-
: backendLanguage === 'csharp'
|
|
2116
|
-
? `│ ├── Crud/ # C# HTTP trigger handlers\n│ └── generated/ # Native-generated C# schema assets`
|
|
2117
|
-
: `│ ├── blueprints/ # Python HTTP trigger handlers\n│ └── generated/ # Native-generated Python schema assets`;
|
|
2118
|
-
const backendSchemaNote = backendLanguage === 'typescript'
|
|
2119
|
-
? `- The shared package (\`@${projectName}/shared\`) is consumed by both Next.js and Azure Functions as a workspace dependency.`
|
|
2120
|
-
: `- The frontend/BFF source of truth stays in \`shared/models/\` as Zod schemas.\n- \`swallowkit scaffold\` exports OpenAPI into \`functions/openapi/\` and generates ${backendLanguageLabel} schema assets into \`functions/generated/\` with native ${backendLanguageLabel} tooling.`;
|
|
2121
|
-
const backendRulesNote = backendLanguage === 'typescript'
|
|
2122
|
-
? `- All CRUD operations and business logic live in \`functions/src/\`.\n- Use Azure Functions Cosmos DB **input/output bindings** (\`extraInputs\`/\`extraOutputs\`) for reads and writes.\n- Use the Cosmos DB SDK client directly **only** for delete operations (bindings do not support delete).\n- Validate all data against Zod schemas before writing to Cosmos DB.\n- The backend auto-generates \`id\` (UUID), \`createdAt\`, and \`updatedAt\` — never trust client-sent values for these fields.`
|
|
2123
|
-
: `- All business logic lives in \`functions/\` and the generated handlers perform real Cosmos DB CRUD.\n- Keep Zod schemas in \`shared/models/\` as the source of truth.\n- Regenerate backend contracts with \`swallowkit scaffold shared/models/<name>.ts\` whenever a schema changes.\n- Use the native-generated schema assets in \`functions/generated/\` to keep backend contracts aligned.\n- The backend should still own \`id\`, \`createdAt\`, and \`updatedAt\`.`;
|
|
2124
|
-
|
|
2125
|
-
// ── 1. AGENTS.md (Codex / generic agents) ──────────────────────────
|
|
2126
|
-
|
|
2127
|
-
const agentsMd = `# AGENTS.md
|
|
2128
|
-
|
|
2129
|
-
This project was generated by **SwallowKit**.
|
|
2130
|
-
All coding agents **must** follow the architecture and conventions described below.
|
|
2131
|
-
|
|
2132
|
-
## Architecture Overview
|
|
2133
|
-
|
|
2134
|
-
This is a full-stack application deployed on Azure with a TypeScript frontend/BFF and an Azure Functions backend in ${backendLanguageLabel}.
|
|
2135
|
-
|
|
2136
|
-
\`\`\`
|
|
2137
|
-
Frontend (React / Next.js App Router)
|
|
2138
|
-
↓ fetch('/api/{model}', ...)
|
|
2139
|
-
BFF Layer (Next.js API Routes)
|
|
2140
|
-
↓ HTTP → Azure Functions
|
|
2141
|
-
Backend (Azure Functions)
|
|
2142
|
-
↓
|
|
2143
|
-
Azure Cosmos DB (Document Database)
|
|
2144
|
-
\`\`\`
|
|
2145
|
-
|
|
2146
|
-
### Project Structure
|
|
2147
|
-
|
|
2148
|
-
\`\`\`
|
|
2149
|
-
${projectName}/
|
|
2150
|
-
├── app/ # Next.js App Router
|
|
2151
|
-
│ ├── api/ # BFF API routes (proxy to Azure Functions)
|
|
2152
|
-
│ └── {model}/ # UI pages per model (list, detail, create, edit)
|
|
2153
|
-
├── functions/ # Azure Functions (backend)
|
|
2154
|
-
${functionsStructureLine}
|
|
2155
|
-
├── shared/ # Shared workspace package
|
|
2156
|
-
│ ├── models/ # Zod schema definitions (single source of truth)
|
|
2157
|
-
│ └── index.ts # Re-exports all models
|
|
2158
|
-
├── lib/
|
|
2159
|
-
│ └── api/ # API client utilities (backend.ts, call-function.ts)
|
|
2160
|
-
├── components/ # Shared React components
|
|
2161
|
-
├── infra/ # Bicep infrastructure-as-code files
|
|
2162
|
-
│ ├── main.bicep
|
|
2163
|
-
│ └── modules/
|
|
2164
|
-
├── .mcp.json # Project-scoped MCP bootstrap resolving SwallowKit on each launch
|
|
2165
|
-
└── .github/workflows/ # CI/CD workflows (if configured)
|
|
2166
|
-
\`\`\`
|
|
2167
|
-
|
|
2168
|
-
## Setup & Everyday Commands
|
|
2169
|
-
|
|
2170
|
-
\`\`\`bash
|
|
2171
|
-
${pm} install # install dependencies
|
|
2172
|
-
${runCmd} swallowkit dev # Next.js (3000) + Azure Functions (7071)
|
|
2173
|
-
${pm} run build # production build
|
|
2174
|
-
${pm} run lint # ESLint (generated code must stay error-free)
|
|
2175
|
-
${runCmd} swallowkit verify # structure / drift / typecheck (exit 1 on failure)
|
|
2176
|
-
\`\`\`
|
|
2177
|
-
|
|
2178
|
-
Run \`${runCmd} swallowkit verify\` (or \`machine verify project\`) before finishing any task.
|
|
2179
|
-
|
|
2180
|
-
## SwallowKit MCP / Machine Workflow
|
|
2181
|
-
|
|
2182
|
-
- This repository includes a project-scoped \`.mcp.json\` file that resolves and starts the latest SwallowKit MCP server on each launch. Set \`SWALLOWKIT_MCP_VERSION\` in that file to pin a specific version.
|
|
2183
|
-
- Prefer the \`swallowkit_*\` MCP tools for framework-owned inspection, validation, and generation when they are available.
|
|
2184
|
-
- If MCP is unavailable in your runtime, fall back to the machine CLI:
|
|
2185
|
-
- \`${runCmd} swallowkit machine inspect project\`
|
|
2186
|
-
- \`${runCmd} swallowkit machine inspect boundaries\` — responsibility boundary contract (which files you may edit freely)
|
|
2187
|
-
- \`${runCmd} swallowkit machine validate project\`
|
|
2188
|
-
- \`${runCmd} swallowkit machine plan scaffold <name>\` → \`apply scaffold --plan <planId>\` — safe two-phase generation
|
|
2189
|
-
- \`${runCmd} swallowkit machine verify project\` → \`explain failure\` — verification loop
|
|
2190
|
-
- Do not hand-edit framework-owned artifacts when the MCP or machine interface can generate or validate them for you.
|
|
2191
|
-
- The MCP bootstrap uses ${pm} and requires network access when the selected version is not cached.
|
|
2192
|
-
- **Always invoke SwallowKit via \`${runCmd}\`.** Do not mix package manager commands.
|
|
2193
|
-
|
|
2194
|
-
## Autonomous Loop (Plan / Apply / Verify)
|
|
2195
|
-
|
|
2196
|
-
Machine commands return a \`status\` terminal state (\`complete\` / \`in-progress\` / \`blocked\` / \`requires-human\` / \`failed\`) and \`nextActions\`. Standard loop:
|
|
2197
|
-
|
|
2198
|
-
1. \`plan scaffold <model>\` — compute changes without writing (get \`planId\`)
|
|
2199
|
-
2. \`apply scaffold --plan <planId>\` — apply with freshness + approval checks
|
|
2200
|
-
3. \`verify project\` — structure / drift / typecheck (and project-specific checks)
|
|
2201
|
-
4. \`explain failure\` — evidence and repair actions when verification fails
|
|
2202
|
-
|
|
2203
|
-
Step-by-step runbooks live in \`.swallowkit/workflows/\` (agent-agnostic Markdown):
|
|
2204
|
-
|
|
2205
|
-
- \`.swallowkit/workflows/add-model.md\`
|
|
2206
|
-
- \`.swallowkit/workflows/modify-model.md\`
|
|
2207
|
-
- \`.swallowkit/workflows/verify-and-repair.md\`
|
|
2208
|
-
- \`.swallowkit/workflows/provision.md\`
|
|
2209
|
-
|
|
2210
|
-
The same runbooks are installed as **Agent Skills** ([agentskills.io](https://agentskills.io/) open standard) under \`.github/skills/\`:
|
|
2211
|
-
|
|
2212
|
-
| Skill | Use when |
|
|
2213
|
-
|-------|----------|
|
|
2214
|
-
| \`swallowkit-add-model\` | adding a new model / entity / CRUD feature |
|
|
2215
|
-
| \`swallowkit-modify-model\` | changing an existing schema and re-aligning artifacts |
|
|
2216
|
-
| \`swallowkit-verify-repair\` | converging to a verified state after any change |
|
|
2217
|
-
| \`swallowkit-provision\` | provisioning Azure infrastructure (human approval required) |
|
|
2218
|
-
|
|
2219
|
-
Skills-aware agents (GitHub Copilot in VS Code / CLI / cloud agent, and other agents supporting the standard) discover these automatically from their \`name\`/\`description\` and load the body on demand. If your agent does not support skills, read the equivalent runbook in \`.swallowkit/workflows/\` before performing these tasks.
|
|
2220
|
-
|
|
2221
|
-
## Responsibility Boundary (AI × Deterministic Generation)
|
|
2222
|
-
|
|
2223
|
-
- **ai-authored (write freely)**: \`shared/models/\`, business logic, custom pages/components, tests.
|
|
2224
|
-
- **deterministic (never hand-edit)**: artifacts recorded in \`.swallowkit/artifacts.json\` with \`managed\` ownership, and \`.swallowkit/\` metadata. Change the model/config and regenerate via plan/apply instead.
|
|
2225
|
-
- **shared (edit outside markers)**: \`infra/main.bicep\`, \`functions/function_app.py\`, \`shared/index.ts\`.
|
|
2226
|
-
- Full machine-readable contract: \`${runCmd} swallowkit machine inspect boundaries\`
|
|
2227
|
-
|
|
2228
|
-
## Critical Design Principles
|
|
2229
|
-
|
|
2230
|
-
### 1. Next.js API Routes Are Strictly a BFF (Backend for Frontend)
|
|
2231
|
-
|
|
2232
|
-
- \`app/api/\` routes exist **only** to proxy requests to Azure Functions.
|
|
2233
|
-
- **Never** place business logic, database access, or direct Cosmos DB calls in Next.js API routes.
|
|
2234
|
-
- The BFF layer may validate input/output with Zod schemas before forwarding to Functions.
|
|
2235
|
-
- Use the \`callFunction\` helper (\`lib/api/call-function.ts\`) or the \`api\` client (\`lib/api/backend.ts\`) to call Azure Functions.
|
|
2236
|
-
|
|
2237
|
-
Example BFF route pattern:
|
|
2238
|
-
|
|
2239
|
-
\`\`\`typescript
|
|
2240
|
-
// app/api/{model}/route.ts
|
|
2241
|
-
import { callFunction } from '@/lib/api/call-function';
|
|
2242
|
-
import { ModelSchema } from '@${projectName}/shared';
|
|
2243
|
-
import { z } from 'zod/v4';
|
|
2244
|
-
|
|
2245
|
-
export async function GET() {
|
|
2246
|
-
return callFunction({
|
|
2247
|
-
method: 'GET',
|
|
2248
|
-
path: '/api/{model}',
|
|
2249
|
-
responseSchema: z.array(ModelSchema),
|
|
2250
|
-
});
|
|
2251
|
-
}
|
|
2252
|
-
|
|
2253
|
-
export async function POST(request: NextRequest) {
|
|
2254
|
-
const body = await request.json();
|
|
2255
|
-
return callFunction({
|
|
2256
|
-
method: 'POST',
|
|
2257
|
-
path: '/api/{model}',
|
|
2258
|
-
body,
|
|
2259
|
-
inputSchema: ModelSchema.omit({ id: true, createdAt: true, updatedAt: true }),
|
|
2260
|
-
responseSchema: ModelSchema,
|
|
2261
|
-
successStatus: 201,
|
|
2262
|
-
});
|
|
2263
|
-
}
|
|
2264
|
-
\`\`\`
|
|
2265
|
-
|
|
2266
|
-
### 2. Zod Schemas Are the Single Source of Truth
|
|
2267
|
-
|
|
2268
|
-
- All data models are defined **once** as Zod schemas in \`shared/models/\`.
|
|
2269
|
-
- TypeScript types are derived with \`z.infer<typeof Schema>\` — never define types separately.
|
|
2270
|
-
- ${backendSchemaNote}
|
|
2271
|
-
|
|
2272
|
-
Model definition pattern:
|
|
2273
|
-
|
|
2274
|
-
\`\`\`typescript
|
|
2275
|
-
// shared/models/{model}.ts
|
|
2276
|
-
import { z } from 'zod/v4';
|
|
2277
|
-
|
|
2278
|
-
export const Todo = z.object({
|
|
2279
|
-
id: z.string(),
|
|
2280
|
-
name: z.string().min(1),
|
|
2281
|
-
// ... your fields
|
|
2282
|
-
createdAt: z.string().optional(),
|
|
2283
|
-
updatedAt: z.string().optional(),
|
|
2284
|
-
});
|
|
2285
|
-
|
|
2286
|
-
export type Todo = z.infer<typeof Todo>;
|
|
2287
|
-
export const displayName = 'Todo';
|
|
2288
|
-
\`\`\`
|
|
2289
|
-
|
|
2290
|
-
Key rules:
|
|
2291
|
-
- Use the **Zod official pattern**: the schema constant and the TypeScript type share the same name.
|
|
2292
|
-
- \`id\`, \`createdAt\`, and \`updatedAt\` are auto-managed by the backend. Mark them as \`optional()\` in the schema.
|
|
2293
|
-
- Always re-export models from \`shared/index.ts\`.
|
|
2294
|
-
|
|
2295
|
-
### 3. Azure Functions Own All Business Logic and Data Access
|
|
2296
|
-
|
|
2297
|
-
- ${backendRulesNote}
|
|
2298
|
-
|
|
2299
|
-
${backendLanguage === 'typescript' ? 'Azure Functions handler pattern:' : `Generated ${backendLanguageLabel} handlers live under \`functions/\`. Re-run \`swallowkit scaffold shared/models/<name>.ts\` after schema changes to keep generated CRUD handlers and the native schema assets under \`functions/generated/\` in sync.`}
|
|
2300
|
-
|
|
2301
|
-
${backendLanguage === 'typescript' ? `\`\`\`typescript
|
|
2302
|
-
// functions/src/{model}.ts
|
|
2303
|
-
import { app } from '@azure/functions';
|
|
2304
|
-
import { ModelSchema } from '@${projectName}/shared';
|
|
2305
|
-
|
|
2306
|
-
const containerName = 'Models'; // PascalCase + 's'
|
|
2307
|
-
|
|
2308
|
-
app.http('{model}-get-all', {
|
|
2309
|
-
methods: ['GET'],
|
|
2310
|
-
route: '{model}',
|
|
2311
|
-
authLevel: 'function',
|
|
2312
|
-
extraInputs: [{ type: 'cosmosDB', name: 'cosmosInput', containerName, ... }],
|
|
2313
|
-
handler: async (request, context) => {
|
|
2314
|
-
const documents = context.extraInputs.get('cosmosInput');
|
|
2315
|
-
const validated = z.array(ModelSchema).parse(documents);
|
|
2316
|
-
return { status: 200, jsonBody: validated };
|
|
2317
|
-
},
|
|
2318
|
-
});
|
|
2319
|
-
\`\`\`` : ''}
|
|
2320
|
-
|
|
2321
|
-
## Naming Conventions
|
|
2322
|
-
|
|
2323
|
-
| Item | Convention | Example |
|
|
2324
|
-
|------|-----------|---------|
|
|
2325
|
-
| Model schema file | \`shared/models/{kebab-case}.ts\` | \`shared/models/todo.ts\` |
|
|
2326
|
-
| Schema/type name | PascalCase (same name for both) | \`export const Todo = z.object({...}); export type Todo = z.infer<typeof Todo>;\` |
|
|
2327
|
-
| Functions handler file | backend-language specific under \`functions/\` | \`${backendLanguage === 'typescript' ? 'functions/src/todo.ts' : backendLanguage === 'csharp' ? 'functions/Crud/TodoCrudFunctions.cs' : 'functions/blueprints/todo.py'}\` |
|
|
2328
|
-
| Functions handler name | \`{camelCase}-{operation}\` | \`todo-get-all\`, \`todo-create\` |
|
|
2329
|
-
| API route path | \`/api/{camelCase}\` | \`/api/todo\`, \`/api/todo/{id}\` |
|
|
2330
|
-
| BFF route file | \`app/api/{kebab-case}/route.ts\` | \`app/api/todo/route.ts\` |
|
|
2331
|
-
| BFF detail route | \`app/api/{kebab-case}/[id]/route.ts\` | \`app/api/todo/[id]/route.ts\` |
|
|
2332
|
-
| UI page directory | \`app/{kebab-case}/\` | \`app/todo/page.tsx\` |
|
|
2333
|
-
| React component | PascalCase | \`TodoForm.tsx\` |
|
|
2334
|
-
| Cosmos DB container | PascalCase + 's' | \`Todos\` |
|
|
2335
|
-
| Cosmos DB partition key | \`/id\` (default) | Custom: \`export const partitionKey = '/field'\` |
|
|
2336
|
-
| Bicep container file | \`infra/containers/{kebab-case}-container.bicep\` | \`infra/containers/todo-container.bicep\` |
|
|
2337
|
-
|
|
2338
|
-
## Adding New Models (SwallowKit CLI)
|
|
2339
|
-
|
|
2340
|
-
Use the SwallowKit CLI — do **not** manually create model files or CRUD boilerplate.
|
|
2341
|
-
For autonomous agents, prefer the plan/apply loop above (or the \`swallowkit-add-model\` skill); the commands below are the human-friendly equivalents.
|
|
2342
|
-
|
|
2343
|
-
### Create a new data model
|
|
2344
|
-
|
|
2345
|
-
\`\`\`bash
|
|
2346
|
-
${runCmd} swallowkit create-model <name>
|
|
2347
|
-
# Multiple models at once:
|
|
2348
|
-
${runCmd} swallowkit create-model user post comment
|
|
2349
|
-
\`\`\`
|
|
2350
|
-
|
|
2351
|
-
Creates \`shared/models/<name>.ts\` with a Zod schema template including \`id\`, \`createdAt\`, \`updatedAt\`.
|
|
2352
|
-
Edit the generated file to add your domain-specific fields, then run scaffold.
|
|
2353
|
-
|
|
2354
|
-
### Generate full CRUD from a model
|
|
2355
|
-
|
|
2356
|
-
\`\`\`bash
|
|
2357
|
-
${runCmd} swallowkit scaffold shared/models/<name>.ts
|
|
2358
|
-
\`\`\`
|
|
2359
|
-
|
|
2360
|
-
Generates:
|
|
2361
|
-
- Azure Functions handlers (${backendLanguage === 'typescript' ? '`functions/src/<name>.ts`' : '`functions/` language-specific CRUD files + `functions/generated/` schema assets'})
|
|
2362
|
-
- BFF API routes (\`app/api/<name>/route.ts\`, \`app/api/<name>/[id]/route.ts\`)
|
|
2363
|
-
- UI pages (\`app/<name>/page.tsx\`, detail, create, edit pages)
|
|
2364
|
-
- Cosmos DB Bicep container config (\`infra/containers/<name>-container.bicep\`)
|
|
2365
|
-
|
|
2366
|
-
### Start development servers
|
|
2367
|
-
|
|
2368
|
-
\`\`\`bash
|
|
2369
|
-
${runCmd} swallowkit dev
|
|
2370
|
-
\`\`\`
|
|
2371
2117
|
|
|
2372
|
-
|
|
2373
|
-
|
|
2374
|
-
|
|
2375
|
-
|
|
2376
|
-
|
|
2377
|
-
\`\`\`bash
|
|
2378
|
-
${runCmd} swallowkit provision --resource-group <name> --location <region>
|
|
2379
|
-
\`\`\`
|
|
2380
|
-
|
|
2381
|
-
Deploys Bicep infrastructure: Static Web Apps, Functions, Cosmos DB, Storage, Managed Identity.
|
|
2382
|
-
|
|
2383
|
-
### Typical workflow for "add a new feature/model"
|
|
2384
|
-
|
|
2385
|
-
1. \`${runCmd} swallowkit create-model <name>\`
|
|
2386
|
-
2. Edit \`shared/models/<name>.ts\` — add fields
|
|
2387
|
-
3. \`${runCmd} swallowkit scaffold shared/models/<name>.ts\`
|
|
2388
|
-
4. \`${runCmd} swallowkit dev\` — verify at http://localhost:3000/<name>
|
|
2389
|
-
5. If \`dev-seeds/\` already exists, update the seed JSON files to include realistic data for the new model and adjust existing seeds if relationships changed.
|
|
2390
|
-
|
|
2391
|
-
## Do NOT
|
|
2392
|
-
|
|
2393
|
-
- **Do not** put business logic or database calls in \`app/api/\` routes. They are BFF only.
|
|
2394
|
-
- **Do not** define TypeScript interfaces/types separately from Zod schemas. Always derive types with \`z.infer<>\`.
|
|
2395
|
-
- **Do not** manually duplicate model definitions across layers. Use the shared package.
|
|
2396
|
-
- **Do not** manually create CRUD boilerplate. Use \`swallowkit scaffold\`.
|
|
2397
|
-
- **Do not** hardcode Cosmos DB connection strings. Use Managed Identity (\`CosmosDBConnection__accountEndpoint\`) in production and emulator settings locally.
|
|
2398
|
-
- By default, all containers use \`/id\` as the partition key. To use a custom partition key, add \`export const partitionKey = '/yourField'\` to the model file. The scaffold command will apply it across all layers.
|
|
2399
|
-
|
|
2400
|
-
## Technology Stack
|
|
2401
|
-
|
|
2402
|
-
- **Frontend**: Next.js (App Router), React, TypeScript, Tailwind CSS
|
|
2403
|
-
- **BFF**: Next.js API Routes (proxy only)
|
|
2404
|
-
- **Backend**: Azure Functions (${backendLanguageLabel})
|
|
2405
|
-
- **Database**: Azure Cosmos DB (NoSQL)
|
|
2406
|
-
- **Schema**: Zod (shared across all layers via workspace package)
|
|
2407
|
-
- **Infrastructure**: Bicep (IaC)
|
|
2408
|
-
- **Hosting**: Azure Static Web Apps (frontend) + Azure Functions Flex Consumption (backend)
|
|
2409
|
-
- **Auth**: Azure Managed Identity (no connection strings in production)
|
|
2410
|
-
- **Monitoring**: Application Insights
|
|
2411
|
-
`;
|
|
2412
|
-
|
|
2413
|
-
fs.writeFileSync(path.join(projectDir, 'AGENTS.md'), agentsMd);
|
|
2414
|
-
console.log(' ✅ AGENTS.md (Codex / generic agents)');
|
|
2415
|
-
|
|
2416
|
-
// ── 2. CLAUDE.md (Claude Code) ─────────────────────────────────────
|
|
2417
|
-
|
|
2418
|
-
const claudeMd = `# CLAUDE.md
|
|
2419
|
-
|
|
2420
|
-
This file is for Claude Code. Read AGENTS.md in the project root for the full architecture, conventions, and rules.
|
|
2421
|
-
|
|
2422
|
-
## Quick Reference
|
|
2423
|
-
|
|
2424
|
-
- **Architecture**: Next.js (frontend) → BFF (API routes, proxy only) → Azure Functions (backend) → Cosmos DB
|
|
2425
|
-
- **Schema**: Zod schemas in \`shared/models/\` are the single source of truth. Never define types separately.
|
|
2426
|
-
- **BFF rule**: \`app/api/\` routes must ONLY proxy to Azure Functions via \`callFunction()\`. No business logic.
|
|
2427
|
-
- **Backend language**: ${backendLanguageLabel}
|
|
2428
|
-
- **Backend rule**: Regenerate backend contracts with \`swallowkit scaffold\` after schema changes and keep \`functions/generated/\` in sync.
|
|
2429
|
-
|
|
2430
|
-
## SwallowKit MCP
|
|
2431
|
-
|
|
2432
|
-
- This repository includes a project-scoped \`.mcp.json\` that resolves and starts the latest SwallowKit MCP server on each launch. Set \`SWALLOWKIT_MCP_VERSION\` in that file to pin a specific version.
|
|
2433
|
-
- When the \`swallowkit_*\` tools are available, prefer them for inspect / validate / generate tasks.
|
|
2434
|
-
- If MCP is unavailable, use \`${runCmd} swallowkit machine ...\` instead.
|
|
2435
|
-
- For generation, prefer the two-phase flow: \`plan scaffold <name>\` → \`apply scaffold --plan <planId>\` → \`verify project\`. Runbooks: \`.swallowkit/workflows/\`.
|
|
2436
|
-
- Agent Skills (agentskills.io) for the same workflows live in \`.github/skills/\` (\`swallowkit-add-model\`, \`swallowkit-modify-model\`, \`swallowkit-verify-repair\`, \`swallowkit-provision\`). If your runtime does not auto-discover them, read the relevant \`SKILL.md\` before performing these tasks.
|
|
2437
|
-
- Boundary contract (what you may edit freely vs what SwallowKit regenerates): \`${runCmd} swallowkit machine inspect boundaries\`
|
|
2438
|
-
- **Always invoke SwallowKit via \`${runCmd}\`.** Do not mix package manager commands.
|
|
2439
|
-
|
|
2440
|
-
## SwallowKit CLI Commands
|
|
2441
|
-
|
|
2442
|
-
| Task | Command |
|
|
2443
|
-
|------|---------|
|
|
2444
|
-
| Create model | \`${runCmd} swallowkit create-model <name>\` |
|
|
2445
|
-
| Generate CRUD | \`${runCmd} swallowkit scaffold shared/models/<name>.ts\` |
|
|
2446
|
-
| Dev servers | \`${runCmd} swallowkit dev\` |
|
|
2447
|
-
| Provision Azure | \`${runCmd} swallowkit provision --resource-group <rg> --location <region>\` |
|
|
2448
|
-
|
|
2449
|
-
## Workflow: Add a new model
|
|
2450
|
-
|
|
2451
|
-
1. \`${runCmd} swallowkit create-model <name>\`
|
|
2452
|
-
2. Edit \`shared/models/<name>.ts\` — add your fields
|
|
2453
|
-
3. \`${runCmd} swallowkit scaffold shared/models/<name>.ts\`
|
|
2454
|
-
4. \`${runCmd} swallowkit dev\` — verify at http://localhost:3000/<name>
|
|
2455
|
-
5. If \`dev-seeds/\` exists, update the seed JSON files to include data for the new model and adjust existing seeds if relationships changed.
|
|
2456
|
-
`;
|
|
2457
|
-
|
|
2458
|
-
fs.writeFileSync(path.join(projectDir, 'CLAUDE.md'), claudeMd);
|
|
2459
|
-
console.log(' ✅ CLAUDE.md (Claude Code)');
|
|
2460
|
-
|
|
2461
|
-
fs.writeFileSync(path.join(projectDir, '.mcp.json'), projectMcpConfigSource);
|
|
2462
|
-
console.log(' ✅ .mcp.json (project-scoped MCP bootstrap)');
|
|
2463
|
-
|
|
2464
|
-
// ── 3. .github/copilot-instructions.md (GitHub Copilot) ────────────
|
|
2465
|
-
|
|
2466
|
-
const ghDir = path.join(projectDir, '.github');
|
|
2467
|
-
fs.mkdirSync(ghDir, { recursive: true });
|
|
2468
|
-
|
|
2469
|
-
const copilotInstructions = `# Copilot Instructions
|
|
2470
|
-
|
|
2471
|
-
This project was generated by **SwallowKit**. See \`AGENTS.md\` in the project root for the full specification.
|
|
2472
|
-
|
|
2473
|
-
## Architecture (3-layer)
|
|
2474
|
-
|
|
2475
|
-
\`\`\`
|
|
2476
|
-
Frontend (Next.js App Router) → BFF (Next.js API Routes) → Backend (Azure Functions) → Cosmos DB
|
|
2477
|
-
\`\`\`
|
|
2478
|
-
|
|
2479
|
-
## Key Rules
|
|
2480
|
-
|
|
2481
|
-
1. **BFF is proxy only** — \`app/api/\` routes call Azure Functions via \`callFunction()\`. No business logic, no direct DB access.
|
|
2482
|
-
2. **Zod = single source of truth** — Models live in \`shared/models/\`. Types are derived with \`z.infer<>\`. Never define types separately.
|
|
2483
|
-
3. **Backend owns data** — All CRUD and business logic stay in \`functions/\`, and generated contract assets under \`functions/generated/\` must stay aligned with \`shared/models/\`.
|
|
2484
|
-
4. **Use the CLI** — Run \`${runCmd} swallowkit create-model <name>\` then \`${runCmd} swallowkit scaffold shared/models/<name>.ts\` to add models. Do not create boilerplate manually.
|
|
2485
|
-
5. **Maintain seed data** — When adding models or changing schemas, update the JSON files under \`dev-seeds/\` to keep seed data consistent with the current schema.
|
|
2486
|
-
|
|
2487
|
-
## SwallowKit Framework Operations
|
|
2488
|
-
|
|
2489
|
-
- Prefer the SwallowKit MCP or machine interface for framework-owned inspection, validation, and generation instead of hand-editing generated files.
|
|
2490
|
-
- If your runtime loads project-scoped MCP config from \`.mcp.json\`, use the \`swallowkit_*\` tools.
|
|
2491
|
-
- Otherwise use \`${runCmd} swallowkit machine inspect project\`, \`${runCmd} swallowkit machine validate project\`, and the two-phase flow \`${runCmd} swallowkit machine plan scaffold <name>\` → \`apply scaffold --plan <planId>\` → \`verify project\`.
|
|
2492
|
-
- Agent Skills in \`.github/skills/\` (\`swallowkit-add-model\`, \`swallowkit-modify-model\`, \`swallowkit-verify-repair\`, \`swallowkit-provision\`) cover these workflows — load them when the task matches.
|
|
2493
|
-
- Boundary contract: \`${runCmd} swallowkit machine inspect boundaries\` tells you which files are free to edit and which are regenerated. Runbooks live in \`.swallowkit/workflows/\`.
|
|
2494
|
-
- **Always invoke SwallowKit via \`${runCmd}\`.** Do not mix package manager commands.
|
|
2495
|
-
|
|
2496
|
-
## Naming
|
|
2497
|
-
|
|
2498
|
-
- Schema/type: PascalCase, same name for both (\`export const Todo = z.object({...}); export type Todo = z.infer<typeof Todo>;\`)
|
|
2499
|
-
- Files: kebab-case (\`shared/models/todo.ts\`, backend handlers under \`functions/\`)
|
|
2500
|
-
- Cosmos DB containers: PascalCase + 's' (\`Todos\`), partition key default \`/id\` (customizable via \`export const partitionKey\`)
|
|
2501
|
-
|
|
2502
|
-
## Managed Fields
|
|
2503
|
-
|
|
2504
|
-
\`id\`, \`createdAt\`, \`updatedAt\` are auto-managed by the backend. Define them as \`optional()\` in schemas. Never trust client-sent values.
|
|
2505
|
-
`;
|
|
2506
|
-
|
|
2507
|
-
fs.writeFileSync(path.join(ghDir, 'copilot-instructions.md'), copilotInstructions);
|
|
2508
|
-
console.log(' ✅ .github/copilot-instructions.md (GitHub Copilot)');
|
|
2509
|
-
|
|
2510
|
-
// ── 4. .github/instructions/*.instructions.md (Copilot layer-specific) ──
|
|
2511
|
-
|
|
2512
|
-
const instructionsDir = path.join(ghDir, 'instructions');
|
|
2513
|
-
fs.mkdirSync(instructionsDir, { recursive: true });
|
|
2514
|
-
|
|
2515
|
-
// 4a. shared/models — Zod schema layer
|
|
2516
|
-
const sharedModelsInstructions = `---
|
|
2517
|
-
applyTo: "shared/models/**"
|
|
2518
|
-
---
|
|
2519
|
-
|
|
2520
|
-
# Shared Models — Zod Schema Rules
|
|
2521
|
-
|
|
2522
|
-
Files in this directory are the **single source of truth** for data models across the entire application.
|
|
2523
|
-
|
|
2524
|
-
## Rules
|
|
2525
|
-
|
|
2526
|
-
- Define Zod schemas using \`zod/v4\` (\`import { z } from 'zod/v4'\`).
|
|
2527
|
-
- Use the **Zod official pattern**: the schema constant and the TypeScript type share the same name.
|
|
2528
|
-
\`\`\`typescript
|
|
2529
|
-
export const Todo = z.object({ ... });
|
|
2530
|
-
export type Todo = z.infer<typeof Todo>;
|
|
2531
|
-
\`\`\`
|
|
2532
|
-
- Always include \`id: z.string()\`, \`createdAt: z.string().optional()\`, \`updatedAt: z.string().optional()\`. These are managed by the backend.
|
|
2533
|
-
- Export a \`displayName\` string constant for UI display.
|
|
2534
|
-
- Re-export every model from \`shared/index.ts\`.
|
|
2535
|
-
- For relationships, use **nested schemas** (import and embed the related schema), not ID references.
|
|
2536
|
-
- After editing a model, run \`${runCmd} swallowkit scaffold shared/models/<name>.ts\` to regenerate CRUD code.
|
|
2537
|
-
`;
|
|
2538
|
-
|
|
2539
|
-
fs.writeFileSync(
|
|
2540
|
-
path.join(instructionsDir, 'shared-models.instructions.md'),
|
|
2541
|
-
sharedModelsInstructions
|
|
2542
|
-
);
|
|
2543
|
-
|
|
2544
|
-
// 4b. app/api — BFF layer
|
|
2545
|
-
const bffInstructions = `---
|
|
2546
|
-
applyTo: "app/api/**"
|
|
2547
|
-
---
|
|
2548
|
-
|
|
2549
|
-
# BFF API Routes — Rules
|
|
2550
|
-
|
|
2551
|
-
Files in \`app/api/\` are the **BFF (Backend for Frontend)** layer. They exist solely to proxy requests to Azure Functions.
|
|
2552
|
-
|
|
2553
|
-
## Rules
|
|
2554
|
-
|
|
2555
|
-
- **Never** put business logic, database access, or direct Cosmos DB calls here.
|
|
2556
|
-
- Use \`callFunction()\` from \`@/lib/api/call-function\` to forward requests to Azure Functions.
|
|
2557
|
-
- You may validate input/output with Zod schemas before forwarding.
|
|
2558
|
-
- Import schemas from \`@${projectName}/shared\`.
|
|
2559
|
-
|
|
2560
|
-
## Pattern
|
|
2561
|
-
|
|
2562
|
-
\`\`\`typescript
|
|
2563
|
-
import { callFunction } from '@/lib/api/call-function';
|
|
2564
|
-
import { ModelSchema } from '@${projectName}/shared';
|
|
2565
|
-
import { z } from 'zod/v4';
|
|
2566
|
-
|
|
2567
|
-
export async function GET() {
|
|
2568
|
-
return callFunction({
|
|
2569
|
-
method: 'GET',
|
|
2570
|
-
path: '/api/{model}',
|
|
2571
|
-
responseSchema: z.array(ModelSchema),
|
|
2118
|
+
writeAgentInstructionFiles(projectDir, {
|
|
2119
|
+
projectName,
|
|
2120
|
+
backendLanguage,
|
|
2121
|
+
packageManager: pm,
|
|
2572
2122
|
});
|
|
2573
|
-
|
|
2574
|
-
|
|
2575
|
-
|
|
2576
|
-
|
|
2577
|
-
fs.writeFileSync(
|
|
2578
|
-
path.join(instructionsDir, 'bff-routes.instructions.md'),
|
|
2579
|
-
bffInstructions
|
|
2580
|
-
);
|
|
2581
|
-
|
|
2582
|
-
// 4c. functions — Azure Functions backend layer
|
|
2583
|
-
const functionsInstructions = `---
|
|
2584
|
-
applyTo: "functions/**"
|
|
2585
|
-
---
|
|
2586
|
-
|
|
2587
|
-
# Azure Functions — Backend Rules
|
|
2588
|
-
|
|
2589
|
-
Files in \`functions/\` contain all business logic and data access for this application.
|
|
2590
|
-
|
|
2591
|
-
## Rules
|
|
2592
|
-
|
|
2593
|
-
- Keep backend contracts aligned with \`shared/models/\` by rerunning \`swallowkit scaffold\` after schema changes.
|
|
2594
|
-
- For TypeScript backends, use Cosmos DB **input/output bindings** (\`extraInputs\`/\`extraOutputs\`) for reads and writes.
|
|
2595
|
-
- For C#/Python backends, consume the native-generated assets in \`functions/generated/\`.
|
|
2596
|
-
- Auto-generate \`id\` (UUID), \`createdAt\`, and \`updatedAt\` on the backend. Never trust client-sent values.
|
|
2597
|
-
- Container names are PascalCase + 's' (e.g., \`Todos\`). Partition key defaults to \`/id\` but can be customized per model.
|
|
2598
|
-
|
|
2599
|
-
## Handler Pattern
|
|
2600
|
-
|
|
2601
|
-
\`\`\`typescript
|
|
2602
|
-
import { app } from '@azure/functions';
|
|
2603
|
-
import { ModelSchema } from '@${projectName}/shared';
|
|
2604
|
-
|
|
2605
|
-
app.http('{model}-get-all', {
|
|
2606
|
-
methods: ['GET'],
|
|
2607
|
-
route: '{model}',
|
|
2608
|
-
authLevel: 'function',
|
|
2609
|
-
extraInputs: [cosmosInput],
|
|
2610
|
-
handler: async (request, context) => {
|
|
2611
|
-
const documents = context.extraInputs.get(cosmosInput);
|
|
2612
|
-
const validated = z.array(ModelSchema).parse(documents);
|
|
2613
|
-
return { status: 200, jsonBody: validated };
|
|
2614
|
-
},
|
|
2615
|
-
});
|
|
2616
|
-
\`\`\`
|
|
2617
|
-
`;
|
|
2123
|
+
console.log(' ✅ AGENTS.md (canonical project contract)');
|
|
2124
|
+
console.log(' ✅ CLAUDE.md (Claude Code adapter)');
|
|
2125
|
+
console.log(' ✅ .github/copilot-instructions.md (GitHub Copilot adapter)');
|
|
2126
|
+
console.log(' ✅ .github/instructions/ (path-specific instructions)');
|
|
2618
2127
|
|
|
2619
2128
|
fs.writeFileSync(
|
|
2620
|
-
path.join(
|
|
2621
|
-
|
|
2129
|
+
path.join(projectDir, '.mcp.json'),
|
|
2130
|
+
buildSwallowKitMcpProjectConfigSource(pm)
|
|
2622
2131
|
);
|
|
2132
|
+
console.log(' ✅ .mcp.json (project-scoped MCP bootstrap)');
|
|
2623
2133
|
|
|
2624
|
-
console.log(' ✅ .github/instructions/ (Copilot layer-specific instructions)');
|
|
2625
|
-
console.log(' - shared-models.instructions.md');
|
|
2626
|
-
console.log(' - bff-routes.instructions.md');
|
|
2627
|
-
console.log(' - azure-functions.instructions.md');
|
|
2628
|
-
|
|
2629
|
-
// ── 5. .swallowkit/workflows/*.md (agent-agnostic runbooks) ────────
|
|
2630
2134
|
writeWorkflowDocs(projectDir, runCmd);
|
|
2631
2135
|
console.log(' ✅ .swallowkit/workflows/ (agent-agnostic autonomous-loop runbooks)');
|
|
2632
2136
|
|
|
2633
|
-
// ── 6. .github/skills/<name>/SKILL.md (Agent Skills, agentskills.io) ─
|
|
2634
2137
|
const skillPaths = writeAgentSkills(projectDir, runCmd);
|
|
2635
2138
|
console.log(' ✅ .github/skills/ (Agent Skills — agentskills.io open standard)');
|
|
2636
2139
|
for (const skillPath of skillPaths) {
|
|
@@ -2638,16 +2141,7 @@ app.http('{model}-get-all', {
|
|
|
2638
2141
|
}
|
|
2639
2142
|
|
|
2640
2143
|
console.log('\n✅ AI agent files created\n');
|
|
2641
|
-
console.log(' Supported agents:');
|
|
2642
|
-
console.log(' - OpenAI Codex → AGENTS.md');
|
|
2643
|
-
console.log(' - Claude Code → CLAUDE.md (+ AGENTS.md)');
|
|
2644
|
-
console.log(' - Project MCP runtimes → .mcp.json');
|
|
2645
|
-
console.log(' - GitHub Copilot → .github/copilot-instructions.md');
|
|
2646
|
-
console.log(' - GitHub Copilot (edit) → .github/instructions/*.instructions.md');
|
|
2647
|
-
console.log(' - Skills-aware agents → .github/skills/*/SKILL.md');
|
|
2648
|
-
console.log('');
|
|
2649
2144
|
}
|
|
2650
|
-
|
|
2651
2145
|
export function buildFunctionsHostKeyBicepExpression(): string {
|
|
2652
2146
|
return "listKeys('${resourceId('Microsoft.Web/sites', functionsAppName)}/host/default', '2023-12-01').functionKeys.default";
|
|
2653
2147
|
}
|
package/src/cli/index.ts
CHANGED
|
@@ -189,10 +189,12 @@ export function createProgram(devCommandOverride: Command = devCommand): Command
|
|
|
189
189
|
.description("Add authentication and authorization to the project")
|
|
190
190
|
.option("--provider <provider>", "Auth provider: custom-jwt | swa | external-token | swa-custom | none", "custom-jwt")
|
|
191
191
|
.option("--scheme <name>", "Add a named authentication scheme")
|
|
192
|
+
.option("--allowed-providers <list>", "Comma-separated SWA identity providers to allow (e.g. github,aad); defaults to aad")
|
|
192
193
|
.action((options) => {
|
|
193
194
|
addAuthCommand({
|
|
194
195
|
provider: options.provider,
|
|
195
196
|
scheme: options.scheme,
|
|
197
|
+
allowedProviders: options.allowedProviders ? String(options.allowedProviders).split(",") : undefined,
|
|
196
198
|
});
|
|
197
199
|
});
|
|
198
200
|
|
|
@@ -27,6 +27,8 @@ import {
|
|
|
27
27
|
export interface PlanAuthOptions {
|
|
28
28
|
provider: string;
|
|
29
29
|
scheme?: string;
|
|
30
|
+
/** SWA の許可 identity provider。未指定時は add-auth 側の既定 (['aad'])。 */
|
|
31
|
+
allowedProviders?: string[];
|
|
30
32
|
}
|
|
31
33
|
|
|
32
34
|
export type AuthPlanAction = "create" | "update" | "overwrite" | "append" | "delete" | "skip";
|
|
@@ -44,6 +46,7 @@ export interface AuthPlanData {
|
|
|
44
46
|
planType: "auth";
|
|
45
47
|
provider: string;
|
|
46
48
|
scheme?: string;
|
|
49
|
+
allowedProviders?: string[];
|
|
47
50
|
createdAt: string;
|
|
48
51
|
swallowkitVersion: string;
|
|
49
52
|
operations: AuthPlanOperation[];
|
|
@@ -70,7 +73,7 @@ async function collectAuthOperations(options: PlanAuthOptions): Promise<FileOper
|
|
|
70
73
|
const captured = await captureConsoleMessagesWithError(async () => {
|
|
71
74
|
await interceptProcessExit(async () => {
|
|
72
75
|
await runWithFileSession(session, async () => {
|
|
73
|
-
await addAuthCommand({ provider: options.provider, scheme: options.scheme });
|
|
76
|
+
await addAuthCommand({ provider: options.provider, scheme: options.scheme, allowedProviders: options.allowedProviders });
|
|
74
77
|
});
|
|
75
78
|
});
|
|
76
79
|
});
|
|
@@ -166,6 +169,7 @@ export async function planAuthOperation(options: PlanAuthOptions): Promise<AuthP
|
|
|
166
169
|
JSON.stringify({
|
|
167
170
|
provider: options.provider,
|
|
168
171
|
scheme: options.scheme,
|
|
172
|
+
allowedProviders: options.allowedProviders,
|
|
169
173
|
operations: operations.map((op) => ({ path: op.path, action: op.action })),
|
|
170
174
|
fingerprints,
|
|
171
175
|
})
|
|
@@ -178,6 +182,7 @@ export async function planAuthOperation(options: PlanAuthOptions): Promise<AuthP
|
|
|
178
182
|
planType: "auth",
|
|
179
183
|
provider: options.provider,
|
|
180
184
|
...(options.scheme ? { scheme: options.scheme } : {}),
|
|
185
|
+
...(options.allowedProviders && options.allowedProviders.length > 0 ? { allowedProviders: options.allowedProviders } : {}),
|
|
181
186
|
createdAt: new Date().toISOString(),
|
|
182
187
|
swallowkitVersion: getSwallowKitVersion(),
|
|
183
188
|
operations,
|
|
@@ -208,6 +213,7 @@ export function verifyAuthPlanFingerprints(
|
|
|
208
213
|
export interface ApplyAuthOptions {
|
|
209
214
|
provider?: string;
|
|
210
215
|
scheme?: string;
|
|
216
|
+
allowedProviders?: string[];
|
|
211
217
|
planId?: string;
|
|
212
218
|
approve?: boolean;
|
|
213
219
|
}
|
|
@@ -241,7 +247,7 @@ async function runCommitAuthOperation(options: PlanAuthOptions): Promise<{
|
|
|
241
247
|
const tracked = await trackFileMutations(async () => {
|
|
242
248
|
const captured = await captureConsoleMessagesWithError(async () => {
|
|
243
249
|
await interceptProcessExit(async () => {
|
|
244
|
-
await addAuthCommand({ provider: options.provider, scheme: options.scheme });
|
|
250
|
+
await addAuthCommand({ provider: options.provider, scheme: options.scheme, allowedProviders: options.allowedProviders });
|
|
245
251
|
});
|
|
246
252
|
});
|
|
247
253
|
|
|
@@ -318,6 +324,7 @@ export async function applyAuthOperation(options: ApplyAuthOptions): Promise<App
|
|
|
318
324
|
const effectiveOptions: PlanAuthOptions = {
|
|
319
325
|
provider,
|
|
320
326
|
scheme: options.scheme ?? basePlan?.scheme,
|
|
327
|
+
allowedProviders: options.allowedProviders ?? basePlan?.allowedProviders,
|
|
321
328
|
};
|
|
322
329
|
|
|
323
330
|
// 常に最新状態で collect し、競合を再確認する
|