Skip to content

Commit

Permalink
Merge pull request #1292 from rharkor/dev
Browse files Browse the repository at this point in the history
Dev
  • Loading branch information
rharkor authored Sep 4, 2024
2 parents 3a41d78 + 690f953 commit 9d83fad
Show file tree
Hide file tree
Showing 9 changed files with 898 additions and 364 deletions.
1,034 changes: 747 additions & 287 deletions _old/package-lock.json

Large diffs are not rendered by default.

3 changes: 2 additions & 1 deletion packages/cli/src/app/.env.example
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
LOGGER_ENV=development
ROOT_PATH=/workspace/packages/cli/src/app
ENV=development
ROOT_PATH=/workspace/packages/cli/src/app/out
3 changes: 2 additions & 1 deletion packages/cli/src/app/.gitignore
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
config.json
config.json
out
1 change: 1 addition & 0 deletions packages/cli/src/app/src/api/configuration/mutations.ts
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ export const applyConfiguration = async ({}: apiInputFromSchema<typeof undefined
configFileName: "config.json",
pluginsDirectory,
root: env.ROOT_PATH,
noTask: true,
})

const data: z.infer<ReturnType<typeof updateConfigurationResponseSchema>> = { configuration }
Expand Down
93 changes: 54 additions & 39 deletions packages/cli/src/app/src/app/components/current-configuration.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ export default function CurrentConfiguration({
}

const applyConfigurationMutation = trpc.configuration.applyConfiguration.useMutation({
onSettled: async () => {
onSuccess: async () => {
toast.success(dictionary.configurationApplied)
},
})
Expand Down Expand Up @@ -256,17 +256,35 @@ function Plugin({
onClose: onEditClose,
} = useDisclosure()

const [overridedTo, setOverridedTo] = useState<Record<string, string>>({})
const onEdit = async (e: React.FormEvent<HTMLFormElement>) => {
e.preventDefault()
await _onEdit(plugin)
onEditClose()
}

const onEdit = async () => {
await _onEdit({
...plugin,
paths: plugin.paths.map((p) => ({
from: plugin.sourcePath,
to: overridedTo[p.to] ?? p.to,
})),
const [overridedTo, setOverridedTo] = useState<Record<string, string>>(
plugin.paths.reduce(
(acc, p) => {
acc[p.from] = p.overridedTo ?? p.to
return acc
},
{} as Record<string, string>
)
)
const editPath = (fromKey: string) => (to: string) => {
setOverridedTo((prev) => ({
...prev,
[fromKey]: to,
}))
plugin.paths = plugin.paths.map((p) => {
if (p.from === fromKey) {
return {
...p,
overridedTo: to,
}
}
return p
})
onEditClose()
}

return (
Expand Down Expand Up @@ -352,35 +370,32 @@ function Plugin({
{(onClose) => (
<>
<ModalHeader className="flex flex-col gap-1">{dictionary.pluginSettings}</ModalHeader>
<ModalBody>
{plugin.paths.map((p, i) => (
<Fragment key={p.from}>
{i !== 0 && <Divider orientation="horizontal" />}
<div className="flex flex-col gap-1">
<Input isDisabled isReadOnly value={plugin.sourcePath} label={dictionary.sourcePath} />
<Input
value={overridedTo[p.to] ?? ""}
onValueChange={(value) => {
setOverridedTo((prev) => ({
...prev,
[p.to]: value,
}))
}}
placeholder={p.to}
label={dictionary.outputPath}
/>
</div>
</Fragment>
))}
</ModalBody>
<ModalFooter>
<Button variant="light" onPress={onClose} isDisabled={isPending}>
{dictionary.close}
</Button>
<Button color="primary" onPress={onEdit} isLoading={isPending}>
{dictionary.save}
</Button>
</ModalFooter>
<form onSubmit={onEdit}>
<ModalBody>
{plugin.paths.map((p, i) => (
<Fragment key={p.from}>
{i !== 0 && <Divider orientation="horizontal" />}
<div className="flex flex-col gap-1">
<Input isDisabled isReadOnly value={p.from} label={dictionary.sourcePath} />
<Input
value={overridedTo[p.from] ?? ""}
onValueChange={editPath(p.from)}
placeholder={p.to}
label={dictionary.outputPath}
/>
</div>
</Fragment>
))}
</ModalBody>
<ModalFooter>
<Button variant="light" onPress={onClose} isDisabled={isPending}>
{dictionary.close}
</Button>
<Button color="primary" type="submit" isLoading={isPending}>
{dictionary.save}
</Button>
</ModalFooter>
</form>
</>
)}
</ModalContent>
Expand Down
24 changes: 20 additions & 4 deletions packages/cli/src/app/src/lib/configuration/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,15 +29,23 @@ const webConfigToApiConfig = (webConfig: TConfiguration): z.infer<typeof optiona
const content = optionalConfigSchema.parse({
name: webConfig.name,
plugins: (webConfig.plugins ?? []).map((plugin) => {
return {
const fullP = {
name: plugin.sourcePath,
paths: plugin.paths.map((p) => p.to),
paths: plugin.paths.map((p) => ({
from: p.from,
to: p.overridedTo || p.to,
})),
}
//? If there's no override, or the override is the same as the original path, return the name
if (!plugin.paths.some((p) => p.overridedTo) || plugin.paths.every((p) => p.to === p.overridedTo)) {
return fullP.name
}
return fullP
}),
})
return content
} catch (error) {
logger.error(error)
logger.error("Failed to convert the web configuration", error)
throw new TRPCError({
message: `Failed to convert the web configuration`,
code: "INTERNAL_SERVER_ERROR",
Expand Down Expand Up @@ -76,7 +84,15 @@ const apiConfigToWebConfig = async (apiConfig: z.infer<typeof optionalConfigSche
description: foundPlugin.description,
id: foundPlugin.id,
sourcePath: foundPlugin.sourcePath,
paths: foundPlugin.paths,
paths: foundPlugin.paths.map((path) => {
const overridedTo =
typeof plugin === "string" ? undefined : plugin.paths.find((p) => p.from === path.from)?.to
return {
from: path.from,
to: path.to,
overridedTo,
}
}),
}
}),
}
Expand Down
1 change: 1 addition & 0 deletions packages/cli/src/functions/apply-config/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ export const applyConfig = async () => {
configFileName,
pluginsDirectory,
root,
noTask: false,
}).catch(() => {
process.exit(1)
})
Expand Down
71 changes: 46 additions & 25 deletions packages/scripts/src/utils/template-config/apply.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,68 +10,84 @@ export const applyConfigurationTask = async ({
configFileName,
pluginsDirectory,
root,
noTask,
}: {
pluginsDirectory: string
configFileName: string
root: string
noTask: boolean
}) => {
const applyConfigTask = await task.startTask({
name: "Apply template config... 🧰",
})
let applyConfigTask: null | Awaited<ReturnType<(typeof task)["startTask"]>> = null
if (!noTask) {
applyConfigTask = await task.startTask({
name: "Apply template config... 🧰",
})
}

//* Check if the plugins directory exists
applyConfigTask.log("Checking if the plugins directory exists")
if (applyConfigTask) applyConfigTask.log("Checking if the plugins directory exists")
else logger.info("Checking if the plugins directory exists")
if (!(await fs.exists(pluginsDirectory))) {
applyConfigTask.error(`The plugins directory doesn't exist at ${pluginsDirectory}`)
applyConfigTask.stop()
if (applyConfigTask) applyConfigTask.error(`The plugins directory doesn't exist at ${pluginsDirectory}`)
else logger.error(`The plugins directory doesn't exist at ${pluginsDirectory}`)
applyConfigTask?.stop()
throw new Error(`The plugins directory doesn't exist at ${pluginsDirectory}`)
}

//* Retrieve config
applyConfigTask.log("Retrieving the config")
if (applyConfigTask) applyConfigTask.log("Retrieving the config")
else logger.info("Retrieving the config")
const configPath = !root.endsWith(configFileName) ? path.join(root, configFileName) : root
if (!(await fs.exists(configPath))) {
applyConfigTask.error(`The config file ${configPath} doesn't exist`)
applyConfigTask.stop()
if (applyConfigTask) applyConfigTask.error(`The config file ${configPath} doesn't exist`)
else logger.error(`The config file ${configPath} doesn't exist`)
applyConfigTask?.stop()
throw new Error(`The config file ${configPath} doesn't exist`)
}

const config = (await fs.readJson(configPath)) as TConfig
try {
configSchema.parse(config)
} catch (error) {
applyConfigTask.error(`The config file ${configPath} is not valid`)
applyConfigTask.stop()
if (applyConfigTask) applyConfigTask.error(`The config file ${configPath} is not valid`)
else logger.error(`The config file ${configPath} is not valid`)
applyConfigTask?.stop()
logger.error(error)
throw error
}

//* Apply plugins
applyConfigTask.log("Applying plugins")
//* Verify plugins
if (applyConfigTask) applyConfigTask.log("Applying plugins")
else logger.info("Applying plugins")

for (const plugin of config.plugins) {
const pluginName = typeof plugin === "string" ? plugin : plugin.name
const pluginPath = path.join(pluginsDirectory, pluginName)
if (!(await fs.exists(pluginPath))) {
applyConfigTask.error(`The plugin ${pluginName} doesn't exist at ${pluginPath}`)
applyConfigTask.stop()
if (applyConfigTask) applyConfigTask.error(`The plugin ${pluginName} doesn't exist at ${pluginPath}`)
else logger.error(`The plugin ${pluginName} doesn't exist at ${pluginPath}`)
applyConfigTask?.stop()
throw new Error(`The plugin ${pluginName} doesn't exist at ${pluginPath}`)
}
const pluginConfigPath = path.join(pluginPath, configFileName)
const pluginConfig = (await fs.readJson(pluginConfigPath)) as TPluginConfig
try {
pluginConfigSchema.parse(pluginConfig)
} catch (error) {
applyConfigTask.error(`The plugin config file ${pluginConfigPath} is not valid. Contact developer`)
applyConfigTask.stop()
if (applyConfigTask)
applyConfigTask.error(`The plugin config file ${pluginConfigPath} is not valid. Contact developer`)
else logger.error(`The plugin config file ${pluginConfigPath} is not valid. Contact developer`)
applyConfigTask?.stop()
logger.error(error)
throw error
}

//? Check if the plugin config exists
if (!(await fs.exists(pluginConfigPath))) {
applyConfigTask.error(`The plugin config for ${pluginName} doesn't exist at ${pluginConfigPath}`)
applyConfigTask.stop()
if (applyConfigTask)
applyConfigTask.error(`The plugin config for ${pluginName} doesn't exist at ${pluginConfigPath}`)
else logger.error(`The plugin config for ${pluginName} doesn't exist at ${pluginConfigPath}`)
applyConfigTask?.stop()
throw new Error(`The plugin config for ${pluginName} doesn't exist at ${pluginConfigPath}`)
}

Expand All @@ -81,25 +97,29 @@ export const applyConfigurationTask = async ({
for (const relativeDestinationPath of relativeDestinationPaths) {
const destinationPath = path.join(root, relativeDestinationPath)
if (await fs.exists(destinationPath)) {
applyConfigTask.error(`A file/folder already exists at the destination ${destinationPath}`)
applyConfigTask.stop()
if (applyConfigTask) applyConfigTask.error(`A file/folder already exists at the destination ${destinationPath}`)
else logger.error(`A file/folder already exists at the destination ${destinationPath}`)
applyConfigTask?.stop()
throw new Error(`A file/folder already exists at the destination ${destinationPath}`)
}
}
}

//* Apply the plugins
applyConfigTask.log("Applying the plugins")
if (applyConfigTask) applyConfigTask.log("Applying the plugins")
else logger.info("Applying the plugins")
for (const plugin of config.plugins) {
const pluginName = typeof plugin === "string" ? plugin : plugin.name
const pluginPath = path.join(pluginsDirectory, pluginName)
const pluginConfigPath = path.join(pluginPath, configFileName)
const pluginConfig = (await fs.readJson(pluginConfigPath)) as TPluginConfig
// Copy the plugin to the destination
for (const { from, to } of pluginConfig.paths) {
for (const { from, to: defaultTo } of pluginConfig.paths) {
const to = typeof plugin === "string" ? defaultTo : (plugin.paths.find((p) => p.from === from)?.to ?? defaultTo)
const sourcePath = path.join(pluginPath, from)
const destinationPath = path.join(root, to)
applyConfigTask.log(`Copying the plugin ${pluginName} to the destination ${destinationPath}`)
if (applyConfigTask) applyConfigTask.log(`Copying the plugin ${pluginName} to the destination ${destinationPath}`)
else logger.info(`Copying the plugin ${pluginName} to the destination ${destinationPath}`)
await fs.copy(sourcePath, destinationPath)
}
}
Expand All @@ -108,6 +128,7 @@ export const applyConfigurationTask = async ({
// applyConfigTask.log("Deleting the config file")
// await fs.remove(configPath)

applyConfigTask.stop("The template config has been applied! 🎉")
if (applyConfigTask) applyConfigTask.stop("The template config has been applied! 🎉")
else logger.success("The template config has been applied! 🎉")
logger.info("You can now delete the config file if you want")
}
32 changes: 25 additions & 7 deletions packages/scripts/src/utils/template-config/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,21 +17,26 @@ export function isPathInCurrentScope(filePath: string): boolean {
export const fullPluginSchema = z.object({
name: z.string(),
paths: z.array(
z
.string()
.optional()
.refine(
z.object({
from: z.string().refine(
(value) => {
if (value === undefined) {
return true
if (!isPathInCurrentScope(value)) {
return false
}
return true
},
{ message: "The path should be relative and in the current directory" }
),
to: z.string().refine(
(value) => {
if (!isPathInCurrentScope(value)) {
return false
}
return true
},
{ message: "The path should be relative and in the current directory" }
)
),
})
),
})

Expand Down Expand Up @@ -71,6 +76,19 @@ export const pluginConfigSchema = z.object({
},
{ message: "The path should be relative and in the current directory" }
),
overridedTo: z
.string()
.optional()
.refine(
(value) => {
if (value === undefined) return true
if (!isPathInCurrentScope(value)) {
return false
}
return true
},
{ message: "The path should be relative and in the current directory" }
),
})
)
.refine(
Expand Down

0 comments on commit 9d83fad

Please sign in to comment.