| import fsp from 'node:fs/promises'; | ||
| import { fileURLToPath } from 'node:url'; | ||
| import consola from 'consola'; | ||
| import createJiti from 'jiti'; | ||
| import { resolve, dirname, basename, join, extname } from 'pathe'; | ||
| import { filename } from 'pathe/utils'; | ||
| import { existsSync } from 'node:fs'; | ||
| import { homedir } from 'node:os'; | ||
| import { hash } from 'ohash'; | ||
| import { c as createContext, r as runWithContext } from './codeup.d746067e.mjs'; | ||
| const GIGET_PREFIXES = [ | ||
| "gh:", | ||
| "github:", | ||
| "gitlab:", | ||
| "bitbucket:", | ||
| "https://", | ||
| "http://" | ||
| ]; | ||
| async function resolveSourceDir(source, cwd, gigetOpts) { | ||
| if (!GIGET_PREFIXES.some((prefix) => source.startsWith(prefix))) { | ||
| return resolve(cwd, source); | ||
| } | ||
| const cloneName = `${source.replace(/\W+/g, "_").split("_").splice(0, 3).join("_")}_${hash(source)}`; | ||
| let cloneDir; | ||
| const localNodeModules = resolve(cwd, "node_modules"); | ||
| const parentDir = dirname(cwd); | ||
| if (basename(parentDir) === ".giget") { | ||
| cloneDir = join(parentDir, cloneName); | ||
| } else if (existsSync(localNodeModules)) { | ||
| cloneDir = join(localNodeModules, ".giget", cloneName); | ||
| } else { | ||
| cloneDir = process.env.XDG_CACHE_HOME ? resolve(process.env.XDG_CACHE_HOME, "giget", cloneName) : resolve(homedir(), ".cache/giget", cloneName); | ||
| } | ||
| if (existsSync(cloneDir) && !gigetOpts?.install) { | ||
| await fsp.rm(cloneDir, { recursive: true }); | ||
| } | ||
| const { downloadTemplate } = await import('giget'); | ||
| const cloned = await downloadTemplate(source, { | ||
| dir: cloneDir, | ||
| ...gigetOpts | ||
| }); | ||
| return cloned.dir; | ||
| } | ||
| async function applyAction(action, cwd) { | ||
| const context = createContext(cwd || ".", action.meta?.name); | ||
| try { | ||
| const start = performance.now(); | ||
| await runWithContext(context, async () => { | ||
| if (action.filter && !await action.filter(context)) { | ||
| consola.info(`Skipping action \`${getActionName(action)}\`...`); | ||
| return; | ||
| } | ||
| consola.info(`Applying action \`${getActionName(action)}\``); | ||
| await action.apply(context); | ||
| consola.success( | ||
| `Action \`${getActionName(action)}\` applied in ${(performance.now() - start).toFixed(2)}ms` | ||
| ); | ||
| }); | ||
| } catch (error) { | ||
| consola.error( | ||
| `Failed to apply action \`${getActionName(action)}\`: | ||
| `, | ||
| error | ||
| ); | ||
| } | ||
| } | ||
| async function applyActions(actions, cwd, opts) { | ||
| const _actions = opts?.sort ? sortActions(actions) : actions; | ||
| const _cwd = resolve(cwd || "."); | ||
| consola.info( | ||
| `Applying ${_actions.length} action${actions.length > 1 ? "s" : ""} to \`${_cwd}\`: | ||
| ${_actions.map((a) => { | ||
| const name = a.meta?.name || a._path || a.apply?.name || "?"; | ||
| const parts = [ | ||
| `\`${name}\``, | ||
| a.meta?.description && `: ${a.meta?.description}`, | ||
| a.meta?.date && `(${a.meta?.date})` | ||
| ].filter(Boolean); | ||
| return ` - ${parts.join(" ")}`; | ||
| }).join("\n")} | ||
| ` | ||
| ); | ||
| for (const action of _actions) { | ||
| await applyAction(action, _cwd); | ||
| } | ||
| } | ||
| function sortActions(actions) { | ||
| return [...actions].sort((a, b) => { | ||
| if (a.meta?.date && b.meta?.date) { | ||
| return a.meta.date.localeCompare(b.meta.date); | ||
| } | ||
| const aName = a.meta?.name || a._path || a.apply?.name || ""; | ||
| const bName = b.meta?.name || b._path || b.apply?.name || ""; | ||
| return aName.localeCompare(bName); | ||
| }); | ||
| } | ||
| async function applyActionFromFile(path, workingDir) { | ||
| const _path = resolve(path); | ||
| let action; | ||
| try { | ||
| action = await loadActionFromFile(path); | ||
| } catch (error) { | ||
| consola.error(`Failed to load action from \`${_path}\`: | ||
| `, error); | ||
| return; | ||
| } | ||
| return await applyAction(action, workingDir); | ||
| } | ||
| async function loadActionFromFile(path) { | ||
| const _path = resolve(path); | ||
| const actionDir = dirname(_path); | ||
| const _pkgDir = fileURLToPath(new URL("../..", import.meta.url)); | ||
| const jiti = createJiti(actionDir, { | ||
| interopDefault: true, | ||
| alias: { | ||
| codeup: join(_pkgDir, "dist/index.mjs"), | ||
| "codeup/utils": join(_pkgDir, "dist/utils/index.mjs") | ||
| } | ||
| }); | ||
| const action = jiti(_path); | ||
| if (!action || typeof action.apply !== "function") { | ||
| throw new Error( | ||
| `File \`${_path}\` does not export a valid object with \`apply\` method!` | ||
| ); | ||
| } | ||
| action._path = _path; | ||
| return action; | ||
| } | ||
| const supportedExtensions = /* @__PURE__ */ new Set([".js", ".ts", ".mjs", ".cjs"]); | ||
| async function loadActionsFromDir(actionsDir) { | ||
| const actionFiles = (await fsp.readdir(actionsDir)).filter( | ||
| (path) => supportedExtensions.has(extname(path)) | ||
| ); | ||
| const actions = await Promise.all( | ||
| actionFiles.map( | ||
| async (actionFile) => loadActionFromFile(resolve(actionsDir, actionFile)) | ||
| ) | ||
| ); | ||
| return actions; | ||
| } | ||
| async function applyActionsFromDir(actionsDir, cwd) { | ||
| const actions = await loadActionsFromDir(actionsDir); | ||
| return await applyActions(actions, cwd, { sort: true }); | ||
| } | ||
| async function applyActionsFrom(source, cwd) { | ||
| const sourceDir = await resolveSourceDir(source, cwd); | ||
| return await applyActionsFromDir(sourceDir, cwd); | ||
| } | ||
| function getActionName(action) { | ||
| return action.meta?.name || action._path && filename(action._path) || action.apply?.name || ""; | ||
| } | ||
| export { applyAction as a, applyActions as b, applyActionFromFile as c, loadActionsFromDir as d, applyActionsFromDir as e, applyActionsFrom as f, getActionName as g, loadActionFromFile as l, sortActions as s }; |
| #!/usr/bin/env node | ||
| import { defineCommand } from 'citty'; | ||
| import { f as applyActionsFrom } from '../shared/codeup.f0795b16.mjs'; | ||
| import { f as applyActionsFrom } from '../shared/codeup.cd1b3209.mjs'; | ||
| import 'node:fs/promises'; | ||
| import 'node:url'; | ||
| import 'consola'; | ||
@@ -6,0 +7,0 @@ import 'jiti'; |
@@ -5,3 +5,3 @@ #!/usr/bin/env node | ||
| const name = "codeup"; | ||
| const version = "0.0.2"; | ||
| const version = "0.0.3"; | ||
| const description = "Automated Codebase Maintainer."; | ||
@@ -8,0 +8,0 @@ |
+2
-1
| export { c as createContext, r as runWithContext, u as useContext } from './shared/codeup.d746067e.mjs'; | ||
| export { a as applyAction, c as applyActionFromFile, b as applyActions, f as applyActionsFrom, e as applyActionsFromDir, g as getActionName, l as loadActionFromFile, d as loadActionsFromDir, s as sortActions } from './shared/codeup.f0795b16.mjs'; | ||
| export { a as applyAction, c as applyActionFromFile, b as applyActions, f as applyActionsFrom, e as applyActionsFromDir, g as getActionName, l as loadActionFromFile, d as loadActionsFromDir, s as sortActions } from './shared/codeup.cd1b3209.mjs'; | ||
| import 'node:async_hooks'; | ||
@@ -10,2 +10,3 @@ import 'consola'; | ||
| import 'nypm'; | ||
| import 'node:url'; | ||
| import 'jiti'; | ||
@@ -12,0 +13,0 @@ import 'pathe/utils'; |
+1
-1
| { | ||
| "name": "codeup", | ||
| "version": "0.0.2", | ||
| "version": "0.0.3", | ||
| "description": "Automated Codebase Maintainer.", | ||
@@ -5,0 +5,0 @@ "repository": "unjs/codeup", |
+6
-3
@@ -71,5 +71,5 @@ # codeup | ||
| ignores: eslintignore.filter( | ||
| (i) => !["", "node_modules", "dist", "coverage"].includes(i), | ||
| (i) => !["", "node_modules", "dist", "coverage"].includes(i) | ||
| ), | ||
| }), | ||
| }) | ||
| ); | ||
@@ -94,3 +94,6 @@ | ||
| // Ensure latest eslint and preset versions are installed | ||
| await utils.addDevDependency(["eslint", "eslint-config-unjs"]); | ||
| await utils.addDevDependency([ | ||
| "eslint@^9.0.0", | ||
| "eslint-config-unjs@^0.3.0", | ||
| ]); | ||
@@ -97,0 +100,0 @@ // Run lint:fix script once |
| import fsp from 'node:fs/promises'; | ||
| import consola from 'consola'; | ||
| import createJiti from 'jiti'; | ||
| import { resolve, dirname, basename, join, extname } from 'pathe'; | ||
| import { filename } from 'pathe/utils'; | ||
| import { existsSync } from 'node:fs'; | ||
| import { homedir } from 'node:os'; | ||
| import { hash } from 'ohash'; | ||
| import { c as createContext, r as runWithContext } from './codeup.d746067e.mjs'; | ||
| const GIGET_PREFIXES = [ | ||
| "gh:", | ||
| "github:", | ||
| "gitlab:", | ||
| "bitbucket:", | ||
| "https://", | ||
| "http://" | ||
| ]; | ||
| async function resolveSourceDir(source, cwd, gigetOpts) { | ||
| if (!GIGET_PREFIXES.some((prefix) => source.startsWith(prefix))) { | ||
| return resolve(cwd, source); | ||
| } | ||
| const cloneName = `${source.replace(/\W+/g, "_").split("_").splice(0, 3).join("_")}_${hash(source)}`; | ||
| let cloneDir; | ||
| const localNodeModules = resolve(cwd, "node_modules"); | ||
| const parentDir = dirname(cwd); | ||
| if (basename(parentDir) === ".giget") { | ||
| cloneDir = join(parentDir, cloneName); | ||
| } else if (existsSync(localNodeModules)) { | ||
| cloneDir = join(localNodeModules, ".giget", cloneName); | ||
| } else { | ||
| cloneDir = process.env.XDG_CACHE_HOME ? resolve(process.env.XDG_CACHE_HOME, "giget", cloneName) : resolve(homedir(), ".cache/giget", cloneName); | ||
| } | ||
| if (existsSync(cloneDir) && !gigetOpts?.install) { | ||
| await fsp.rm(cloneDir, { recursive: true }); | ||
| } | ||
| const { downloadTemplate } = await import('giget'); | ||
| const cloned = await downloadTemplate(source, { | ||
| dir: cloneDir, | ||
| ...gigetOpts | ||
| }); | ||
| return cloned.dir; | ||
| } | ||
| async function applyAction(action, cwd) { | ||
| const context = createContext(cwd || ".", action.meta?.name); | ||
| try { | ||
| const start = performance.now(); | ||
| await runWithContext(context, async () => { | ||
| if (action.filter && !await action.filter(context)) { | ||
| consola.info(`Skipping action \`${getActionName(action)}\`...`); | ||
| return; | ||
| } | ||
| consola.info(`Applying action \`${getActionName(action)}\``); | ||
| await action.apply(context); | ||
| consola.success( | ||
| `Action \`${getActionName(action)}\` applied in ${(performance.now() - start).toFixed(2)}ms` | ||
| ); | ||
| }); | ||
| } catch (error) { | ||
| consola.error( | ||
| `Failed to apply action \`${getActionName(action)}\`: | ||
| `, | ||
| error | ||
| ); | ||
| } | ||
| } | ||
| async function applyActions(actions, cwd, opts) { | ||
| const _actions = opts?.sort ? sortActions(actions) : actions; | ||
| const _cwd = resolve(cwd || "."); | ||
| consola.info( | ||
| `Applying ${_actions.length} action${actions.length > 1 ? "s" : ""} to \`${_cwd}\`: | ||
| ${_actions.map((a) => { | ||
| const name = a.meta?.name || a._path || a.apply?.name || "?"; | ||
| const parts = [ | ||
| `\`${name}\``, | ||
| a.meta?.description && `: ${a.meta?.description}`, | ||
| a.meta?.date && `(${a.meta?.date})` | ||
| ].filter(Boolean); | ||
| return ` - ${parts.join(" ")}`; | ||
| }).join("\n")} | ||
| ` | ||
| ); | ||
| for (const action of _actions) { | ||
| await applyAction(action, _cwd); | ||
| } | ||
| } | ||
| function sortActions(actions) { | ||
| return [...actions].sort((a, b) => { | ||
| if (a.meta?.date && b.meta?.date) { | ||
| return a.meta.date.localeCompare(b.meta.date); | ||
| } | ||
| const aName = a.meta?.name || a._path || a.apply?.name || ""; | ||
| const bName = b.meta?.name || b._path || b.apply?.name || ""; | ||
| return aName.localeCompare(bName); | ||
| }); | ||
| } | ||
| async function applyActionFromFile(path, workingDir) { | ||
| const _path = resolve(path); | ||
| let action; | ||
| try { | ||
| action = await loadActionFromFile(path); | ||
| } catch (error) { | ||
| consola.error(`Failed to load action from \`${_path}\`: | ||
| `, error); | ||
| return; | ||
| } | ||
| return await applyAction(action, workingDir); | ||
| } | ||
| async function loadActionFromFile(path) { | ||
| const _path = resolve(path); | ||
| const actionDir = dirname(_path); | ||
| const jiti = createJiti(actionDir, { interopDefault: true }); | ||
| const action = jiti(_path); | ||
| if (!action || typeof action.apply !== "function") { | ||
| throw new Error( | ||
| `File \`${_path}\` does not export a valid object with \`apply\` method!` | ||
| ); | ||
| } | ||
| action._path = _path; | ||
| return action; | ||
| } | ||
| const supportedExtensions = /* @__PURE__ */ new Set([".js", ".ts", ".mjs", ".cjs"]); | ||
| async function loadActionsFromDir(actionsDir) { | ||
| const actionFiles = (await fsp.readdir(actionsDir)).filter( | ||
| (path) => supportedExtensions.has(extname(path)) | ||
| ); | ||
| const actions = await Promise.all( | ||
| actionFiles.map( | ||
| async (actionFile) => loadActionFromFile(resolve(actionsDir, actionFile)) | ||
| ) | ||
| ); | ||
| return actions; | ||
| } | ||
| async function applyActionsFromDir(actionsDir, cwd) { | ||
| const actions = await loadActionsFromDir(actionsDir); | ||
| return await applyActions(actions, cwd, { sort: true }); | ||
| } | ||
| async function applyActionsFrom(source, cwd) { | ||
| const sourceDir = await resolveSourceDir(source, cwd); | ||
| return await applyActionsFromDir(sourceDir, cwd); | ||
| } | ||
| function getActionName(action) { | ||
| return action.meta?.name || action._path && filename(action._path) || action.apply?.name || ""; | ||
| } | ||
| export { applyAction as a, applyActions as b, applyActionFromFile as c, loadActionsFromDir as d, applyActionsFromDir as e, applyActionsFrom as f, getActionName as g, loadActionFromFile as l, sortActions as s }; |
Filesystem access
Supply chain riskAccesses the file system, and could potentially read sensitive data.
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Filesystem access
Supply chain riskAccesses the file system, and could potentially read sensitive data.
32183
0.98%556
1.83%340
0.89%0
-100%