@svadmin/create 0.31.0 → 0.32.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -5024,16 +5024,35 @@ var require_picocolors = __commonJS(function(exports, module) {
5024
5024
 
5025
5025
  // src/index.ts
5026
5026
  var import_prompts2 = __toESM(require_prompts3(), 1);
5027
- var import_picocolors3 = __toESM(require_picocolors(), 1);
5028
- import fs4 from "node:fs";
5029
- import path4 from "node:path";
5027
+ var import_picocolors4 = __toESM(require_picocolors(), 1);
5028
+ import fs5 from "node:fs";
5029
+ import path5 from "node:path";
5030
5030
  import { fileURLToPath } from "node:url";
5031
5031
  import { createRequire as createRequire2 } from "node:module";
5032
5032
  import { spawnSync } from "node:child_process";
5033
5033
 
5034
5034
  // src/project-manifest.ts
5035
5035
  import { readFileSync } from "node:fs";
5036
- var DATA_PROVIDER_CHOICES = ["simple-rest", "supabase", "graphql", "none"];
5036
+ var DATA_PROVIDER_CHOICES = [
5037
+ "simple-rest",
5038
+ "supabase",
5039
+ "graphql",
5040
+ "rest",
5041
+ "airtable",
5042
+ "appwrite",
5043
+ "directus",
5044
+ "drizzle",
5045
+ "elysia",
5046
+ "firebase",
5047
+ "hasura",
5048
+ "medusa",
5049
+ "nestjs-query",
5050
+ "nestjsx-crud",
5051
+ "pocketbase",
5052
+ "sanity",
5053
+ "strapi",
5054
+ "none"
5055
+ ];
5037
5056
  var AUTH_PROVIDER_CHOICES = ["mock", "jwt", "supabase", "none"];
5038
5057
  function assertJsonObject(candidate, path) {
5039
5058
  if (candidate === null || typeof candidate !== "object" || Array.isArray(candidate)) {
@@ -6898,11 +6917,695 @@ Dry run only; re-run with --write to add missing Lite routes.`);
6898
6917
  Written ${result.written.length} file(s); preserved ${result.preserved.length} existing file(s).`);
6899
6918
  }
6900
6919
 
6920
+ // src/init-arguments.ts
6921
+ var PRESET_NAMES = ["supabase", "rest", "graphql"];
6922
+ var INIT_PRESETS = {
6923
+ supabase: { dataProvider: "supabase", authProvider: "supabase" },
6924
+ rest: { dataProvider: "simple-rest", authProvider: "jwt" },
6925
+ graphql: { dataProvider: "graphql", authProvider: "mock" }
6926
+ };
6927
+ function isPresetName(value) {
6928
+ return PRESET_NAMES.includes(value);
6929
+ }
6930
+ function isDataProviderChoice(value) {
6931
+ return DATA_PROVIDER_CHOICES.includes(value);
6932
+ }
6933
+ function isAuthProviderChoice(value) {
6934
+ return AUTH_PROVIDER_CHOICES.includes(value);
6935
+ }
6936
+ function takeValue(args, index, option) {
6937
+ const value = args[index + 1];
6938
+ if (value === undefined || value.startsWith("-")) {
6939
+ throw new Error(`${option} requires a value`);
6940
+ }
6941
+ return value;
6942
+ }
6943
+ function parseInitArguments(args) {
6944
+ let projectName;
6945
+ let preset;
6946
+ let dataProvider;
6947
+ let authProvider;
6948
+ let installDependencies;
6949
+ for (let index = 0;index < args.length; index++) {
6950
+ const argument = args[index];
6951
+ if (argument === undefined)
6952
+ continue;
6953
+ if (argument === "--preset") {
6954
+ const value = takeValue(args, index, "--preset");
6955
+ if (!isPresetName(value)) {
6956
+ throw new Error(`Unknown preset "${value}"; expected one of: ${PRESET_NAMES.join(", ")}`);
6957
+ }
6958
+ preset = value;
6959
+ index++;
6960
+ } else if (argument === "--data-provider") {
6961
+ const value = takeValue(args, index, "--data-provider");
6962
+ if (!isDataProviderChoice(value)) {
6963
+ throw new Error(`Unknown data provider "${value}"; expected one of: ${DATA_PROVIDER_CHOICES.join(", ")}`);
6964
+ }
6965
+ dataProvider = value;
6966
+ index++;
6967
+ } else if (argument === "--auth-provider") {
6968
+ const value = takeValue(args, index, "--auth-provider");
6969
+ if (!isAuthProviderChoice(value)) {
6970
+ throw new Error(`Unknown auth provider "${value}"; expected one of: ${AUTH_PROVIDER_CHOICES.join(", ")}`);
6971
+ }
6972
+ authProvider = value;
6973
+ index++;
6974
+ } else if (argument === "--install") {
6975
+ installDependencies = true;
6976
+ } else if (argument === "--no-install") {
6977
+ installDependencies = false;
6978
+ } else if (argument.startsWith("-")) {
6979
+ throw new Error(`Unknown option: ${argument}`);
6980
+ } else if (projectName === undefined) {
6981
+ projectName = argument;
6982
+ } else {
6983
+ throw new Error(`Unexpected argument: ${argument}`);
6984
+ }
6985
+ }
6986
+ const resolved = {};
6987
+ if (projectName !== undefined)
6988
+ resolved.projectName = projectName;
6989
+ if (preset !== undefined)
6990
+ resolved.preset = preset;
6991
+ if (dataProvider !== undefined)
6992
+ resolved.dataProvider = dataProvider;
6993
+ if (authProvider !== undefined)
6994
+ resolved.authProvider = authProvider;
6995
+ if (installDependencies !== undefined)
6996
+ resolved.installDependencies = installDependencies;
6997
+ return resolved;
6998
+ }
6999
+ function resolvePresetSelections(args) {
7000
+ const preset = args.preset === undefined ? undefined : INIT_PRESETS[args.preset];
7001
+ const dataProvider = args.dataProvider ?? preset?.dataProvider;
7002
+ const authProvider = args.authProvider ?? preset?.authProvider;
7003
+ if (dataProvider === undefined || authProvider === undefined)
7004
+ return;
7005
+ return { dataProvider, authProvider };
7006
+ }
7007
+
7008
+ // src/add-command.ts
7009
+ var import_picocolors3 = __toESM(require_picocolors(), 1);
7010
+ import fs4 from "node:fs";
7011
+ import path4 from "node:path";
7012
+
7013
+ // src/scaffold-platform.ts
7014
+ import { existsSync, readFileSync as readFileSync2 } from "node:fs";
7015
+ import { join } from "node:path";
7016
+ var SCAFFOLD_CONFIG_PATH = "src/svadmin.config.ts";
7017
+ var ADMIN_AI_MANIFEST_FILENAME = "svadmin.ai.json";
7018
+ var ADMIN_SCHEMA_FILENAME = "svadmin.schema.json";
7019
+ var SCAFFOLD_OFFICIAL_PROVIDERS = [
7020
+ { name: "simple-rest", package: "@svadmin/simple-rest", capabilities: ["data", "jwt-auth", "session"], stability: "stable" },
7021
+ { name: "supabase", package: "@svadmin/supabase", capabilities: ["data", "auth", "live", "storage", "audit"], stability: "stable" },
7022
+ { name: "graphql", package: "@svadmin/graphql", capabilities: ["data", "graphql"], stability: "stable" },
7023
+ { name: "rest", package: "@svadmin/rest", capabilities: ["data", "rest", "custom-endpoints"], stability: "experimental" },
7024
+ { name: "airtable", package: "@svadmin/airtable", capabilities: ["data"], stability: "stable" },
7025
+ { name: "appwrite", package: "@svadmin/appwrite", capabilities: ["data", "auth", "storage", "live"], stability: "stable" },
7026
+ { name: "directus", package: "@svadmin/directus", capabilities: ["data", "auth"], stability: "stable" },
7027
+ { name: "drizzle", package: "@svadmin/drizzle", capabilities: ["server-data", "migrations"], stability: "stable" },
7028
+ { name: "elysia", package: "@svadmin/elysia", capabilities: ["server-data"], stability: "stable" },
7029
+ { name: "firebase", package: "@svadmin/firebase", capabilities: ["data", "auth", "storage", "live"], stability: "stable" },
7030
+ { name: "hasura", package: "@svadmin/hasura", capabilities: ["data", "graphql", "live"], stability: "stable" },
7031
+ { name: "medusa", package: "@svadmin/medusa", capabilities: ["data", "auth"], stability: "stable" },
7032
+ { name: "nestjs-query", package: "@svadmin/nestjs-query", capabilities: ["data", "graphql"], stability: "stable" },
7033
+ { name: "nestjsx-crud", package: "@svadmin/nestjsx-crud", capabilities: ["data"], stability: "stable" },
7034
+ { name: "pocketbase", package: "@svadmin/pocketbase", capabilities: ["data", "auth", "storage", "live"], stability: "stable" },
7035
+ { name: "sanity", package: "@svadmin/sanity", capabilities: ["data", "live"], stability: "stable" },
7036
+ { name: "strapi", package: "@svadmin/strapi", capabilities: ["data", "auth"], stability: "stable" },
7037
+ { name: "refine-adapter", package: "@svadmin/refine-adapter", capabilities: ["adapter", "refine-bridge"], stability: "stable" },
7038
+ { name: "sso", package: "@svadmin/sso", capabilities: ["auth", "oidc", "oauth2"], stability: "stable" },
7039
+ { name: "sveltekit", package: "@svadmin/sveltekit", capabilities: ["router", "ssr"], stability: "stable" }
7040
+ ];
7041
+ var SCAFFOLD_DATA_PROVIDERS = {
7042
+ "simple-rest": {
7043
+ package: "@svadmin/simple-rest",
7044
+ capabilities: ["data", "filter", "sort", "pagination"]
7045
+ },
7046
+ supabase: {
7047
+ package: "@svadmin/supabase",
7048
+ capabilities: ["data", "auth", "live", "storage"]
7049
+ },
7050
+ graphql: {
7051
+ package: "@svadmin/graphql",
7052
+ capabilities: ["data", "graphql"]
7053
+ },
7054
+ rest: {
7055
+ package: "@svadmin/rest",
7056
+ capabilities: ["data", "rest", "custom-endpoints"]
7057
+ },
7058
+ airtable: {
7059
+ package: "@svadmin/airtable",
7060
+ capabilities: ["data"]
7061
+ },
7062
+ appwrite: {
7063
+ package: "@svadmin/appwrite",
7064
+ capabilities: ["data", "auth", "storage", "live"]
7065
+ },
7066
+ directus: {
7067
+ package: "@svadmin/directus",
7068
+ capabilities: ["data", "auth"]
7069
+ },
7070
+ drizzle: {
7071
+ package: "@svadmin/drizzle",
7072
+ capabilities: ["server-data", "migrations"]
7073
+ },
7074
+ elysia: {
7075
+ package: "@svadmin/elysia",
7076
+ capabilities: ["server-data"]
7077
+ },
7078
+ firebase: {
7079
+ package: "@svadmin/firebase",
7080
+ capabilities: ["data", "auth", "storage", "live"]
7081
+ },
7082
+ hasura: {
7083
+ package: "@svadmin/hasura",
7084
+ capabilities: ["data", "graphql", "live"]
7085
+ },
7086
+ medusa: {
7087
+ package: "@svadmin/medusa",
7088
+ capabilities: ["data", "auth"]
7089
+ },
7090
+ "nestjs-query": {
7091
+ package: "@svadmin/nestjs-query",
7092
+ capabilities: ["data", "graphql"]
7093
+ },
7094
+ "nestjsx-crud": {
7095
+ package: "@svadmin/nestjsx-crud",
7096
+ capabilities: ["data"]
7097
+ },
7098
+ pocketbase: {
7099
+ package: "@svadmin/pocketbase",
7100
+ capabilities: ["data", "auth", "storage", "live"]
7101
+ },
7102
+ sanity: {
7103
+ package: "@svadmin/sanity",
7104
+ capabilities: ["data", "live"]
7105
+ },
7106
+ strapi: {
7107
+ package: "@svadmin/strapi",
7108
+ capabilities: ["data", "auth"]
7109
+ },
7110
+ none: {
7111
+ package: null,
7112
+ capabilities: ["custom"]
7113
+ }
7114
+ };
7115
+ var SCAFFOLD_AUTH_PROVIDERS = {
7116
+ mock: {
7117
+ package: null,
7118
+ capabilities: ["demo-auth"]
7119
+ },
7120
+ jwt: {
7121
+ package: "@svadmin/simple-rest",
7122
+ capabilities: ["jwt-auth", "session"]
7123
+ },
7124
+ supabase: {
7125
+ package: "@svadmin/supabase",
7126
+ capabilities: ["auth", "session"]
7127
+ },
7128
+ none: {
7129
+ package: null,
7130
+ capabilities: []
7131
+ }
7132
+ };
7133
+ var SCAFFOLD_RESOURCES = [
7134
+ {
7135
+ name: "posts",
7136
+ label: "Posts",
7137
+ operations: ["list", "create", "edit", "show", "delete"],
7138
+ fields: [
7139
+ { key: "id", label: "ID", type: "number", required: true },
7140
+ { key: "title", label: "Title", type: "text", required: false },
7141
+ { key: "body", label: "Body", type: "textarea", required: false },
7142
+ { key: "userId", label: "Author", type: "number", required: false }
7143
+ ]
7144
+ },
7145
+ {
7146
+ name: "users",
7147
+ label: "Users",
7148
+ operations: ["list", "show"],
7149
+ fields: [
7150
+ { key: "id", label: "ID", type: "number", required: true },
7151
+ { key: "name", label: "Name", type: "text", required: false },
7152
+ { key: "username", label: "Username", type: "text", required: false },
7153
+ { key: "email", label: "Email", type: "email", required: false },
7154
+ { key: "phone", label: "Phone", type: "phone", required: false },
7155
+ { key: "website", label: "Website", type: "url", required: false }
7156
+ ]
7157
+ },
7158
+ {
7159
+ name: "comments",
7160
+ label: "Comments",
7161
+ operations: ["list", "create", "edit", "show", "delete"],
7162
+ fields: [
7163
+ { key: "id", label: "ID", type: "number", required: true },
7164
+ { key: "postId", label: "Post", type: "number", required: false },
7165
+ { key: "name", label: "Title", type: "text", required: false },
7166
+ { key: "email", label: "Email", type: "email", required: false },
7167
+ { key: "body", label: "Body", type: "textarea", required: false }
7168
+ ]
7169
+ },
7170
+ {
7171
+ name: "todos",
7172
+ label: "Todos",
7173
+ operations: ["list", "create", "edit", "show", "delete"],
7174
+ fields: [
7175
+ { key: "id", label: "ID", type: "number", required: true },
7176
+ { key: "title", label: "Title", type: "text", required: false },
7177
+ { key: "completed", label: "Done", type: "boolean", required: false },
7178
+ { key: "userId", label: "User", type: "number", required: false }
7179
+ ]
7180
+ }
7181
+ ];
7182
+ var SCAFFOLD_MIGRATION_NOTES = [
7183
+ "Run `create-svadmin doctor` after changing providers or dependencies.",
7184
+ "Apply dependency migrations with `create-svadmin migrate --write`.",
7185
+ "Keep src/svadmin.config.ts and svadmin.ai.json in sync."
7186
+ ];
7187
+ var SCAFFOLD_UI_COMPONENTS = [
7188
+ ...[
7189
+ "AdminApp",
7190
+ "AutoTable",
7191
+ "AutoForm",
7192
+ "ShowPage",
7193
+ "Layout",
7194
+ "Sidebar",
7195
+ "Header",
7196
+ "CommandPalette",
7197
+ "DataState",
7198
+ "CreateButton",
7199
+ "EditButton",
7200
+ "DeleteButton",
7201
+ "ShowButton",
7202
+ "RefreshButton",
7203
+ "ExportButton",
7204
+ "ImportButton",
7205
+ "FilterBuilder",
7206
+ "ConfigErrorScreen",
7207
+ "AppFooter",
7208
+ "ResizableGrid",
7209
+ "AreaChart",
7210
+ "ScatterChart",
7211
+ "HighlightText",
7212
+ "Marquee",
7213
+ "MediaPlayer",
7214
+ "TopProgressBar",
7215
+ "PhoneInput"
7216
+ ].map((name) => ({ name, package: "@svadmin/ui", import: "@svadmin/ui" })),
7217
+ { name: "CodeEditor", package: "@svadmin/ui", import: "@svadmin/ui/code-editor" },
7218
+ { name: "CodeEditorPresets", package: "@svadmin/ui", import: "@svadmin/ui/code-editor/presets" },
7219
+ { name: "JsonEditor", package: "@svadmin/ui", import: "@svadmin/ui/json-editor" },
7220
+ { name: "QRCode", package: "@svadmin/ui", import: "@svadmin/ui/qr-code" }
7221
+ ];
7222
+ var CUSTOM_DATA_PROVIDER_BODY = [
7223
+ "const unsupported = (): never => {",
7224
+ " throw new Error('Configure a DataProvider in src/svadmin.config.ts before using the app.');",
7225
+ "};",
7226
+ "const dataProvider: DataProvider = {",
7227
+ " getApiUrl: () => '',",
7228
+ " getList: async () => unsupported(),",
7229
+ " getOne: async () => unsupported(),",
7230
+ " create: async () => unsupported(),",
7231
+ " update: async () => unsupported(),",
7232
+ " deleteOne: async () => unsupported(),",
7233
+ "};"
7234
+ ];
7235
+ function quote(value) {
7236
+ return `'${value.replaceAll("\\", "\\\\").replaceAll("'", "\\'")}'`;
7237
+ }
7238
+ function buildSvadminConfigSource(options) {
7239
+ const imports = new Set(["import { createProviderBundle, defineAdminConfig } from '@svadmin/app';"]);
7240
+ const body = [];
7241
+ let needsSupabaseClient = false;
7242
+ switch (options.dataProvider) {
7243
+ case "simple-rest":
7244
+ imports.add("import { createSimpleRestDataProvider } from '@svadmin/simple-rest';");
7245
+ body.push("const dataProvider = await createSimpleRestDataProvider('https://jsonplaceholder.typicode.com');");
7246
+ break;
7247
+ case "supabase":
7248
+ imports.add("import { createSupabaseDataProvider } from '@svadmin/supabase';");
7249
+ needsSupabaseClient = true;
7250
+ body.push("const dataProvider = createSupabaseDataProvider(supabaseClient);");
7251
+ break;
7252
+ case "graphql":
7253
+ imports.add("import { createGraphQLDataProvider } from '@svadmin/graphql';");
7254
+ body.push("const dataProvider = await createGraphQLDataProvider('https://example.com/graphql');");
7255
+ break;
7256
+ case "none":
7257
+ imports.add("import type { DataProvider } from '@svadmin/core';");
7258
+ body.push(...CUSTOM_DATA_PROVIDER_BODY);
7259
+ break;
7260
+ default: {
7261
+ const descriptor = SCAFFOLD_DATA_PROVIDERS[options.dataProvider];
7262
+ const packageName = descriptor.package ?? "@svadmin/core";
7263
+ imports.add("import type { DataProvider } from '@svadmin/core';");
7264
+ body.push(`// TODO: configure ${packageName} in src/svadmin.config.ts.`, "async function createDataProvider(): Promise<DataProvider> {", ` throw new Error('Configure the ${options.dataProvider} data provider before running the app.');`, "}", "const dataProvider = await createDataProvider();");
7265
+ break;
7266
+ }
7267
+ }
7268
+ let authExpression = null;
7269
+ switch (options.authProvider) {
7270
+ case "mock":
7271
+ imports.add("import { mockAuthProvider } from './providers/mockAuth';");
7272
+ authExpression = "mockAuthProvider";
7273
+ break;
7274
+ case "jwt":
7275
+ imports.add("import { createSimpleRestAuthProvider } from '@svadmin/simple-rest';");
7276
+ body.push("const authProvider = createSimpleRestAuthProvider({ loginUrl: '/api/auth/login', identityUrl: '/api/auth/me' });");
7277
+ authExpression = "authProvider";
7278
+ break;
7279
+ case "supabase":
7280
+ imports.add("import { createSupabaseAuthProvider } from '@svadmin/supabase';");
7281
+ needsSupabaseClient = true;
7282
+ body.push("const authProvider = createSupabaseAuthProvider(supabaseClient);");
7283
+ authExpression = "authProvider";
7284
+ break;
7285
+ case "none":
7286
+ break;
7287
+ }
7288
+ if (needsSupabaseClient) {
7289
+ imports.add("import { supabaseClient } from './providers/supabase';");
7290
+ body.unshift("if (!supabaseClient) throw new Error('Supabase is not configured: set VITE_SUPABASE_URL and VITE_SUPABASE_ANON_KEY.');");
7291
+ }
7292
+ imports.add("import { resources } from './resources';");
7293
+ const providerEntries = [" dataProvider,", ...authExpression === null ? [] : [` authProvider: ${authExpression},`]].join(`
7294
+ `);
7295
+ return [
7296
+ "/**",
7297
+ " * svadmin application entrypoint — the first file AI tooling should read.",
7298
+ " * Generated by create-svadmin; edit freely.",
7299
+ " */",
7300
+ [...imports].join(`
7301
+ `),
7302
+ "",
7303
+ body.join(`
7304
+ `),
7305
+ "",
7306
+ "export default defineAdminConfig({",
7307
+ ` name: ${quote(options.projectName)},`,
7308
+ " providers: createProviderBundle({",
7309
+ providerEntries,
7310
+ " }),",
7311
+ " resources,",
7312
+ "});",
7313
+ ""
7314
+ ].join(`
7315
+ `);
7316
+ }
7317
+ function buildAdminAiManifest(options) {
7318
+ return {
7319
+ $schema: `./${ADMIN_SCHEMA_FILENAME}`,
7320
+ version: 1,
7321
+ project: {
7322
+ name: options.projectName,
7323
+ entrypoints: {
7324
+ config: SCAFFOLD_CONFIG_PATH,
7325
+ manifest: ADMIN_AI_MANIFEST_FILENAME
7326
+ },
7327
+ commands: {
7328
+ dev: "bun run dev",
7329
+ build: "bun run build",
7330
+ preview: "bun run preview",
7331
+ check: "bun run check"
7332
+ },
7333
+ testCommand: null,
7334
+ forbiddenImports: ["@svadmin/ui/src", "@svadmin/core/src", "@svadmin/core/dist"]
7335
+ },
7336
+ providers: {
7337
+ data: { choice: options.dataProvider, ...SCAFFOLD_DATA_PROVIDERS[options.dataProvider] },
7338
+ auth: { choice: options.authProvider, ...SCAFFOLD_AUTH_PROVIDERS[options.authProvider] }
7339
+ },
7340
+ resources: SCAFFOLD_RESOURCES,
7341
+ routes: SCAFFOLD_RESOURCES.map((resource) => ({
7342
+ resource: resource.name,
7343
+ path: `/${resource.name}`,
7344
+ operations: resource.operations
7345
+ })),
7346
+ components: SCAFFOLD_UI_COMPONENTS,
7347
+ providerCatalog: SCAFFOLD_OFFICIAL_PROVIDERS,
7348
+ migration: {
7349
+ scaffoldVersion: options.scaffoldVersion ?? "0.0.0",
7350
+ coreVersionRange: options.coreVersionRange ?? null,
7351
+ notes: SCAFFOLD_MIGRATION_NOTES
7352
+ },
7353
+ plugins: [],
7354
+ guidance: ["AGENTS.md", "DESIGN.md"]
7355
+ };
7356
+ }
7357
+ function buildScaffoldPlatformFiles(options) {
7358
+ return {
7359
+ config: {
7360
+ path: SCAFFOLD_CONFIG_PATH,
7361
+ content: buildSvadminConfigSource(options)
7362
+ },
7363
+ aiManifest: {
7364
+ path: ADMIN_AI_MANIFEST_FILENAME,
7365
+ content: `${JSON.stringify(buildAdminAiManifest(options), null, 2)}
7366
+ `
7367
+ },
7368
+ schema: {
7369
+ path: ADMIN_SCHEMA_FILENAME,
7370
+ content: `${JSON.stringify(buildAdminSchemaJson(), null, 2)}
7371
+ `
7372
+ }
7373
+ };
7374
+ }
7375
+ function buildAdminSchemaJson() {
7376
+ const provider = {
7377
+ type: "object",
7378
+ required: ["choice", "package", "capabilities"],
7379
+ properties: {
7380
+ choice: { type: "string" },
7381
+ package: { type: ["string", "null"] },
7382
+ capabilities: { type: "array", items: { type: "string" } }
7383
+ }
7384
+ };
7385
+ const field = {
7386
+ type: "object",
7387
+ required: ["key", "label", "type", "required"],
7388
+ properties: {
7389
+ key: { type: "string" },
7390
+ label: { type: "string" },
7391
+ type: { type: "string" },
7392
+ required: { type: "boolean" }
7393
+ }
7394
+ };
7395
+ const resource = {
7396
+ type: "object",
7397
+ required: ["name", "label", "fields", "operations"],
7398
+ properties: {
7399
+ name: { type: "string" },
7400
+ label: { type: "string" },
7401
+ fields: { type: "array", items: field },
7402
+ operations: { type: "array", items: { type: "string" } }
7403
+ }
7404
+ };
7405
+ return {
7406
+ $schema: "https://json-schema.org/draft/2020-12/schema",
7407
+ $id: "https://svadmin.dev/schemas/svadmin.ai.json",
7408
+ title: "svadmin AI manifest",
7409
+ type: "object",
7410
+ required: ["version", "project", "providers", "resources"],
7411
+ properties: {
7412
+ $schema: { type: "string" },
7413
+ version: { const: 1 },
7414
+ project: {
7415
+ type: "object",
7416
+ required: ["name", "entrypoints", "commands"],
7417
+ properties: {
7418
+ name: { type: "string" },
7419
+ entrypoints: {
7420
+ type: "object",
7421
+ required: ["config", "manifest"],
7422
+ properties: { config: { type: "string" }, manifest: { type: "string" } }
7423
+ },
7424
+ commands: { type: "object", additionalProperties: { type: "string" } },
7425
+ testCommand: { type: ["string", "null"] },
7426
+ forbiddenImports: { type: "array", items: { type: "string" } }
7427
+ }
7428
+ },
7429
+ providers: {
7430
+ type: "object",
7431
+ required: ["data", "auth"],
7432
+ properties: { data: provider, auth: provider }
7433
+ },
7434
+ resources: { type: "array", items: resource },
7435
+ routes: {
7436
+ type: "array",
7437
+ items: {
7438
+ type: "object",
7439
+ required: ["resource", "path", "operations"],
7440
+ properties: {
7441
+ resource: { type: "string" },
7442
+ path: { type: "string" },
7443
+ operations: { type: "array", items: { type: "string" } }
7444
+ }
7445
+ }
7446
+ },
7447
+ components: {
7448
+ type: "array",
7449
+ items: {
7450
+ type: "object",
7451
+ required: ["name", "package", "import"],
7452
+ properties: {
7453
+ name: { type: "string" },
7454
+ package: { type: "string" },
7455
+ import: { type: "string" }
7456
+ }
7457
+ }
7458
+ },
7459
+ providerCatalog: {
7460
+ type: "array",
7461
+ items: {
7462
+ type: "object",
7463
+ required: ["name", "package", "capabilities", "stability"],
7464
+ properties: {
7465
+ name: { type: "string" },
7466
+ package: { type: "string" },
7467
+ capabilities: { type: "array", items: { type: "string" } },
7468
+ stability: { type: "string" }
7469
+ }
7470
+ }
7471
+ },
7472
+ migration: {
7473
+ type: "object",
7474
+ required: ["scaffoldVersion", "notes"],
7475
+ properties: {
7476
+ scaffoldVersion: { type: "string" },
7477
+ coreVersionRange: { type: ["string", "null"] },
7478
+ notes: { type: "array", items: { type: "string" } }
7479
+ }
7480
+ },
7481
+ plugins: { type: "array" },
7482
+ guidance: { type: "array", items: { type: "string" } }
7483
+ }
7484
+ };
7485
+ }
7486
+ function parseManifest(path) {
7487
+ let parsed;
7488
+ try {
7489
+ parsed = JSON.parse(readFileSync2(path, "utf8"));
7490
+ } catch {
7491
+ return {
7492
+ issue: {
7493
+ path,
7494
+ message: "svadmin.ai.json is not valid JSON",
7495
+ action: "regenerate it or run `create-svadmin doctor` after fixing the file"
7496
+ }
7497
+ };
7498
+ }
7499
+ if (typeof parsed !== "object" || parsed === null || Reflect.get(parsed, "version") !== 1) {
7500
+ return {
7501
+ issue: {
7502
+ path,
7503
+ message: "svadmin.ai.json must be an object with version 1",
7504
+ action: "regenerate the project platform files"
7505
+ }
7506
+ };
7507
+ }
7508
+ return { manifest: parsed };
7509
+ }
7510
+ function declaredDependencies(project) {
7511
+ return new Set([
7512
+ ...Object.keys(project.dependencies ?? {}),
7513
+ ...Object.keys(project.devDependencies ?? {})
7514
+ ]);
7515
+ }
7516
+ function readInstalledProviderMeta(projectDirectory, packageName) {
7517
+ const manifestPath = join(projectDirectory, "node_modules", ...packageName.split("/"), "package.json");
7518
+ if (!existsSync(manifestPath))
7519
+ return null;
7520
+ try {
7521
+ const parsed = JSON.parse(readFileSync2(manifestPath, "utf8"));
7522
+ const meta = typeof parsed === "object" && parsed !== null ? Reflect.get(parsed, "svadmin") : undefined;
7523
+ return typeof meta === "object" && meta !== null ? meta : null;
7524
+ } catch {
7525
+ return null;
7526
+ }
7527
+ }
7528
+ function firstVersion(range) {
7529
+ const match = /(\d+)\.(\d+)\.(\d+)/u.exec(range);
7530
+ if (match === null)
7531
+ return null;
7532
+ return [Number(match[1]), Number(match[2]), Number(match[3])];
7533
+ }
7534
+ function coreRangesCompatible(projectRange, moduleRange) {
7535
+ const project = firstVersion(projectRange);
7536
+ const module = firstVersion(moduleRange);
7537
+ if (project === null || module === null)
7538
+ return true;
7539
+ if (project[0] !== module[0])
7540
+ return false;
7541
+ return project[0] !== 0 || project[1] === module[1];
7542
+ }
7543
+ function checkAdminManifest(projectDirectory, project) {
7544
+ const configPath = join(projectDirectory, SCAFFOLD_CONFIG_PATH);
7545
+ if (!existsSync(configPath))
7546
+ return [];
7547
+ const manifestPath = join(projectDirectory, ADMIN_AI_MANIFEST_FILENAME);
7548
+ if (!existsSync(manifestPath)) {
7549
+ return [{
7550
+ path: manifestPath,
7551
+ message: `${SCAFFOLD_CONFIG_PATH} exists but ${ADMIN_AI_MANIFEST_FILENAME} is missing`,
7552
+ action: "regenerate the platform files so AI tooling has a stable entrypoint"
7553
+ }];
7554
+ }
7555
+ const { manifest, issue } = parseManifest(manifestPath);
7556
+ if (issue !== undefined)
7557
+ return [issue];
7558
+ if (manifest === undefined)
7559
+ return [];
7560
+ const issues = [];
7561
+ if (!existsSync(join(projectDirectory, ADMIN_SCHEMA_FILENAME))) {
7562
+ issues.push({
7563
+ path: join(projectDirectory, ADMIN_SCHEMA_FILENAME),
7564
+ message: `${ADMIN_AI_MANIFEST_FILENAME} is present but ${ADMIN_SCHEMA_FILENAME} is missing`,
7565
+ action: "regenerate the platform files so editors can validate the manifest"
7566
+ });
7567
+ }
7568
+ const dependencies = declaredDependencies(project);
7569
+ const providerPackages = [
7570
+ manifest.providers.data.package,
7571
+ manifest.providers.auth.package
7572
+ ].filter((name) => name !== null);
7573
+ const declaredCore = project.dependencies?.["@svadmin/core"] ?? project.devDependencies?.["@svadmin/core"];
7574
+ for (const packageName of new Set(providerPackages)) {
7575
+ if (!dependencies.has(packageName)) {
7576
+ issues.push({
7577
+ path: manifestPath,
7578
+ message: `svadmin.ai.json declares provider "${packageName}" but package.json does not depend on it`,
7579
+ action: `add ${packageName} to package.json or update svadmin.ai.json`
7580
+ });
7581
+ continue;
7582
+ }
7583
+ const meta = readInstalledProviderMeta(projectDirectory, packageName);
7584
+ if (meta === null)
7585
+ continue;
7586
+ if (meta.capabilities !== undefined && !Array.isArray(meta.capabilities)) {
7587
+ issues.push({
7588
+ path: manifestPath,
7589
+ message: `${packageName} declares a non-array svadmin.capabilities`,
7590
+ action: "fix the provider package metadata"
7591
+ });
7592
+ }
7593
+ if (typeof meta.core === "string" && declaredCore !== undefined && !coreRangesCompatible(declaredCore, meta.core)) {
7594
+ issues.push({
7595
+ path: manifestPath,
7596
+ message: `${packageName} declares @svadmin/core ${meta.core}, incompatible with the project range ${declaredCore}`,
7597
+ action: `align @svadmin/core with ${meta.core} or upgrade ${packageName}`
7598
+ });
7599
+ }
7600
+ }
7601
+ return issues;
7602
+ }
7603
+
6901
7604
  // src/project-maintenance.ts
6902
7605
  import {
6903
7606
  constants,
6904
7607
  copyFileSync,
6905
- readFileSync as readFileSync2,
7608
+ readFileSync as readFileSync3,
6906
7609
  renameSync,
6907
7610
  unlinkSync,
6908
7611
  writeFileSync
@@ -6925,7 +7628,7 @@ function parseMaintainedPackageJson(packageJsonCandidate) {
6925
7628
  return packageJson;
6926
7629
  }
6927
7630
  function readMaintainedPackageJson(packagePath) {
6928
- const parsed = JSON.parse(readFileSync2(packagePath, "utf8"));
7631
+ const parsed = JSON.parse(readFileSync3(packagePath, "utf8"));
6929
7632
  return parseMaintainedPackageJson(parsed);
6930
7633
  }
6931
7634
  function allProjectDependencies(project) {
@@ -7186,17 +7889,269 @@ function writeProjectPackageJsonUpgrade(packagePath, scaffold, backupDate) {
7186
7889
  return { wrote: true, backupPath, plan: plannedUpgrade.plan };
7187
7890
  }
7188
7891
 
7892
+ // src/add-command.ts
7893
+ var RESOURCE_NAME_PATTERN = /^[a-z][a-z0-9_]*$/;
7894
+ function parseAddArguments(args) {
7895
+ const [kind, ...rest] = args;
7896
+ if (kind !== "resource" && kind !== "provider" && kind !== "auth") {
7897
+ throw new Error("Usage: create-svadmin add <resource|provider|auth> <name> [--project-dir <dir>] [--write]");
7898
+ }
7899
+ let projectDirectory = process.cwd();
7900
+ let write = false;
7901
+ const positional = [];
7902
+ for (let index = 0;index < rest.length; index++) {
7903
+ const argument = rest[index];
7904
+ if (argument === "--write") {
7905
+ write = true;
7906
+ } else if (argument === "--project-dir") {
7907
+ const value = rest[index + 1];
7908
+ if (value === undefined)
7909
+ throw new Error("--project-dir requires a value");
7910
+ projectDirectory = path4.resolve(process.cwd(), value);
7911
+ index++;
7912
+ } else if (argument === undefined) {
7913
+ continue;
7914
+ } else if (argument.startsWith("-")) {
7915
+ throw new Error(`Unknown option: ${argument}`);
7916
+ } else {
7917
+ positional.push(argument);
7918
+ }
7919
+ }
7920
+ if (positional.length !== 1) {
7921
+ throw new Error(`Expected exactly one target, received: ${positional.join(", ") || "(none)"}`);
7922
+ }
7923
+ return { kind, target: positional[0], projectDirectory, write };
7924
+ }
7925
+ function humanize4(name) {
7926
+ return name.split("_").filter(Boolean).map((part) => part.charAt(0).toUpperCase() + part.slice(1)).join(" ");
7927
+ }
7928
+ function assertProject(projectDirectory) {
7929
+ if (!fs4.existsSync(path4.join(projectDirectory, "package.json"))) {
7930
+ throw new Error(`Not a Node project: ${path4.join(projectDirectory, "package.json")} is missing`);
7931
+ }
7932
+ }
7933
+ function resourceFileContents(name) {
7934
+ const label = humanize4(name);
7935
+ return {
7936
+ index: `export { ${name}Resource, ${name}Definition } from './${name}.resource';
7937
+ `,
7938
+ resource: `import { Type } from '@sinclair/typebox';
7939
+ import { defineResource, type AdminResourceDefinition } from '@svadmin/core';
7940
+
7941
+ /**
7942
+ * ${label} runtime contract.
7943
+ * Extend the create/update schemas before enabling writes; empty object schemas
7944
+ * keep writes disabled until fields are declared.
7945
+ */
7946
+ export const ${name}Resource = defineResource('${name}', {
7947
+ record: Type.Object({
7948
+ id: Type.String(),
7949
+ }),
7950
+ create: Type.Object({}),
7951
+ update: Type.Object({}),
7952
+ });
7953
+
7954
+ /** Menu and field metadata consumed by the resource registry. */
7955
+ export const ${name}Definition: AdminResourceDefinition = {
7956
+ name: '${name}',
7957
+ label: '${label}',
7958
+ icon: 'file',
7959
+ fields: [
7960
+ { key: 'id', label: 'ID', type: 'text', showInForm: false },
7961
+ ],
7962
+ contract: ${name}Resource,
7963
+ };
7964
+ `
7965
+ };
7966
+ }
7967
+ function planAddResource(projectDirectory, resourceName) {
7968
+ assertProject(projectDirectory);
7969
+ if (!RESOURCE_NAME_PATTERN.test(resourceName)) {
7970
+ throw new Error(`Invalid resource name "${resourceName}"; use lowercase letters, digits, and underscores (for example "order_items")`);
7971
+ }
7972
+ const files = resourceFileContents(resourceName);
7973
+ const base = path4.posix.join("src", "features", resourceName);
7974
+ const contents = {
7975
+ [`${base}/index.ts`]: files.index,
7976
+ [`${base}/${resourceName}.resource.ts`]: files.resource
7977
+ };
7978
+ const entries = Object.entries(contents).map(([relativePath, content]) => ({
7979
+ relativePath,
7980
+ content,
7981
+ filePath: path4.join(projectDirectory, relativePath),
7982
+ exists: fs4.existsSync(path4.join(projectDirectory, relativePath))
7983
+ }));
7984
+ return {
7985
+ projectDirectory,
7986
+ resourceName,
7987
+ entries,
7988
+ registrationHint: `Register it in src/resources.ts:
7989
+ import { ${resourceName}Definition } from './features/${resourceName}';
7990
+ // then add ${resourceName}Definition to the resources array`
7991
+ };
7992
+ }
7993
+ function writeAddResource(plan) {
7994
+ const written = [];
7995
+ const preserved = [];
7996
+ for (const entry of plan.entries) {
7997
+ if (entry.exists || fs4.existsSync(entry.filePath)) {
7998
+ preserved.push(entry.relativePath);
7999
+ continue;
8000
+ }
8001
+ fs4.mkdirSync(path4.dirname(entry.filePath), { recursive: true });
8002
+ fs4.writeFileSync(entry.filePath, entry.content);
8003
+ written.push(entry.relativePath);
8004
+ }
8005
+ return { written, preserved };
8006
+ }
8007
+ function providerPackages(scaffold, kind, choice) {
8008
+ const packs = kind === "provider" ? scaffold.svadmin.dataProviders[choice] : scaffold.svadmin.authProviders[choice];
8009
+ const packages = new Map;
8010
+ for (const packName of packs) {
8011
+ const pack = scaffold.svadmin.dependencyPacks[packName];
8012
+ if (pack === undefined)
8013
+ throw new Error(`Unknown dependency pack: ${packName}`);
8014
+ for (const [packageName, version] of Object.entries(pack))
8015
+ packages.set(packageName, version);
8016
+ }
8017
+ return [...packages].map(([packageName, version]) => ({ packageName, version }));
8018
+ }
8019
+ function readManifest(manifestPath) {
8020
+ if (!fs4.existsSync(manifestPath))
8021
+ return null;
8022
+ try {
8023
+ const parsed = JSON.parse(fs4.readFileSync(manifestPath, "utf8"));
8024
+ if (typeof parsed !== "object" || parsed === null || Reflect.get(parsed, "version") !== 1)
8025
+ return null;
8026
+ return parsed;
8027
+ } catch {
8028
+ return null;
8029
+ }
8030
+ }
8031
+ function planAddProvider(projectDirectory, scaffold, kind, choice) {
8032
+ assertProject(projectDirectory);
8033
+ const validChoices = kind === "provider" ? DATA_PROVIDER_CHOICES : AUTH_PROVIDER_CHOICES;
8034
+ if (!validChoices.includes(choice)) {
8035
+ throw new Error(`Unknown ${kind} "${choice}"; expected one of: ${validChoices.join(", ")}`);
8036
+ }
8037
+ const packageJsonPath = path4.join(projectDirectory, "package.json");
8038
+ const project = readMaintainedPackageJson(packageJsonPath);
8039
+ const dependencies = { ...project.dependencies ?? {} };
8040
+ const devDependencies = { ...project.devDependencies ?? {} };
8041
+ const addedDependencies = [];
8042
+ for (const dependency of providerPackages(scaffold, kind, choice)) {
8043
+ if (dependencies[dependency.packageName] === undefined && devDependencies[dependency.packageName] === undefined) {
8044
+ dependencies[dependency.packageName] = dependency.version;
8045
+ addedDependencies.push(dependency);
8046
+ }
8047
+ }
8048
+ const updatedPackageJson = { ...project, dependencies, devDependencies };
8049
+ const manifestPath = path4.join(projectDirectory, ADMIN_AI_MANIFEST_FILENAME);
8050
+ const manifest = readManifest(manifestPath);
8051
+ const descriptor = kind === "provider" ? SCAFFOLD_DATA_PROVIDERS[choice] : SCAFFOLD_AUTH_PROVIDERS[choice];
8052
+ const updatedManifest = manifest === null ? null : kind === "provider" ? { ...manifest, providers: { ...manifest.providers, data: { choice, ...descriptor } } } : { ...manifest, providers: { ...manifest.providers, auth: { choice, ...descriptor } } };
8053
+ return {
8054
+ projectDirectory,
8055
+ kind,
8056
+ choice,
8057
+ packageJsonPath,
8058
+ updatedPackageJson: addedDependencies.length === 0 ? null : updatedPackageJson,
8059
+ addedDependencies,
8060
+ manifestPath,
8061
+ updatedManifest: manifest === null ? null : updatedManifest
8062
+ };
8063
+ }
8064
+ function writeAddProvider(plan) {
8065
+ const written = [];
8066
+ const preserved = [];
8067
+ if (plan.updatedPackageJson !== null) {
8068
+ fs4.writeFileSync(plan.packageJsonPath, `${JSON.stringify(plan.updatedPackageJson, null, 2)}
8069
+ `);
8070
+ written.push("package.json");
8071
+ } else {
8072
+ preserved.push("package.json");
8073
+ }
8074
+ if (plan.updatedManifest !== null && fs4.existsSync(plan.manifestPath)) {
8075
+ fs4.writeFileSync(plan.manifestPath, `${JSON.stringify(plan.updatedManifest, null, 2)}
8076
+ `);
8077
+ written.push(ADMIN_AI_MANIFEST_FILENAME);
8078
+ }
8079
+ return { written, preserved };
8080
+ }
8081
+ function printAddResult(wrote, result, hint) {
8082
+ if (wrote) {
8083
+ if (result.written.length > 0) {
8084
+ console.log(import_picocolors3.default.green(` ✔ wrote ${result.written.join(", ")}`));
8085
+ }
8086
+ if (result.preserved.length > 0) {
8087
+ console.log(import_picocolors3.default.dim(` • preserved ${result.preserved.join(", ")}`));
8088
+ }
8089
+ }
8090
+ if (hint !== undefined)
8091
+ console.log(`
8092
+ ${hint}`);
8093
+ console.log();
8094
+ }
8095
+ function addCommand(args, scaffold) {
8096
+ const options = parseAddArguments(args);
8097
+ console.log(`
8098
+ svadmin add ${options.kind} ${options.target} — ${options.projectDirectory}`);
8099
+ if (options.kind === "resource") {
8100
+ const plan = planAddResource(options.projectDirectory, options.target);
8101
+ for (const entry of plan.entries) {
8102
+ console.log(` ${entry.exists ? "preserve" : "add"} ${entry.relativePath}`);
8103
+ }
8104
+ if (!options.write) {
8105
+ console.log(`
8106
+ Dry run only; re-run with --write to create missing files.`);
8107
+ printAddResult(false, { written: [], preserved: [] }, plan.registrationHint);
8108
+ return;
8109
+ }
8110
+ printAddResult(true, writeAddResource(plan), plan.registrationHint);
8111
+ return;
8112
+ }
8113
+ const plan = planAddProvider(options.projectDirectory, scaffold, options.kind, options.target);
8114
+ if (plan.addedDependencies.length === 0) {
8115
+ console.log(import_picocolors3.default.green(" ✔ dependencies already present; nothing to add."));
8116
+ } else {
8117
+ for (const dependency of plan.addedDependencies) {
8118
+ console.log(` add ${dependency.packageName}@${dependency.version}`);
8119
+ }
8120
+ }
8121
+ if (plan.updatedManifest !== null) {
8122
+ console.log(` update ${ADMIN_AI_MANIFEST_FILENAME} -> ${options.kind}: ${options.target}`);
8123
+ }
8124
+ if (!options.write) {
8125
+ console.log(`
8126
+ Dry run only; re-run with --write to update package.json and the AI manifest.`);
8127
+ console.log(import_picocolors3.default.dim(" Update src/svadmin.config.ts to wire the new provider."));
8128
+ console.log();
8129
+ return;
8130
+ }
8131
+ printAddResult(true, writeAddProvider(plan), "Update src/svadmin.config.ts to wire the new provider.");
8132
+ }
8133
+
7189
8134
  // src/index.ts
7190
8135
  var __filename2 = fileURLToPath(import.meta.url);
7191
- var __dirname2 = path4.dirname(__filename2);
8136
+ var __dirname2 = path5.dirname(__filename2);
7192
8137
  function loadShippedScaffoldManifest() {
7193
- return loadScaffoldManifest(path4.join(__dirname2, "..", "scaffold-manifest.json"));
8138
+ return loadScaffoldManifest(path5.join(__dirname2, "..", "scaffold-manifest.json"));
8139
+ }
8140
+ function shippedCliVersion() {
8141
+ try {
8142
+ const raw = fs5.readFileSync(path5.join(__dirname2, "..", "package.json"), "utf8");
8143
+ const parsed = JSON.parse(raw);
8144
+ const version = typeof parsed === "object" && parsed !== null ? Reflect.get(parsed, "version") : undefined;
8145
+ return typeof version === "string" ? version : "0.0.0";
8146
+ } catch {
8147
+ return "0.0.0";
8148
+ }
7194
8149
  }
7195
8150
  function projectDirectoryFromArguments(positional) {
7196
8151
  if (positional.length > 1) {
7197
8152
  throw new Error(`Expected at most one project directory, received: ${positional.join(", ")}`);
7198
8153
  }
7199
- return path4.resolve(process.cwd(), positional[0] ?? ".");
8154
+ return path5.resolve(process.cwd(), positional[0] ?? ".");
7200
8155
  }
7201
8156
  function doctorProjectDirectory(args) {
7202
8157
  const unknownOption = args.find((argument) => argument.startsWith("-"));
@@ -7232,52 +8187,61 @@ function upgradeChangeMessage(change) {
7232
8187
  return `update ${change.packageName} from ${change.from ?? "missing"} to ${change.to}`;
7233
8188
  }
7234
8189
  function printDoctorIssue(issue) {
7235
- const marker = issue.kind === "drift" || issue.kind === "section" ? import_picocolors3.default.yellow(" ⚠") : import_picocolors3.default.red(" ✗");
8190
+ const marker = issue.kind === "drift" || issue.kind === "section" ? import_picocolors4.default.yellow(" ⚠") : import_picocolors4.default.red(" ✗");
7236
8191
  console.log(`${marker} ${doctorIssueMessage(issue)}`);
7237
- console.log(import_picocolors3.default.dim(` → ${issue.action}`));
8192
+ console.log(import_picocolors4.default.dim(` → ${issue.action}`));
7238
8193
  }
7239
8194
  function printDoctorReport(report, projectDirectory) {
7240
8195
  console.log();
7241
- console.log(import_picocolors3.default.bold(`svadmin doctor — ${projectDirectory}`));
8196
+ console.log(import_picocolors4.default.bold(`svadmin doctor — ${projectDirectory}`));
7242
8197
  if (report.status === "clean") {
7243
- console.log(import_picocolors3.default.green(" ✔ Dependencies match the shipped svadmin scaffold."));
8198
+ console.log(import_picocolors4.default.green(" ✔ Dependencies match the shipped svadmin scaffold."));
7244
8199
  } else {
7245
8200
  for (const issue of report.issues)
7246
8201
  printDoctorIssue(issue);
7247
8202
  console.log();
7248
- console.log(import_picocolors3.default.yellow(` ${report.issues.length} actionable issue(s) found.`));
8203
+ console.log(import_picocolors4.default.yellow(` ${report.issues.length} actionable issue(s) found.`));
7249
8204
  }
7250
8205
  console.log();
7251
8206
  }
7252
8207
  function doctor(args) {
7253
8208
  const projectDirectory = doctorProjectDirectory(args);
7254
- const project = readMaintainedPackageJson(path4.join(projectDirectory, "package.json"));
8209
+ const project = readMaintainedPackageJson(path5.join(projectDirectory, "package.json"));
7255
8210
  const report = doctorProjectPackageJson(project, loadShippedScaffoldManifest());
7256
8211
  printDoctorReport(report, projectDirectory);
7257
- process.exitCode = report.exitCode;
8212
+ const manifestIssues = checkAdminManifest(projectDirectory, project);
8213
+ if (manifestIssues.length > 0) {
8214
+ console.log(import_picocolors4.default.bold(" Platform entrypoints:"));
8215
+ for (const issue of manifestIssues) {
8216
+ console.log(import_picocolors4.default.yellow(` ⚠ ${issue.message}`));
8217
+ console.log(import_picocolors4.default.dim(` → ${issue.action}`));
8218
+ }
8219
+ console.log();
8220
+ }
8221
+ process.exitCode = report.exitCode === 0 && manifestIssues.length === 0 ? 0 : 1;
7258
8222
  }
7259
8223
  function printUpgradeChanges(upgradeExecution) {
7260
8224
  for (const change of upgradeExecution.plan.changes) {
7261
- console.log(` ${import_picocolors3.default.cyan("•")} ${upgradeChangeMessage(change)}`);
8225
+ console.log(` ${import_picocolors4.default.cyan("•")} ${upgradeChangeMessage(change)}`);
7262
8226
  }
7263
8227
  console.log();
7264
8228
  }
7265
8229
  function printUpgradeOutcome(upgradeExecution, packagePath) {
7266
8230
  if (upgradeExecution.wrote) {
7267
- console.log(import_picocolors3.default.green(" ✔ package.json updated."));
7268
- console.log(` Backup: ${import_picocolors3.default.cyan(upgradeExecution.backupPath)}`);
7269
- console.log(` Restore by copying the backup over: ${import_picocolors3.default.cyan(packagePath)}`);
8231
+ console.log(import_picocolors4.default.green(" ✔ package.json updated."));
8232
+ console.log(` Backup: ${import_picocolors4.default.cyan(upgradeExecution.backupPath)}`);
8233
+ console.log(` Restore by copying the backup over: ${import_picocolors4.default.cyan(packagePath)}`);
7270
8234
  } else {
7271
- console.log(import_picocolors3.default.yellow(" Dry run only; package.json was not changed."));
8235
+ console.log(import_picocolors4.default.yellow(" Dry run only; package.json was not changed."));
7272
8236
  console.log(" Re-run this command with --write to apply the plan.");
7273
8237
  }
7274
8238
  console.log();
7275
8239
  }
7276
8240
  function printUpgradeExecution(upgradeExecution, projectDirectory, packagePath) {
7277
8241
  console.log();
7278
- console.log(import_picocolors3.default.bold(`svadmin upgrade — ${projectDirectory}`));
8242
+ console.log(import_picocolors4.default.bold(`svadmin upgrade — ${projectDirectory}`));
7279
8243
  if (upgradeExecution.plan.changes.length === 0) {
7280
- console.log(import_picocolors3.default.green(" ✔ package.json already matches the shipped scaffold."));
8244
+ console.log(import_picocolors4.default.green(" ✔ package.json already matches the shipped scaffold."));
7281
8245
  console.log();
7282
8246
  return;
7283
8247
  }
@@ -7286,61 +8250,64 @@ function printUpgradeExecution(upgradeExecution, projectDirectory, packagePath)
7286
8250
  }
7287
8251
  function upgrade(args) {
7288
8252
  const commandArguments = parseUpgradeArguments(args);
7289
- const packagePath = path4.join(commandArguments.projectDirectory, "package.json");
8253
+ const packagePath = path5.join(commandArguments.projectDirectory, "package.json");
7290
8254
  const scaffoldManifest = loadShippedScaffoldManifest();
7291
8255
  const upgradeExecution = commandArguments.write ? writeProjectPackageJsonUpgrade(packagePath, scaffoldManifest, new Date) : planProjectPackageFileUpgrade(packagePath, scaffoldManifest);
7292
8256
  printUpgradeExecution(upgradeExecution, commandArguments.projectDirectory, packagePath);
7293
8257
  }
7294
8258
  var GUIDANCE_FILES = ["DESIGN.md", "AGENTS.md"];
7295
8259
  function missingGuidanceFiles(projectDirectory) {
7296
- return GUIDANCE_FILES.filter((fileName) => !fs4.existsSync(path4.join(projectDirectory, fileName)));
8260
+ return GUIDANCE_FILES.filter((fileName) => !fs5.existsSync(path5.join(projectDirectory, fileName)));
7297
8261
  }
7298
8262
  function printGuidancePlan(projectDirectory, missingFiles) {
7299
8263
  console.log();
7300
- console.log(import_picocolors3.default.bold(`svadmin guidance — ${projectDirectory}`));
8264
+ console.log(import_picocolors4.default.bold(`svadmin guidance — ${projectDirectory}`));
7301
8265
  for (const fileName of missingFiles) {
7302
- console.log(` ${import_picocolors3.default.cyan("•")} add ${fileName}`);
8266
+ console.log(` ${import_picocolors4.default.cyan("•")} add ${fileName}`);
7303
8267
  }
7304
8268
  console.log();
7305
8269
  }
7306
8270
  function installMissingGuidanceFiles(guidanceDirectory, projectDirectory, missingFiles) {
7307
8271
  for (const fileName of missingFiles) {
7308
- fs4.copyFileSync(path4.join(guidanceDirectory, fileName), path4.join(projectDirectory, fileName));
8272
+ fs5.copyFileSync(path5.join(guidanceDirectory, fileName), path5.join(projectDirectory, fileName));
7309
8273
  }
7310
8274
  }
7311
8275
  function guidance(args) {
7312
8276
  const { projectDirectory, write } = parseUpgradeArguments(args);
7313
- const guidanceDirectory = path4.join(__dirname2, "..", "guidance");
7314
- if (!fs4.existsSync(projectDirectory))
8277
+ const guidanceDirectory = path5.join(__dirname2, "..", "guidance");
8278
+ if (!fs5.existsSync(projectDirectory))
7315
8279
  throw new Error(`Project directory does not exist: ${projectDirectory}`);
7316
- if (!fs4.existsSync(guidanceDirectory))
8280
+ if (!fs5.existsSync(guidanceDirectory))
7317
8281
  throw new Error("Shipped svadmin guidance files are missing");
7318
8282
  const missingFiles = missingGuidanceFiles(projectDirectory);
7319
8283
  if (missingFiles.length === 0) {
7320
- console.log(import_picocolors3.default.green(`
8284
+ console.log(import_picocolors4.default.green(`
7321
8285
  ✔ DESIGN.md and AGENTS.md already exist; nothing was changed.
7322
8286
  `));
7323
8287
  return;
7324
8288
  }
7325
8289
  printGuidancePlan(projectDirectory, missingFiles);
7326
8290
  if (!write) {
7327
- console.log(import_picocolors3.default.yellow(` Dry run only; re-run with --write to add missing guidance files.
8291
+ console.log(import_picocolors4.default.yellow(` Dry run only; re-run with --write to add missing guidance files.
7328
8292
  `));
7329
8293
  return;
7330
8294
  }
7331
8295
  installMissingGuidanceFiles(guidanceDirectory, projectDirectory, missingFiles);
7332
- console.log(import_picocolors3.default.green(` ✔ Added ${missingFiles.length} guidance file(s); existing files were preserved.`));
8296
+ console.log(import_picocolors4.default.green(` ✔ Added ${missingFiles.length} guidance file(s); existing files were preserved.`));
7333
8297
  console.log();
7334
8298
  }
7335
- async function init() {
8299
+ async function init(args) {
7336
8300
  console.log();
7337
- console.log(import_picocolors3.default.cyan(" ╔═══════════════════════════════════╗"));
7338
- console.log(import_picocolors3.default.cyan(" ║ ") + import_picocolors3.default.bold("create-svadmin") + import_picocolors3.default.cyan(" ║"));
7339
- console.log(import_picocolors3.default.cyan(" ║ ") + import_picocolors3.default.dim("Headless Admin for Svelte 5") + import_picocolors3.default.cyan(" ║"));
7340
- console.log(import_picocolors3.default.cyan(" ╚═══════════════════════════════════╝"));
8301
+ console.log(import_picocolors4.default.cyan(" ╔═══════════════════════════════════╗"));
8302
+ console.log(import_picocolors4.default.cyan(" ║ ") + import_picocolors4.default.bold("create-svadmin") + import_picocolors4.default.cyan(" ║"));
8303
+ console.log(import_picocolors4.default.cyan(" ║ ") + import_picocolors4.default.dim("Headless Admin for Svelte 5") + import_picocolors4.default.cyan(" ║"));
8304
+ console.log(import_picocolors4.default.cyan(" ╚═══════════════════════════════════╝"));
7341
8305
  console.log();
7342
- const response = await import_prompts2.default([
7343
- {
8306
+ const parsed = parseInitArguments(args);
8307
+ const presetSelections = resolvePresetSelections(parsed);
8308
+ const questions = [];
8309
+ if (parsed.projectName === undefined) {
8310
+ questions.push({
7344
8311
  type: "text",
7345
8312
  name: "projectName",
7346
8313
  message: "Project name:",
@@ -7348,99 +8315,130 @@ async function init() {
7348
8315
  validate: (value) => {
7349
8316
  if (!value.trim())
7350
8317
  return "Project name is required";
7351
- if (fs4.existsSync(value.trim()) && fs4.readdirSync(value.trim()).length > 0) {
8318
+ if (fs5.existsSync(value.trim()) && fs5.readdirSync(value.trim()).length > 0) {
7352
8319
  return "Directory already exists and is not empty";
7353
8320
  }
7354
8321
  return true;
7355
8322
  }
7356
- },
7357
- {
7358
- type: "select",
7359
- name: "dataProvider",
7360
- message: "Data Provider:",
7361
- choices: [
7362
- { title: "Simple REST", value: "simple-rest", description: "Standard JSON APIs / JSON Server" },
7363
- { title: "Supabase", value: "supabase", description: "PostgreSQL Backend-as-a-Service" },
7364
- { title: "GraphQL", value: "graphql", description: "Generic GraphQL endpoints" },
7365
- { title: "Custom", value: "none", description: "Implement your own DataProvider" }
7366
- ],
7367
- initial: 0
7368
- },
7369
- {
7370
- type: "select",
7371
- name: "authProvider",
7372
- message: "Auth Provider:",
7373
- choices: [
7374
- { title: "Mock (Demo)", value: "mock", description: "Built-in mock for development" },
7375
- { title: "Simple REST JWT", value: "jwt", description: "JWT-based auth via REST API" },
7376
- { title: "Supabase Auth", value: "supabase", description: "Supabase authentication" },
7377
- { title: "None", value: "none", description: "No authentication" }
7378
- ],
7379
- initial: 0
7380
- },
7381
- {
8323
+ });
8324
+ }
8325
+ if (presetSelections === undefined) {
8326
+ if (parsed.dataProvider === undefined) {
8327
+ questions.push({
8328
+ type: "select",
8329
+ name: "dataProvider",
8330
+ message: "Data Provider:",
8331
+ choices: [
8332
+ { title: "Simple REST", value: "simple-rest", description: "Standard JSON APIs / JSON Server" },
8333
+ { title: "Supabase", value: "supabase", description: "PostgreSQL Backend-as-a-Service" },
8334
+ { title: "GraphQL", value: "graphql", description: "Generic GraphQL endpoints" },
8335
+ { title: "Custom", value: "none", description: "Implement your own DataProvider" }
8336
+ ],
8337
+ initial: 0
8338
+ });
8339
+ }
8340
+ if (parsed.authProvider === undefined) {
8341
+ questions.push({
8342
+ type: "select",
8343
+ name: "authProvider",
8344
+ message: "Auth Provider:",
8345
+ choices: [
8346
+ { title: "Mock (Demo)", value: "mock", description: "Built-in mock for development" },
8347
+ { title: "Simple REST JWT", value: "jwt", description: "JWT-based auth via REST API" },
8348
+ { title: "Supabase Auth", value: "supabase", description: "Supabase authentication" },
8349
+ { title: "None", value: "none", description: "No authentication" }
8350
+ ],
8351
+ initial: 0
8352
+ });
8353
+ }
8354
+ }
8355
+ if (parsed.installDependencies === undefined) {
8356
+ questions.push({
7382
8357
  type: "confirm",
7383
8358
  name: "installDeps",
7384
8359
  message: "Install dependencies now?",
7385
8360
  initial: true
7386
- }
7387
- ]);
7388
- if (!response.projectName) {
7389
- console.log(import_picocolors3.default.red(`
8361
+ });
8362
+ }
8363
+ const answers = questions.length > 0 ? await import_prompts2.default(questions) : {};
8364
+ const resolvedDataProvider = parsed.dataProvider ?? presetSelections?.dataProvider ?? answers.dataProvider;
8365
+ const resolvedAuthProvider = parsed.authProvider ?? presetSelections?.authProvider ?? answers.authProvider;
8366
+ const projectName = parsed.projectName ?? answers.projectName;
8367
+ if (!projectName || resolvedDataProvider === undefined || resolvedAuthProvider === undefined) {
8368
+ console.log(import_picocolors4.default.red(`
7390
8369
  Operation cancelled.
7391
8370
  `));
7392
8371
  return;
7393
8372
  }
7394
- const projectDir = path4.resolve(process.cwd(), response.projectName.trim());
7395
- if (!fs4.existsSync(projectDir)) {
7396
- fs4.mkdirSync(projectDir, { recursive: true });
8373
+ const response = {
8374
+ projectName,
8375
+ dataProvider: resolvedDataProvider,
8376
+ authProvider: resolvedAuthProvider,
8377
+ installDeps: parsed.installDependencies ?? answers.installDeps ?? true
8378
+ };
8379
+ const projectDir = path5.resolve(process.cwd(), response.projectName.trim());
8380
+ if (!fs5.existsSync(projectDir)) {
8381
+ fs5.mkdirSync(projectDir, { recursive: true });
7397
8382
  }
7398
8383
  console.log(`
7399
- ${import_picocolors3.default.bold("Scaffolding")} project in ${import_picocolors3.default.green(projectDir)}...
8384
+ ${import_picocolors4.default.bold("Scaffolding")} project in ${import_picocolors4.default.green(projectDir)}...
7400
8385
  `);
7401
- const templateDir = path4.join(__dirname2, "..", "template");
7402
- const guidanceDir = path4.join(__dirname2, "..", "guidance");
8386
+ const templateDir = path5.join(__dirname2, "..", "template");
8387
+ const guidanceDir = path5.join(__dirname2, "..", "guidance");
7403
8388
  const scaffoldManifest = loadShippedScaffoldManifest();
7404
8389
  function copyDir(src, dest) {
7405
- fs4.mkdirSync(dest, { recursive: true });
7406
- const entries = fs4.readdirSync(src, { withFileTypes: true });
8390
+ fs5.mkdirSync(dest, { recursive: true });
8391
+ const entries = fs5.readdirSync(src, { withFileTypes: true });
7407
8392
  for (const entry of entries) {
7408
- const srcPath = path4.join(src, entry.name);
7409
- const destPath = path4.join(dest, entry.name === "_gitignore" ? ".gitignore" : entry.name);
8393
+ const srcPath = path5.join(src, entry.name);
8394
+ const destPath = path5.join(dest, entry.name === "_gitignore" ? ".gitignore" : entry.name);
7410
8395
  if (entry.isDirectory()) {
7411
8396
  copyDir(srcPath, destPath);
7412
8397
  } else {
7413
- fs4.copyFileSync(srcPath, destPath);
8398
+ fs5.copyFileSync(srcPath, destPath);
7414
8399
  }
7415
8400
  }
7416
8401
  }
7417
- if (fs4.existsSync(templateDir)) {
8402
+ if (fs5.existsSync(templateDir)) {
7418
8403
  copyDir(templateDir, projectDir);
7419
- console.log(import_picocolors3.default.green(" ✔") + " Template files copied");
8404
+ console.log(import_picocolors4.default.green(" ✔") + " Template files copied");
7420
8405
  }
7421
- if (fs4.existsSync(guidanceDir)) {
8406
+ if (fs5.existsSync(guidanceDir)) {
7422
8407
  copyDir(guidanceDir, projectDir);
7423
- console.log(import_picocolors3.default.green(" ✔") + " AI and design guidance copied");
8408
+ console.log(import_picocolors4.default.green(" ✔") + " AI and design guidance copied");
7424
8409
  }
8410
+ const platformFiles = buildScaffoldPlatformFiles({
8411
+ projectName: response.projectName.trim(),
8412
+ dataProvider: response.dataProvider,
8413
+ authProvider: response.authProvider,
8414
+ scaffoldVersion: shippedCliVersion(),
8415
+ ...scaffoldManifest.dependencies["@svadmin/core"] === undefined ? {} : { coreVersionRange: scaffoldManifest.dependencies["@svadmin/core"] }
8416
+ });
8417
+ for (const file of [platformFiles.config, platformFiles.aiManifest, platformFiles.schema]) {
8418
+ const target = path5.join(projectDir, file.path);
8419
+ fs5.mkdirSync(path5.dirname(target), { recursive: true });
8420
+ fs5.writeFileSync(target, file.content);
8421
+ }
8422
+ console.log(import_picocolors4.default.green(" ✔") + " svadmin.config.ts, svadmin.ai.json and svadmin.schema.json generated");
7425
8423
  const packageJson = createProjectPackageJson(scaffoldManifest, {
7426
8424
  projectName: response.projectName,
7427
8425
  dataProvider: response.dataProvider,
7428
8426
  authProvider: response.authProvider
7429
8427
  });
7430
- fs4.writeFileSync(path4.join(projectDir, "package.json"), `${JSON.stringify(packageJson, null, 2)}
8428
+ fs5.writeFileSync(path5.join(projectDir, "package.json"), `${JSON.stringify(packageJson, null, 2)}
7431
8429
  `);
7432
- console.log(import_picocolors3.default.green(" ✔") + " package.json generated");
7433
- fs4.writeFileSync(path4.join(projectDir, ".gitignore"), `node_modules
8430
+ console.log(import_picocolors4.default.green(" ✔") + " package.json generated");
8431
+ fs5.writeFileSync(path5.join(projectDir, ".gitignore"), `node_modules
7434
8432
  dist
7435
8433
  .svelte-kit
7436
8434
  .env
7437
8435
  .env.local
7438
8436
  *.local
7439
8437
  `);
7440
- console.log(import_picocolors3.default.green(" ✔") + " .gitignore generated");
8438
+ console.log(import_picocolors4.default.green(" ✔") + " .gitignore generated");
7441
8439
  const dpLabel = response.dataProvider === "simple-rest" ? "Simple REST" : response.dataProvider === "supabase" ? "Supabase" : response.dataProvider === "graphql" ? "GraphQL" : "Custom";
7442
8440
  const authLabel = response.authProvider === "mock" ? "Mock (demo)" : response.authProvider === "jwt" ? "JWT" : response.authProvider === "supabase" ? "Supabase Auth" : "None";
7443
- fs4.writeFileSync(path4.join(projectDir, "README.md"), `# ${response.projectName}
8441
+ fs5.writeFileSync(path5.join(projectDir, "README.md"), `# ${response.projectName}
7444
8442
 
7445
8443
  Built with [svadmin](https://github.com/vibeunion/svadmin) — Headless Admin Framework for Svelte 5.
7446
8444
 
@@ -7458,30 +8456,30 @@ bun run dev
7458
8456
  - **Auth**: ${authLabel}
7459
8457
  - **State**: TanStack Query v6
7460
8458
  `);
7461
- console.log(import_picocolors3.default.green(" ✔") + " README.md generated");
8459
+ console.log(import_picocolors4.default.green(" ✔") + " README.md generated");
7462
8460
  if (response.installDeps) {
7463
8461
  console.log(`
7464
- ${import_picocolors3.default.bold("Installing dependencies...")}
8462
+ ${import_picocolors4.default.bold("Installing dependencies...")}
7465
8463
  `);
7466
8464
  const bunInstall = spawnSync("bun", ["install"], { cwd: projectDir, stdio: "inherit" });
7467
8465
  if (bunInstall.status !== 0) {
7468
8466
  const npmInstall = spawnSync("npm", ["install"], { cwd: projectDir, stdio: "inherit" });
7469
8467
  if (npmInstall.status !== 0) {
7470
- console.log(import_picocolors3.default.yellow("\n ⚠ Auto-install failed. Run `bun install` or `npm install` manually."));
8468
+ console.log(import_picocolors4.default.yellow("\n ⚠ Auto-install failed. Run `bun install` or `npm install` manually."));
7471
8469
  }
7472
8470
  }
7473
8471
  }
7474
8472
  console.log();
7475
- console.log(import_picocolors3.default.green(import_picocolors3.default.bold(" ✔ Project ready!")));
8473
+ console.log(import_picocolors4.default.green(import_picocolors4.default.bold(" ✔ Project ready!")));
7476
8474
  console.log();
7477
8475
  console.log(" Next steps:");
7478
- console.log(` ${import_picocolors3.default.cyan(`cd ${response.projectName}`)}`);
8476
+ console.log(` ${import_picocolors4.default.cyan(`cd ${response.projectName}`)}`);
7479
8477
  if (!response.installDeps) {
7480
- console.log(` ${import_picocolors3.default.cyan("bun install")}`);
8478
+ console.log(` ${import_picocolors4.default.cyan("bun install")}`);
7481
8479
  }
7482
- console.log(` ${import_picocolors3.default.cyan("bun run dev")}`);
8480
+ console.log(` ${import_picocolors4.default.cyan("bun run dev")}`);
7483
8481
  console.log();
7484
- console.log(` Docs: ${import_picocolors3.default.blue("https://github.com/vibeunion/svadmin")}`);
8482
+ console.log(` Docs: ${import_picocolors4.default.blue("https://github.com/vibeunion/svadmin")}`);
7485
8483
  console.log();
7486
8484
  }
7487
8485
  var EJECT_COMPONENTS = [
@@ -7510,64 +8508,64 @@ var EJECT_COMPONENTS = [
7510
8508
  ];
7511
8509
  async function eject(args) {
7512
8510
  console.log();
7513
- console.log(import_picocolors3.default.cyan(" svadmin eject") + import_picocolors3.default.dim(" — copy internal components for deep customization"));
8511
+ console.log(import_picocolors4.default.cyan(" svadmin eject") + import_picocolors4.default.dim(" — copy internal components for deep customization"));
7514
8512
  console.log();
7515
8513
  const requested = args.filter((a) => !a.startsWith("-"));
7516
8514
  const toEject = requested.length > 0 ? requested.filter((name) => {
7517
8515
  if (!EJECT_COMPONENTS.includes(name)) {
7518
- console.log(import_picocolors3.default.yellow(` ⚠ Unknown component: ${name} (skipped)`));
8516
+ console.log(import_picocolors4.default.yellow(` ⚠ Unknown component: ${name} (skipped)`));
7519
8517
  return false;
7520
8518
  }
7521
8519
  return true;
7522
8520
  }) : [...EJECT_COMPONENTS];
7523
8521
  if (toEject.length === 0) {
7524
- console.log(import_picocolors3.default.red(" No valid components to eject."));
8522
+ console.log(import_picocolors4.default.red(" No valid components to eject."));
7525
8523
  console.log(` Available: ${EJECT_COMPONENTS.join(", ")}`);
7526
8524
  return;
7527
8525
  }
7528
8526
  let uiSrcDir;
7529
8527
  try {
7530
8528
  const require2 = createRequire2(import.meta.url);
7531
- const uiPkg = path4.dirname(require2.resolve("@svadmin/ui/package.json"));
7532
- uiSrcDir = path4.join(uiPkg, "src", "components");
8529
+ const uiPkg = path5.dirname(require2.resolve("@svadmin/ui/package.json"));
8530
+ uiSrcDir = path5.join(uiPkg, "src", "components");
7533
8531
  } catch {
7534
- const nm = path4.join(process.cwd(), "node_modules", "@svadmin", "ui", "src", "components");
7535
- if (fs4.existsSync(nm)) {
8532
+ const nm = path5.join(process.cwd(), "node_modules", "@svadmin", "ui", "src", "components");
8533
+ if (fs5.existsSync(nm)) {
7536
8534
  uiSrcDir = nm;
7537
8535
  } else {
7538
- console.log(import_picocolors3.default.red(" ✗ Cannot find @svadmin/ui. Run `bun install` first."));
8536
+ console.log(import_picocolors4.default.red(" ✗ Cannot find @svadmin/ui. Run `bun install` first."));
7539
8537
  return;
7540
8538
  }
7541
8539
  }
7542
- const destDir = path4.join(process.cwd(), "src", "components", "svadmin");
7543
- fs4.mkdirSync(destDir, { recursive: true });
8540
+ const destDir = path5.join(process.cwd(), "src", "components", "svadmin");
8541
+ fs5.mkdirSync(destDir, { recursive: true });
7544
8542
  let copied = 0;
7545
8543
  for (const name of toEject) {
7546
- const srcFile = path4.join(uiSrcDir, `${name}.svelte`);
7547
- const srcFileAlt = path4.join(uiSrcDir, "fields", `${name}.svelte`);
7548
- const src = fs4.existsSync(srcFile) ? srcFile : fs4.existsSync(srcFileAlt) ? srcFileAlt : null;
8544
+ const srcFile = path5.join(uiSrcDir, `${name}.svelte`);
8545
+ const srcFileAlt = path5.join(uiSrcDir, "fields", `${name}.svelte`);
8546
+ const src = fs5.existsSync(srcFile) ? srcFile : fs5.existsSync(srcFileAlt) ? srcFileAlt : null;
7549
8547
  if (!src) {
7550
- console.log(import_picocolors3.default.yellow(` ⚠ ${name}.svelte not found in @svadmin/ui (skipped)`));
8548
+ console.log(import_picocolors4.default.yellow(` ⚠ ${name}.svelte not found in @svadmin/ui (skipped)`));
7551
8549
  continue;
7552
8550
  }
7553
- let content = fs4.readFileSync(src, "utf-8");
8551
+ let content = fs5.readFileSync(src, "utf-8");
7554
8552
  content = content.replace(/from\s+['"]\.\/ui\//g, "from '@svadmin/ui/components/ui/");
7555
8553
  content = content.replace(/from\s+['"]\.\/((?!ui\/)[^'"]+)['"]/g, "from './$1'");
7556
- const destFile = path4.join(destDir, `${name}.svelte`);
7557
- fs4.writeFileSync(destFile, content);
7558
- console.log(import_picocolors3.default.green(" ✔") + ` ${name}.svelte → src/components/svadmin/`);
8554
+ const destFile = path5.join(destDir, `${name}.svelte`);
8555
+ fs5.writeFileSync(destFile, content);
8556
+ console.log(import_picocolors4.default.green(" ✔") + ` ${name}.svelte → src/components/svadmin/`);
7559
8557
  copied++;
7560
8558
  }
7561
8559
  console.log();
7562
8560
  if (copied > 0) {
7563
- console.log(import_picocolors3.default.green(import_picocolors3.default.bold(` ✔ Ejected ${copied} component(s)`)));
8561
+ console.log(import_picocolors4.default.green(import_picocolors4.default.bold(` ✔ Ejected ${copied} component(s)`)));
7564
8562
  console.log();
7565
8563
  console.log(" Usage: import overrides in your AdminApp and pass via `components` prop:");
7566
8564
  console.log();
7567
- console.log(import_picocolors3.default.dim(' import CustomLayout from "./components/svadmin/Layout.svelte";'));
7568
- console.log(import_picocolors3.default.dim(" <AdminApp components={{ Layout: CustomLayout }} ... />"));
8565
+ console.log(import_picocolors4.default.dim(' import CustomLayout from "./components/svadmin/Layout.svelte";'));
8566
+ console.log(import_picocolors4.default.dim(" <AdminApp components={{ Layout: CustomLayout }} ... />"));
7569
8567
  } else {
7570
- console.log(import_picocolors3.default.yellow(" No components were ejected."));
8568
+ console.log(import_picocolors4.default.yellow(" No components were ejected."));
7571
8569
  }
7572
8570
  console.log();
7573
8571
  }
@@ -7575,7 +8573,7 @@ var [, , subcommand, ...rest] = process.argv;
7575
8573
  var runCommand = (command) => {
7576
8574
  Promise.resolve().then(command).catch((error) => {
7577
8575
  const message = error instanceof Error ? error.message : String(error);
7578
- console.error(import_picocolors3.default.red(`
8576
+ console.error(import_picocolors4.default.red(`
7579
8577
  ✗ ${message}
7580
8578
  `));
7581
8579
  process.exitCode = 2;
@@ -7587,10 +8585,14 @@ if (subcommand === "eject") {
7587
8585
  runCommand(() => doctor(rest));
7588
8586
  } else if (subcommand === "upgrade") {
7589
8587
  runCommand(() => upgrade(rest));
8588
+ } else if (subcommand === "migrate") {
8589
+ runCommand(() => upgrade(rest));
7590
8590
  } else if (subcommand === "guidance") {
7591
8591
  runCommand(() => guidance(rest));
7592
8592
  } else if (subcommand === "infer") {
7593
8593
  runCommand(() => inferCommand(rest));
8594
+ } else if (subcommand === "add") {
8595
+ runCommand(() => addCommand(rest, loadShippedScaffoldManifest()));
7594
8596
  } else if (subcommand === "generate" || subcommand === "gen") {
7595
8597
  runCommand(() => generateCommand(rest));
7596
8598
  } else if (subcommand === "lite") {
@@ -7601,6 +8603,8 @@ if (subcommand === "eject") {
7601
8603
  } else {
7602
8604
  runCommand(() => liteInitCommand(rest.slice(1)));
7603
8605
  }
8606
+ } else if (subcommand === "init") {
8607
+ runCommand(() => init(rest));
7604
8608
  } else {
7605
- runCommand(init);
8609
+ runCommand(() => init(subcommand === undefined ? rest : [subcommand, ...rest]));
7606
8610
  }