@eide/foir-cli 0.1.28 → 0.1.29

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.
@@ -1 +1 @@
1
- {"version":3,"file":"extensions.d.ts","sourceRoot":"","sources":["../../src/commands/extensions.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACzC,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAC;AActD,wBAAgB,0BAA0B,CACxC,OAAO,EAAE,OAAO,EAChB,UAAU,EAAE,MAAM,aAAa,GAC9B,IAAI,CAkKN"}
1
+ {"version":3,"file":"extensions.d.ts","sourceRoot":"","sources":["../../src/commands/extensions.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACzC,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAC;AAetD,wBAAgB,0BAA0B,CACxC,OAAO,EAAE,OAAO,EAChB,UAAU,EAAE,MAAM,aAAa,GAC9B,IAAI,CAiPN"}
@@ -2,7 +2,7 @@ import { withErrorHandler } from '../lib/errors.js';
2
2
  import { createClient } from '../lib/client.js';
3
3
  import { formatOutput, formatList, success } from '../lib/output.js';
4
4
  import { parseInputData, isUUID } from '../lib/input.js';
5
- import { ListExtensionsDocument, GetExtensionDocument, GetExtensionByKeyDocument, RegisterExtensionDocument, TriggerExtensionSyncDocument, InstallExtensionDocument, } from '../graphql/generated.js';
5
+ import { ListExtensionsDocument, GetExtensionDocument, GetExtensionByKeyDocument, RegisterExtensionDocument, TriggerExtensionSyncDocument, InstallExtensionDocument, UnregisterExtensionDocument, } from '../graphql/generated.js';
6
6
  export function registerExtensionsCommands(program, globalOpts) {
7
7
  const extensions = program
8
8
  .command('extensions')
@@ -80,10 +80,11 @@ export function registerExtensionsCommands(program, globalOpts) {
80
80
  .option('-d, --data <json>', 'Extension manifest as JSON')
81
81
  .option('-f, --file <path>', 'Read manifest from file (.ts, .js, or .json)')
82
82
  .option('-k, --key <key>', 'Extension key (overrides manifest)')
83
+ .option('--force', 'Uninstall existing extension before installing (fresh install)')
83
84
  .addHelpText('after', `
84
85
  Examples:
85
86
  $ foir extensions install -f install.config.ts
86
- $ foir extensions install -f install.json
87
+ $ foir extensions install -f install.json --force
87
88
  $ foir extensions install -d '{"key":"my-ext","name":"My Extension",...}'
88
89
  `)
89
90
  .action(withErrorHandler(globalOpts, async (cmdOpts) => {
@@ -94,6 +95,30 @@ Examples:
94
95
  if (cmdOpts.key) {
95
96
  input.key = cmdOpts.key;
96
97
  }
98
+ const extensionKey = input.key;
99
+ // Handle --force: uninstall first if extension exists
100
+ if (cmdOpts.force) {
101
+ try {
102
+ const existing = await client.request(GetExtensionByKeyDocument, {
103
+ key: extensionKey,
104
+ });
105
+ if (existing.extensionByKey) {
106
+ if (!(opts.json || opts.jsonl || opts.quiet)) {
107
+ console.log(`🗑️ Uninstalling existing extension "${extensionKey}"...`);
108
+ }
109
+ await client.request(UnregisterExtensionDocument, {
110
+ id: existing.extensionByKey.id,
111
+ });
112
+ if (!(opts.json || opts.jsonl || opts.quiet)) {
113
+ success(`Uninstalled extension "${extensionKey}"`);
114
+ console.log('');
115
+ }
116
+ }
117
+ }
118
+ catch (err) {
119
+ // Extension doesn't exist - that's fine, continue with install
120
+ }
121
+ }
97
122
  const data = await client.request(InstallExtensionDocument, { input });
98
123
  const result = data.installExtension;
99
124
  if (opts.json || opts.jsonl || opts.quiet) {
@@ -125,6 +150,52 @@ Examples:
125
150
  }
126
151
  }
127
152
  }));
153
+ // uninstall
154
+ extensions
155
+ .command('uninstall <keyOrId>')
156
+ .description('Uninstall an extension by key or ID')
157
+ .addHelpText('after', `
158
+ Examples:
159
+ $ foir extensions uninstall tilly
160
+ $ foir extensions uninstall c7a3f8b0-1234-5678-90ab-cdef12345678
161
+ `)
162
+ .action(withErrorHandler(globalOpts, async (keyOrId) => {
163
+ const opts = globalOpts();
164
+ const client = await createClient(opts);
165
+ // Resolve key to ID if needed
166
+ let extensionId;
167
+ let extensionKey;
168
+ if (isUUID(keyOrId)) {
169
+ extensionId = keyOrId;
170
+ const data = await client.request(GetExtensionDocument, { id: keyOrId });
171
+ if (!data.extension) {
172
+ throw new Error(`Extension "${keyOrId}" not found.`);
173
+ }
174
+ extensionKey = data.extension.key;
175
+ }
176
+ else {
177
+ const data = await client.request(GetExtensionByKeyDocument, {
178
+ key: keyOrId,
179
+ });
180
+ if (!data.extensionByKey) {
181
+ throw new Error(`Extension "${keyOrId}" not found.`);
182
+ }
183
+ extensionId = data.extensionByKey.id;
184
+ extensionKey = data.extensionByKey.key;
185
+ }
186
+ // Unregister the extension
187
+ await client.request(UnregisterExtensionDocument, { id: extensionId });
188
+ if (opts.json || opts.jsonl) {
189
+ formatOutput({ success: true, extensionId, extensionKey }, opts);
190
+ }
191
+ else if (opts.quiet) {
192
+ console.log(extensionId);
193
+ }
194
+ else {
195
+ success(`Uninstalled extension "${extensionKey}"`);
196
+ console.log(` Extension ID: ${extensionId}`);
197
+ }
198
+ }));
128
199
  // sync
129
200
  extensions
130
201
  .command('sync <id>')
@@ -6674,6 +6674,12 @@ export type InstallExtensionMutation = {
6674
6674
  } | null;
6675
6675
  };
6676
6676
  };
6677
+ export type UnregisterExtensionMutationVariables = Exact<{
6678
+ id: Scalars['ID']['input'];
6679
+ }>;
6680
+ export type UnregisterExtensionMutation = {
6681
+ unregisterExtension: boolean;
6682
+ };
6677
6683
  export type ListFilesQueryVariables = Exact<{
6678
6684
  folder?: InputMaybe<Scalars['String']['input']>;
6679
6685
  mimeType?: InputMaybe<Scalars['String']['input']>;
@@ -8168,6 +8174,7 @@ export declare const GetExtensionByKeyDocument: DocumentNode<GetExtensionByKeyQu
8168
8174
  export declare const RegisterExtensionDocument: DocumentNode<RegisterExtensionMutation, RegisterExtensionMutationVariables>;
8169
8175
  export declare const TriggerExtensionSyncDocument: DocumentNode<TriggerExtensionSyncMutation, TriggerExtensionSyncMutationVariables>;
8170
8176
  export declare const InstallExtensionDocument: DocumentNode<InstallExtensionMutation, InstallExtensionMutationVariables>;
8177
+ export declare const UnregisterExtensionDocument: DocumentNode<UnregisterExtensionMutation, UnregisterExtensionMutationVariables>;
8171
8178
  export declare const ListFilesDocument: DocumentNode<ListFilesQuery, ListFilesQueryVariables>;
8172
8179
  export declare const GetFileDocument: DocumentNode<GetFileQuery, GetFileQueryVariables>;
8173
8180
  export declare const FileStorageUsageDocument: DocumentNode<FileStorageUsageQuery, FileStorageUsageQueryVariables>;