-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: upload images and mutation dependencies
- Loading branch information
Showing
31 changed files
with
573 additions
and
99 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,78 @@ | ||
import { Command, Argument, Option } from 'commander'; | ||
import { addInteractiveAndTokenOption } from '../../core/helpers/add-iteractive-and-token-option'; | ||
import type { Logger } from '../../domain/contracts/logger'; | ||
import type { CommandBus } from '../../domain/contracts/bus'; | ||
import type { GetAuthenticatedUser } from '../../domain/contracts/get-authenticated-user'; | ||
import type { FlySystem } from '../../domain/contracts/fly-system'; | ||
import type { AsyncCreateClient } from '../../domain/contracts/credential-retriever'; | ||
import pc from 'picocolors'; | ||
|
||
type Deps = { | ||
logger: Logger; | ||
commandBus: CommandBus; | ||
flySystem: FlySystem; | ||
getAuthenticatedUserWithInteractivityIfPossible: GetAuthenticatedUser; | ||
createCrystallizeClient: AsyncCreateClient; | ||
}; | ||
export const createImageUploadCommand = ({ | ||
getAuthenticatedUserWithInteractivityIfPossible, | ||
commandBus, | ||
logger, | ||
flySystem, | ||
}: Deps): Command => { | ||
const command = new Command('upload'); | ||
command.description('Upload images(s) to a Tenant.'); | ||
command.addArgument(new Argument('<tenant-identifier>', 'The tenant identifier to invite on.')); | ||
command.addArgument(new Argument('<file>', 'The file or the folder that contains the Images.')); | ||
command.addArgument(new Argument('[output-file]', 'An optional file that will contain the mapping path:key.')); | ||
command.addOption(new Option('-f, --force', 'Force and override the output-file if it exits.')); | ||
|
||
addInteractiveAndTokenOption(command); | ||
command.action(async (tenantIdentifier: string, file: string, outputFile: string, flags) => { | ||
if (outputFile && (await flySystem.isFileExists(outputFile)) && !flags.force) { | ||
throw new Error(`File ${outputFile} already exist.`); | ||
} | ||
|
||
const { credentials } = await getAuthenticatedUserWithInteractivityIfPossible({ | ||
isInteractive: !flags.noInteractive, | ||
token_id: flags.token_id, | ||
token_secret: flags.token_secret, | ||
}); | ||
|
||
const images: string[] = []; | ||
if (await flySystem.isFileExists(file)) { | ||
images.push(file); | ||
} | ||
|
||
for await (const image of flySystem.loopInDirectory(file)) { | ||
images.push(image); | ||
} | ||
|
||
const intent = commandBus.createCommand('UploadImages', { | ||
paths: images, | ||
credentials, | ||
tenant: { | ||
identifier: tenantIdentifier, | ||
}, | ||
}); | ||
const { result } = await commandBus.dispatch(intent); | ||
|
||
if (!result) { | ||
logger.error(`Failed to upload images.`); | ||
return; | ||
} | ||
logger.success(`Images uploaded.`); | ||
if (!outputFile) { | ||
for (const [path, key] of Object.entries(result.keys)) { | ||
logger.complete(`\t - ${path} -> ${pc.yellowBright(key)}`); | ||
} | ||
return; | ||
} | ||
|
||
await flySystem.saveFile(outputFile, JSON.stringify(result.keys, null, 2) + `\r\n`); | ||
logger.complete(`Mapping saved at ${outputFile}`); | ||
return; | ||
}); | ||
|
||
return command; | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
71 changes: 71 additions & 0 deletions
71
components/cli/src/command/mass-operation/execute-mutations.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,71 @@ | ||
import { Argument, Command } from 'commander'; | ||
import { addInteractiveAndTokenOption } from '../../core/helpers/add-iteractive-and-token-option'; | ||
import type { GetAuthenticatedUser } from '../../domain/contracts/get-authenticated-user'; | ||
import type { Logger } from '../../domain/contracts/logger'; | ||
import type { FlySystem } from '../../domain/contracts/fly-system'; | ||
import { ZodError } from 'zod'; | ||
import type { CommandBus } from '../../domain/contracts/bus'; | ||
|
||
type Deps = { | ||
logger: Logger; | ||
flySystem: FlySystem; | ||
commandBus: CommandBus; | ||
getAuthenticatedUserWithInteractivityIfPossible: GetAuthenticatedUser; | ||
}; | ||
|
||
export const createExecuteMutationsCommand = ({ | ||
logger, | ||
flySystem, | ||
commandBus, | ||
getAuthenticatedUserWithInteractivityIfPossible: getAuthenticatedUser, | ||
}: Deps): Command => { | ||
const command = new Command('execute-mutations'); | ||
command.description('Execute mutations with different set (client-side).'); | ||
command.addArgument(new Argument('<tenant-identifier>', 'The tenant identifier to use.')); | ||
command.addArgument(new Argument('<file>', 'The file that contains the Mutations.')); | ||
command.addArgument(new Argument('[image-mapping-file]', 'An optional file for images mapping.')); | ||
addInteractiveAndTokenOption(command); | ||
|
||
command.action(async (tenantIdentifier: string, inputFile: string, imageMappingFile: string, flags) => { | ||
if (!(await flySystem.isFileExists(inputFile))) { | ||
throw new Error(`File ${inputFile} was not found.`); | ||
} | ||
try { | ||
const { credentials } = await getAuthenticatedUser({ | ||
isInteractive: !flags.noInteractive, | ||
token_id: flags.token_id, | ||
token_secret: flags.token_secret, | ||
}); | ||
|
||
let imageMapping: Record<string, string> = {}; | ||
if (imageMappingFile) { | ||
imageMapping = await flySystem.loadJsonFile<Record<string, string>>(imageMappingFile); | ||
} | ||
|
||
const intent = commandBus.createCommand('ExecuteMutations', { | ||
filePath: inputFile, | ||
tenant: { | ||
identifier: tenantIdentifier, | ||
}, | ||
credentials, | ||
placeholderMap: { | ||
images: imageMapping, | ||
}, | ||
}); | ||
const { result } = await commandBus.dispatch(intent); | ||
if (!result) { | ||
throw new Error('Failed to execute the Mutations file.'); | ||
} | ||
// console.dir({ result }, { depth: null }); | ||
logger.success(`Mutations executed.`); | ||
} catch (error) { | ||
if (error instanceof ZodError) { | ||
for (const issue of error.issues) { | ||
logger.error(`[${issue.path.join('.')}]: ${issue.message}`); | ||
} | ||
} | ||
throw error; | ||
} | ||
}); | ||
return command; | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
21 changes: 18 additions & 3 deletions
21
components/cli/src/core/create-crystallize-client-builder.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,15 +1,30 @@ | ||
import { createClient, type ClientConfiguration, type CreateClientOptions } from '@crystallize/js-api-client'; | ||
import type { AsyncCreateClient } from '../domain/contracts/credential-retriever'; | ||
|
||
type Deps = { | ||
crystallizeEnvironment: 'staging' | 'production'; | ||
}; | ||
export const createCrystallizeClientBuilder = | ||
({ crystallizeEnvironment }: Deps): typeof createClient => | ||
(configuration: ClientConfiguration, options?: CreateClientOptions) => | ||
createClient( | ||
({ crystallizeEnvironment }: Deps): AsyncCreateClient => | ||
async (configuration: ClientConfiguration, options?: CreateClientOptions) => { | ||
if (configuration.tenantIdentifier.length > 0 && (configuration.tenantId || '').length === 0) { | ||
const tempClient = createClient({ | ||
...configuration, | ||
origin: crystallizeEnvironment === 'staging' ? '-dev.crystallize.digital' : '.crystallize.com', | ||
}); | ||
const tenantInfo = await tempClient.nextPimApi( | ||
`query { tenant(identifier:"${configuration.tenantIdentifier}") { ... on Tenant { id } } }`, | ||
); | ||
if (!tenantInfo.tenant.id) { | ||
throw new Error(`Tenant Id for identifier ${configuration.tenantIdentifier} not found`); | ||
} | ||
configuration.tenantId = tenantInfo.tenant.id; | ||
} | ||
return createClient( | ||
{ | ||
...configuration, | ||
origin: crystallizeEnvironment === 'staging' ? '-dev.crystallize.digital' : '.crystallize.com', | ||
}, | ||
options, | ||
); | ||
}; |
Oops, something went wrong.