gigadrive 2.4.4 → 2.5.1

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.md CHANGED
@@ -1 +1,23 @@
1
- # @gigadrive/network-cli
1
+ # Gigadrive CLI
2
+
3
+ Deploy a supported framework from its project directory without a Gigadrive
4
+ configuration file:
5
+
6
+ ```bash
7
+ pnpm dlx gigadrive login
8
+ pnpm dlx gigadrive deploy
9
+ ```
10
+
11
+ For an unlinked project, `deploy` selects the authenticated user's organization,
12
+ creates a Network application, saves the local `.gigadrive/project.json` link,
13
+ auto-detects the framework, and deploys it. Use `--org` when the user belongs to
14
+ multiple organizations and a non-interactive deployment must select one.
15
+
16
+ Applications can also be created independently:
17
+
18
+ ```bash
19
+ pnpm dlx gigadrive apps create --org <organization-id> --name <application-name>
20
+ ```
21
+
22
+ The legacy `gigadrive platform deploy` command remains available as an alias for
23
+ `gigadrive deploy`.
package/dist/index.cjs CHANGED
@@ -32,7 +32,7 @@ var import_effect29 = require("effect");
32
32
  // package.json
33
33
  var package_default = {
34
34
  name: "gigadrive",
35
- version: "2.4.4",
35
+ version: "2.5.1",
36
36
  repository: {
37
37
  type: "git",
38
38
  url: "https://github.com/Gigadrive/sdk.git",
@@ -177,6 +177,13 @@ var ApplicationNotFoundError = class extends import_effect.Schema.TaggedError()(
177
177
  }
178
178
  ) {
179
179
  };
180
+ var NoOrganizationsFoundError = class extends import_effect.Schema.TaggedError()(
181
+ "NoOrganizationsFoundError",
182
+ {
183
+ message: import_effect.Schema.String
184
+ }
185
+ ) {
186
+ };
180
187
  var EnvFileReadError = class extends import_effect.Schema.TaggedError()("EnvFileReadError", {
181
188
  message: import_effect.Schema.String,
182
189
  cause: import_effect.Schema.optional(import_effect.Schema.String)
@@ -513,8 +520,11 @@ var CLI_SCOPES = [
513
520
  "openid",
514
521
  "profile",
515
522
  "email",
523
+ // Platform discovery used for zero-config application onboarding
524
+ "platform:organizations:read",
516
525
  // Network API capabilities
517
526
  "network:applications:read",
527
+ "network:applications:write",
518
528
  "network:env_vars:read",
519
529
  "network:env_vars:write",
520
530
  "network:env_vars:delete",
@@ -523,11 +533,6 @@ var CLI_SCOPES = [
523
533
  "network:deployments:trigger",
524
534
  "network:ai_gateway:chat",
525
535
  "network:ai_gateway:models",
526
- "network:ai_gateway:usage:read",
527
- "network:ai_gateway:budgets:read",
528
- "network:ai_gateway:budgets:write",
529
- "network:ai_gateway:policies:read",
530
- "network:ai_gateway:policies:write",
531
536
  // Provisioning local-dev API credentials
532
537
  "platform:api_keys:read",
533
538
  "platform:api_keys:write",
@@ -1106,13 +1111,13 @@ var readStdin = import_effect8.Effect.async((resume) => {
1106
1111
  stdin.resume();
1107
1112
  });
1108
1113
  var readJsonInput = (file) => import_effect8.Effect.gen(function* () {
1109
- const path = import_effect8.Option.getOrUndefined(file);
1114
+ const path2 = import_effect8.Option.getOrUndefined(file);
1110
1115
  let raw;
1111
- if (path === void 0 || path === "-") {
1116
+ if (path2 === void 0 || path2 === "-") {
1112
1117
  raw = yield* readStdin;
1113
1118
  } else {
1114
1119
  const fs = yield* import_platform3.FileSystem.FileSystem;
1115
- raw = yield* fs.readFileString(path, "utf8").pipe(import_effect8.Effect.mapError((e) => new ApiRequestError({ message: `Failed to read ${path}: ${String(e)}` })));
1120
+ raw = yield* fs.readFileString(path2, "utf8").pipe(import_effect8.Effect.mapError((e) => new ApiRequestError({ message: `Failed to read ${path2}: ${String(e)}` })));
1116
1121
  }
1117
1122
  return yield* import_effect8.Effect.try({
1118
1123
  try: () => JSON.parse(raw),
@@ -1332,14 +1337,30 @@ var aiCommand = aiBase.pipe(
1332
1337
  // src/commands/apps/index.ts
1333
1338
  var import_cli2 = require("@effect/cli");
1334
1339
  var import_effect9 = require("effect");
1335
- var orgOption2 = import_cli2.Options.text("org").pipe(
1340
+ var listOrgOption = import_cli2.Options.text("org").pipe(
1336
1341
  import_cli2.Options.withAlias("o"),
1337
1342
  import_cli2.Options.withDescription("Only list applications belonging to this organization ID"),
1338
1343
  import_cli2.Options.optional
1339
1344
  );
1345
+ var createOrgOption = import_cli2.Options.text("org").pipe(
1346
+ import_cli2.Options.withAlias("o"),
1347
+ import_cli2.Options.withDescription("Organization ID that will own the application")
1348
+ );
1349
+ var nameOption = import_cli2.Options.text("name").pipe(
1350
+ import_cli2.Options.withAlias("n"),
1351
+ import_cli2.Options.withDescription("Application display name")
1352
+ );
1353
+ var slugOption = import_cli2.Options.text("slug").pipe(
1354
+ import_cli2.Options.withDescription("Optional lowercase application slug"),
1355
+ import_cli2.Options.optional
1356
+ );
1357
+ var rootDirectoryOption = import_cli2.Options.text("root-directory").pipe(
1358
+ import_cli2.Options.withDescription("Optional project directory relative to the repository root"),
1359
+ import_cli2.Options.optional
1360
+ );
1340
1361
  var appsListCommand = import_cli2.Command.make(
1341
1362
  "list",
1342
- { org: orgOption2 },
1363
+ { org: listOrgOption },
1343
1364
  ({ org }) => import_effect9.Effect.gen(function* () {
1344
1365
  const apiClient = yield* ApiClientService;
1345
1366
  const organizationId = import_effect9.Option.getOrUndefined(org);
@@ -1362,8 +1383,35 @@ ${total} application(s).`);
1362
1383
  })
1363
1384
  )
1364
1385
  );
1386
+ var appsCreateCommand = import_cli2.Command.make(
1387
+ "create",
1388
+ { org: createOrgOption, name: nameOption, slug: slugOption, rootDirectory: rootDirectoryOption },
1389
+ ({ org, name, slug, rootDirectory }) => import_effect9.Effect.gen(function* () {
1390
+ const apiClient = yield* ApiClientService;
1391
+ const application = yield* apiClient.request(
1392
+ (client) => client.applications.create({
1393
+ organizationId: org,
1394
+ name,
1395
+ ...import_effect9.Option.match(slug, { onNone: () => ({}), onSome: (value) => ({ slug: value }) }),
1396
+ ...import_effect9.Option.match(rootDirectory, {
1397
+ onNone: () => ({}),
1398
+ onSome: (value) => ({ rootDirectory: value })
1399
+ })
1400
+ })
1401
+ );
1402
+ yield* import_effect9.Console.log(`Created application ${application.name} (${application.id}).`);
1403
+ yield* import_effect9.Console.log(`Run "gigadrive link --app ${application.id}" to link the current directory.`);
1404
+ }).pipe(
1405
+ import_effect9.Effect.catchTags({
1406
+ NotAuthenticatedError: (err) => import_effect9.Console.error('You are not logged in. Run "gigadrive login" to authenticate.').pipe(
1407
+ import_effect9.Effect.andThen(import_effect9.Effect.fail(err))
1408
+ ),
1409
+ ApiRequestError: (err) => import_effect9.Console.error(`Failed to create application: ${err.message}`).pipe(import_effect9.Effect.andThen(import_effect9.Effect.fail(err)))
1410
+ })
1411
+ )
1412
+ );
1365
1413
  var appsBase = import_cli2.Command.make("apps", {}, () => import_effect9.Effect.void);
1366
- var appsCommand = appsBase.pipe(import_cli2.Command.withSubcommands([appsListCommand]));
1414
+ var appsCommand = appsBase.pipe(import_cli2.Command.withSubcommands([appsListCommand, appsCreateCommand]));
1367
1415
 
1368
1416
  // src/commands/build/index.ts
1369
1417
  var import_cli3 = require("@effect/cli");
@@ -1651,7 +1699,7 @@ var appOption2 = import_cli6.Options.text("app").pipe(
1651
1699
  import_cli6.Options.withDescription("Filter by application ID (defaults to the linked application)"),
1652
1700
  import_cli6.Options.optional
1653
1701
  );
1654
- var orgOption3 = import_cli6.Options.text("org").pipe(
1702
+ var orgOption2 = import_cli6.Options.text("org").pipe(
1655
1703
  import_cli6.Options.withAlias("o"),
1656
1704
  import_cli6.Options.withDescription("Filter by organization ID"),
1657
1705
  import_cli6.Options.optional
@@ -1671,7 +1719,7 @@ var resolveApplicationFilter = (app) => import_effect15.Option.match(app, {
1671
1719
  });
1672
1720
  var deploymentsListCommand = import_cli6.Command.make(
1673
1721
  "list",
1674
- { app: appOption2, org: orgOption3, status: statusOption },
1722
+ { app: appOption2, org: orgOption2, status: statusOption },
1675
1723
  ({ app, org, status }) => import_effect15.Effect.gen(function* () {
1676
1724
  const apiClient = yield* ApiClientService;
1677
1725
  const applicationId = yield* resolveApplicationFilter(app);
@@ -1965,7 +2013,7 @@ var appOption3 = import_cli7.Options.text("app").pipe(
1965
2013
  import_cli7.Options.withDescription("Operate on this application (overrides the linked application)"),
1966
2014
  import_cli7.Options.optional
1967
2015
  );
1968
- var orgOption4 = import_cli7.Options.text("org").pipe(
2016
+ var orgOption3 = import_cli7.Options.text("org").pipe(
1969
2017
  import_cli7.Options.withAlias("o"),
1970
2018
  import_cli7.Options.withDescription("Operate on this organization instead of an application"),
1971
2019
  import_cli7.Options.optional
@@ -2014,7 +2062,7 @@ var resolveScope = (app, org) => import_effect19.Effect.gen(function* () {
2014
2062
  });
2015
2063
  var envListCommand = import_cli7.Command.make(
2016
2064
  "list",
2017
- { app: appOption3, org: orgOption4 },
2065
+ { app: appOption3, org: orgOption3 },
2018
2066
  ({ app, org }) => import_effect19.Effect.gen(function* () {
2019
2067
  const apiClient = yield* ApiClientService;
2020
2068
  const scope = yield* resolveScope(app, org);
@@ -2041,7 +2089,7 @@ var envListCommand = import_cli7.Command.make(
2041
2089
  );
2042
2090
  var envSetCommand = import_cli7.Command.make(
2043
2091
  "set",
2044
- { keyValue: keyValueArg, app: appOption3, org: orgOption4, sensitive: sensitiveOption, env: envIdOption },
2092
+ { keyValue: keyValueArg, app: appOption3, org: orgOption3, sensitive: sensitiveOption, env: envIdOption },
2045
2093
  ({ keyValue, app, org, sensitive, env }) => import_effect19.Effect.gen(function* () {
2046
2094
  const separator = keyValue.indexOf("=");
2047
2095
  if (separator <= 0) {
@@ -2074,7 +2122,7 @@ var envSetCommand = import_cli7.Command.make(
2074
2122
  );
2075
2123
  var envRmCommand = import_cli7.Command.make(
2076
2124
  "rm",
2077
- { keyOrId: keyOrIdArg, app: appOption3, org: orgOption4 },
2125
+ { keyOrId: keyOrIdArg, app: appOption3, org: orgOption3 },
2078
2126
  ({ keyOrId, app, org }) => import_effect19.Effect.gen(function* () {
2079
2127
  const apiClient = yield* ApiClientService;
2080
2128
  const scope = yield* resolveScope(app, org);
@@ -2188,14 +2236,14 @@ var appOption4 = import_cli8.Options.text("app").pipe(
2188
2236
  import_cli8.Options.withDescription("Application ID to link (skips the interactive picker)"),
2189
2237
  import_cli8.Options.optional
2190
2238
  );
2191
- var orgOption5 = import_cli8.Options.text("org").pipe(
2239
+ var orgOption4 = import_cli8.Options.text("org").pipe(
2192
2240
  import_cli8.Options.withAlias("o"),
2193
2241
  import_cli8.Options.withDescription("Only list applications belonging to this organization ID"),
2194
2242
  import_cli8.Options.optional
2195
2243
  );
2196
2244
  var linkCommand = import_cli8.Command.make(
2197
2245
  "link",
2198
- { app: appOption4, org: orgOption5 },
2246
+ { app: appOption4, org: orgOption4 },
2199
2247
  ({ app, org }) => import_effect20.Effect.gen(function* () {
2200
2248
  const apiClient = yield* ApiClientService;
2201
2249
  const projectLink = yield* ProjectLinkService;
@@ -2320,6 +2368,7 @@ var import_platform9 = require("@effect/platform");
2320
2368
  var import_commons = require("@gigadrive/commons");
2321
2369
  var import_effect25 = require("effect");
2322
2370
  var os4 = __toESM(require("os"), 1);
2371
+ var path = __toESM(require("path"), 1);
2323
2372
 
2324
2373
  // src/services/archive.ts
2325
2374
  var import_platform8 = require("@effect/platform");
@@ -2329,7 +2378,15 @@ var import_effect23 = require("effect");
2329
2378
  var import_ignore = __toESM(require("ignore"), 1);
2330
2379
  var nodeFs = __toESM(require("fs"), 1);
2331
2380
  var nodeFsPromises = __toESM(require("fs/promises"), 1);
2332
- var IGNORE_FILE_NAMES = [".gigadriveignore", ".vercelignore", ".dockerignore", ".nowignore"];
2381
+ var IGNORE_FILE_NAMES = [".gitignore", ".dockerignore", ".nowignore", ".vercelignore", ".gigadriveignore"];
2382
+ var MANAGED_IGNORE_PATTERNS = [
2383
+ ".git/",
2384
+ "**/.git/",
2385
+ "node_modules/",
2386
+ "**/node_modules/",
2387
+ "**/.DS_Store",
2388
+ "**/Thumbs.db"
2389
+ ];
2333
2390
  var readIgnoreFile = (fs, ignorePath) => fs.readFileString(ignorePath, "utf8").pipe(
2334
2391
  import_effect23.Effect.map((content) => content.split("\n").filter((line) => line.trim() !== "")),
2335
2392
  import_effect23.Effect.catchAll(() => import_effect23.Effect.succeed([]))
@@ -2360,19 +2417,23 @@ var collectIgnorePatterns = (fs, pathService, dir, baseDir, ignoreRules) => impo
2360
2417
  }
2361
2418
  }
2362
2419
  }).pipe(import_effect23.Effect.catchAll(() => import_effect23.Effect.void));
2363
- var initializeIgnoreRules = (fs, pathService, baseDir) => import_effect23.Effect.gen(function* () {
2420
+ var initializeIgnoreRules = (fs, pathService, baseDir, useIgnoreFiles, useManagedIgnore) => import_effect23.Effect.gen(function* () {
2364
2421
  const ignoreRules = (0, import_ignore.default)();
2365
- ignoreRules.add([".git/", "**/.DS_Store", "**/Thumbs.db"]);
2366
- for (const ignoreFileName of IGNORE_FILE_NAMES) {
2367
- const ignoreFilePath = pathService.join(baseDir, ignoreFileName);
2368
- const patterns = yield* readIgnoreFile(fs, ignoreFilePath);
2369
- if (patterns.length > 0) {
2370
- ignoreRules.add(
2371
- patterns.map((pattern) => pattern.startsWith("!") ? `!${pattern.slice(1)}` : pattern)
2372
- );
2422
+ if (useManagedIgnore) {
2423
+ ignoreRules.add(MANAGED_IGNORE_PATTERNS);
2424
+ }
2425
+ if (useIgnoreFiles) {
2426
+ for (const ignoreFileName of IGNORE_FILE_NAMES) {
2427
+ const ignoreFilePath = pathService.join(baseDir, ignoreFileName);
2428
+ const patterns = yield* readIgnoreFile(fs, ignoreFilePath);
2429
+ if (patterns.length > 0) {
2430
+ ignoreRules.add(
2431
+ patterns.map((pattern) => pattern.startsWith("!") ? `!${pattern.slice(1)}` : pattern)
2432
+ );
2433
+ }
2373
2434
  }
2435
+ yield* collectIgnorePatterns(fs, pathService, baseDir, baseDir, ignoreRules);
2374
2436
  }
2375
- yield* collectIgnorePatterns(fs, pathService, baseDir, baseDir, ignoreRules);
2376
2437
  return ignoreRules;
2377
2438
  });
2378
2439
  var getFilesToInclude = (fs, pathService, dir, ignoreRules) => import_effect23.Effect.gen(function* () {
@@ -2409,7 +2470,13 @@ var ArchiveService = class extends import_effect23.Effect.Service()("ArchiveServ
2409
2470
  yield* import_effect23.Effect.annotateCurrentSpan("inputDir", inputDir);
2410
2471
  yield* import_effect23.Effect.annotateCurrentSpan("outputFile", outputFile);
2411
2472
  yield* import_effect23.Effect.log("Creating zip archive", { inputDir, outputFile });
2412
- const ignoreRules = options.useIgnoreFiles !== false ? yield* initializeIgnoreRules(fs, pathService, inputDir) : (0, import_ignore.default)();
2473
+ const ignoreRules = yield* initializeIgnoreRules(
2474
+ fs,
2475
+ pathService,
2476
+ inputDir,
2477
+ options.useIgnoreFiles !== false,
2478
+ options.useManagedIgnore !== false
2479
+ );
2413
2480
  const filesToInclude = options.whitelist ? yield* import_effect23.Effect.tryPromise({
2414
2481
  try: () => Promise.all(
2415
2482
  options.whitelist.map((file) => (0, import_build_utils3.getFilesForPattern)(file, inputDir, options.excludeFiles ?? []))
@@ -2590,22 +2657,83 @@ var appOption5 = import_cli11.Options.text("app").pipe(
2590
2657
  import_cli11.Options.withDescription("Application ID to deploy to (overrides the linked application)"),
2591
2658
  import_cli11.Options.optional
2592
2659
  );
2660
+ var orgOption5 = import_cli11.Options.text("org").pipe(
2661
+ import_cli11.Options.withAlias("o"),
2662
+ import_cli11.Options.withDescription("Organization ID to use when automatically creating an application"),
2663
+ import_cli11.Options.optional
2664
+ );
2665
+ var nameOption2 = import_cli11.Options.text("name").pipe(
2666
+ import_cli11.Options.withAlias("n"),
2667
+ import_cli11.Options.withDescription("Application name to use when automatically creating an application"),
2668
+ import_cli11.Options.optional
2669
+ );
2670
+ var createAndLinkDeploymentApplication = (input) => import_effect25.Effect.gen(function* () {
2671
+ const projectLink = yield* ProjectLinkService;
2672
+ const apiClient = yield* ApiClientService;
2673
+ const { items: organizations } = yield* apiClient.request((client) => client.organizations.list());
2674
+ const availableOrganizations = import_effect25.Option.match(input.org, {
2675
+ onNone: () => organizations,
2676
+ onSome: (organizationId) => organizations.filter((organization2) => organization2.id === organizationId)
2677
+ });
2678
+ if (availableOrganizations.length === 0) {
2679
+ return yield* new NoOrganizationsFoundError({
2680
+ message: import_effect25.Option.match(input.org, {
2681
+ onNone: () => 'No organization is available for this deployment. Create an organization, then run "gigadrive deploy" again.',
2682
+ onSome: (organizationId) => `Organization "${organizationId}" was not found among your organizations.`
2683
+ })
2684
+ });
2685
+ }
2686
+ const organization = availableOrganizations.length === 1 ? availableOrganizations[0] : yield* import_cli11.Prompt.run(
2687
+ import_cli11.Prompt.select({
2688
+ message: "Select an organization for this application",
2689
+ choices: availableOrganizations.map((candidate) => ({
2690
+ title: candidate.name,
2691
+ value: candidate
2692
+ }))
2693
+ })
2694
+ );
2695
+ const inferredName = path.basename(input.cwd) || "Application";
2696
+ const applicationName = import_effect25.Option.match(input.name, {
2697
+ onNone: () => inferredName,
2698
+ onSome: (name) => name
2699
+ }).trim();
2700
+ const application = yield* apiClient.request(
2701
+ (client) => client.applications.create({
2702
+ organizationId: organization.id,
2703
+ name: applicationName || inferredName
2704
+ })
2705
+ );
2706
+ yield* projectLink.save(input.cwd, {
2707
+ applicationId: application.id,
2708
+ organizationId: organization.id
2709
+ });
2710
+ yield* import_effect25.Console.log(`Created and linked application ${application.name} (${application.id}).`);
2711
+ return application.id;
2712
+ });
2713
+ var resolveLinkedDeploymentApplication = (input) => import_effect25.Effect.gen(function* () {
2714
+ const projectLink = yield* ProjectLinkService;
2715
+ const existingLink = yield* projectLink.load(input.cwd);
2716
+ return yield* import_effect25.Option.match(existingLink, {
2717
+ onNone: () => createAndLinkDeploymentApplication(input),
2718
+ onSome: (link) => import_effect25.Effect.succeed(link.applicationId)
2719
+ });
2720
+ });
2721
+ var resolveDeploymentApplication = (input) => import_effect25.Option.match(input.app, {
2722
+ onNone: () => resolveLinkedDeploymentApplication(input),
2723
+ onSome: import_effect25.Effect.succeed
2724
+ });
2593
2725
  var deployCommand = import_cli11.Command.make(
2594
2726
  "deploy",
2595
- { app: appOption5 },
2596
- ({ app }) => import_effect25.Effect.gen(function* () {
2727
+ { app: appOption5, org: orgOption5, name: nameOption2 },
2728
+ ({ app, org, name }) => import_effect25.Effect.gen(function* () {
2597
2729
  const projectConfig = yield* ProjectConfigService;
2598
2730
  const deploymentApi = yield* DeploymentApiService;
2599
2731
  const archiveService = yield* ArchiveService;
2600
- const projectLink = yield* ProjectLinkService;
2601
2732
  const pathService = yield* import_platform9.Path.Path;
2602
2733
  const cwd = process.cwd();
2603
- const applicationId = yield* import_effect25.Option.match(app, {
2604
- onSome: (id) => import_effect25.Effect.succeed(id),
2605
- onNone: () => projectLink.resolve(cwd).pipe(import_effect25.Effect.map((link) => link.applicationId))
2606
- });
2607
2734
  yield* import_effect25.Effect.log("Starting deploy command");
2608
2735
  const { config } = yield* projectConfig.resolve(cwd);
2736
+ const applicationId = yield* resolveDeploymentApplication({ app, org, name, cwd });
2609
2737
  yield* import_effect25.Console.log("Creating deployment...");
2610
2738
  const deploymentId = yield* deploymentApi.createDeployment(applicationId);
2611
2739
  yield* import_effect25.Console.log(`Deployment ID: ${deploymentId}`);
@@ -2613,9 +2741,7 @@ var deployCommand = import_cli11.Command.make(
2613
2741
  const archivePath = pathService.join(os4.tmpdir(), `project-${Date.now()}.zip`);
2614
2742
  const archive = yield* archiveService.createZipArchive(config.userArchive?.rootOverwrite || cwd, archivePath, {
2615
2743
  whitelist: config.userArchive?.fileWhitelist,
2616
- excludeFiles: config.excludeFiles,
2617
- useIgnoreFiles: false,
2618
- useManagedIgnore: false
2744
+ excludeFiles: config.excludeFiles
2619
2745
  });
2620
2746
  yield* import_effect25.Console.log(`Archive created (${(0, import_commons.formatFileSize)(archive.size)})`);
2621
2747
  yield* import_effect25.Console.log("Uploading archive...");
@@ -2625,8 +2751,14 @@ var deployCommand = import_cli11.Command.make(
2625
2751
  yield* pollDeployment(deploymentId);
2626
2752
  }).pipe(
2627
2753
  import_effect25.Effect.catchTags({
2628
- ProjectNotLinkedError: (err) => import_effect25.Console.error(err.message).pipe(import_effect25.Effect.andThen(import_effect25.Effect.fail(err))),
2754
+ QuitException: () => import_effect25.Console.log("Cancelled."),
2755
+ NotAuthenticatedError: (err) => import_effect25.Console.error('You are not logged in. Run "gigadrive login" to authenticate.').pipe(
2756
+ import_effect25.Effect.andThen(import_effect25.Effect.fail(err))
2757
+ ),
2758
+ ApiRequestError: (err) => import_effect25.Console.error(`Application setup failed: ${err.message}`).pipe(import_effect25.Effect.andThen(import_effect25.Effect.fail(err))),
2759
+ NoOrganizationsFoundError: (err) => import_effect25.Console.error(err.message).pipe(import_effect25.Effect.andThen(import_effect25.Effect.fail(err))),
2629
2760
  ProjectLinkReadError: (err) => import_effect25.Console.error(err.message).pipe(import_effect25.Effect.andThen(import_effect25.Effect.fail(err))),
2761
+ ProjectLinkWriteError: (err) => import_effect25.Console.error(err.message).pipe(import_effect25.Effect.andThen(import_effect25.Effect.fail(err))),
2630
2762
  ConfigNotFoundError: (err) => import_effect25.Console.error(err.message).pipe(import_effect25.Effect.andThen(import_effect25.Effect.fail(err))),
2631
2763
  ConfigParseError: (err) => import_effect25.Console.error(`Config parse error: ${err.message}`).pipe(import_effect25.Effect.andThen(import_effect25.Effect.fail(err))),
2632
2764
  ConfigValidationError: (err) => import_effect25.Effect.gen(function* () {
@@ -2917,6 +3049,7 @@ var gigadrive = import_cli15.Command.make("gigadrive", {}, () => import_effect29
2917
3049
  aiCommand,
2918
3050
  buildCommand,
2919
3051
  debugCommand,
3052
+ deployCommand,
2920
3053
  platformCommand,
2921
3054
  setupCommand
2922
3055
  ])