Comparing version 1.0.1 to 1.1.0
@@ -9,3 +9,3 @@ import process from 'node:process'; | ||
import { getPackageJson } from './util/index.js'; | ||
import { update, fix, refresh } from './commands/index.js'; | ||
import { update, fix, refresh, add } from './commands/index.js'; | ||
const __dirname = dirname(fileURLToPath(import.meta.url)); | ||
@@ -33,2 +33,10 @@ export async function run(arguments_ = process.argv) { | ||
program | ||
.command('add [path]') | ||
.description('adds infra core templates') | ||
.action(async (targetPath, _options, command) => { | ||
targetPath = targetPath?.trim() ?? '.'; | ||
const options = command.optsWithGlobals(); | ||
await add(targetPath, options); | ||
}); | ||
program | ||
.command('update [path]') | ||
@@ -35,0 +43,0 @@ .description('updates infra core templates') |
@@ -32,3 +32,3 @@ import { promises as fs } from 'node:fs'; | ||
if (!(options.yes || (await askForConfirmation('Add/remove files?')))) { | ||
console.info('Clean up cancelled.'); | ||
console.info('Cancelled, no changes made.'); | ||
return; | ||
@@ -35,0 +35,0 @@ } |
@@ -0,3 +1,4 @@ | ||
export * from './add.js'; | ||
export * from './fix.js'; | ||
export * from './refresh.js'; | ||
export * from './update.js'; |
@@ -0,3 +1,4 @@ | ||
export * from './add.js'; | ||
export * from './fix.js'; | ||
export * from './refresh.js'; | ||
export * from './update.js'; |
import { type DependencyInfo } from './dependency.js'; | ||
export declare function getBicepDependencyInfo(files: string[]): Promise<DependencyInfo>; | ||
export declare function getBicepDependencyInfo(files: string[], basePath?: string): Promise<DependencyInfo>; | ||
export declare function getBicepCoreTemplates(azdPath: string): Promise<string[]>; |
import path from 'node:path'; | ||
import createDebug from 'debug'; | ||
import { AZD_INFRA_PATH } from '../constants.js'; | ||
import { pathExists, readFile } from '../util/index.js'; | ||
import glob from 'fast-glob'; | ||
import { AZD_BICEP_CORE_GLOBS, AZD_BICEP_PATH, AZD_INFRA_PATH } from '../constants.js'; | ||
import { deepClone, pathExists, readFile } from '../util/index.js'; | ||
import { isDependencyUsed } from './dependency.js'; | ||
const debug = createDebug('bicep'); | ||
const bicepModuleRegex = /module\s+[\w_]+\s+'(.+)'/g; | ||
export async function getBicepDependencyInfo(files) { | ||
const bicepFiles = files.filter((file) => file.endsWith('.bicep')).map((file) => path.join(AZD_INFRA_PATH, file)); | ||
export async function getBicepDependencyInfo(files, basePath = AZD_INFRA_PATH) { | ||
const bicepFiles = files.filter((file) => file.endsWith('.bicep')).map((file) => path.join(basePath, file)); | ||
const deps = { | ||
@@ -39,11 +40,29 @@ graph: {}, | ||
deps.all = [...allFiles]; | ||
// Find unused dependencies | ||
for (const file of allFiles) { | ||
if (!isDependencyUsed(file, deps.graph) && !file.endsWith('main.bicep')) { | ||
deps.unused.push(file); | ||
} | ||
} | ||
deps.unused = await findUnusedDependencies(deps.all, deps.graph); | ||
debug('Dependency info:', deps); | ||
return deps; | ||
} | ||
async function findUnusedDependencies(files, graph) { | ||
const unused = new Set(); | ||
const usedGraph = deepClone(graph); | ||
let hasChanged = true; | ||
// Keep iterating until no more changes are made, | ||
// as removing one dependency might make another unused | ||
while (hasChanged) { | ||
hasChanged = false; | ||
for (const file of files) { | ||
if (unused.has(file)) { | ||
continue; | ||
} | ||
if (!isDependencyUsed(file, usedGraph) && !file.endsWith('main.bicep')) { | ||
debug(`Found new unused dependency: ${file}`); | ||
unused.add(file); | ||
hasChanged = true; | ||
// eslint-disable-next-line @typescript-eslint/no-dynamic-delete | ||
delete usedGraph[file]; | ||
} | ||
} | ||
} | ||
return [...unused]; | ||
} | ||
async function getBicepDependencies(file) { | ||
@@ -61,1 +80,7 @@ const dependencies = []; | ||
} | ||
export async function getBicepCoreTemplates(azdPath) { | ||
const coreInfraPath = path.join(azdPath, AZD_BICEP_PATH); | ||
const coreFiles = await glob(AZD_BICEP_CORE_GLOBS, { cwd: coreInfraPath }); | ||
debug('Found core template files:', coreFiles); | ||
return coreFiles; | ||
} |
@@ -7,3 +7,4 @@ export type PackageJson = Record<string, any> & { | ||
export declare function pathExists(path: string): Promise<boolean>; | ||
export declare function ensureDirectory(path: string): Promise<void>; | ||
export declare function readFile(file: string): Promise<string>; | ||
export declare function removeFirstPosixPathSegment(filePath: string): string; |
@@ -17,2 +17,5 @@ import { join } from 'node:path'; | ||
} | ||
export async function ensureDirectory(path) { | ||
await fs.mkdir(path, { recursive: true }); | ||
} | ||
export async function readFile(file) { | ||
@@ -19,0 +22,0 @@ return fs.readFile(file, 'utf8'); |
export * from './command.js'; | ||
export * from './file.js'; | ||
export * from './input.js'; | ||
export * from './object.js'; | ||
export * from './repository.js'; | ||
export * from './string.js'; |
export * from './command.js'; | ||
export * from './file.js'; | ||
export * from './input.js'; | ||
export * from './object.js'; | ||
export * from './repository.js'; | ||
export * from './string.js'; |
@@ -1,2 +0,2 @@ | ||
export declare function askForInput(question: string): Promise<string>; | ||
export declare function askForConfirmation(question: string): Promise<boolean>; | ||
export declare function selectMany(question: string, choices: string[]): Promise<string[]>; |
@@ -1,18 +0,22 @@ | ||
import { createInterface } from 'node:readline'; | ||
import process from 'node:process'; | ||
export async function askForInput(question) { | ||
return new Promise((resolve, _reject) => { | ||
const read = createInterface({ | ||
input: process.stdin, | ||
output: process.stdout | ||
import { confirm } from '@inquirer/prompts'; | ||
import checkbox from '@inquirer/checkbox'; | ||
export async function askForConfirmation(question) { | ||
try { | ||
return await confirm({ message: question, default: true }); | ||
} | ||
catch { | ||
return false; | ||
} | ||
} | ||
export async function selectMany(question, choices) { | ||
try { | ||
const selected = await checkbox({ | ||
message: question, | ||
choices: choices.map((choice) => ({ value: choice })) | ||
}); | ||
read.question(question, (answer) => { | ||
read.close(); | ||
resolve(answer); | ||
}); | ||
}); | ||
return selected; | ||
} | ||
catch { | ||
return []; | ||
} | ||
} | ||
export async function askForConfirmation(question) { | ||
const answer = await askForInput(`${question} [Y/n] `); | ||
return answer.toLowerCase() !== 'n'; | ||
} |
{ | ||
"name": "azd-infra", | ||
"version": "1.0.1", | ||
"version": "1.1.0", | ||
"description": "Manages your Azure Developer CLI projects' infrastructure", | ||
@@ -22,6 +22,7 @@ "type": "module", | ||
"clean": "rm -rf lib *.tgz", | ||
"release:check": "semantic-release --dry-run", | ||
"prepare": "simple-git-hooks || echo 'simple-git-hooks install skipped'" | ||
"release:check": "semantic-release --dry-run" | ||
}, | ||
"dependencies": { | ||
"@inquirer/checkbox": "^2.3.5", | ||
"@inquirer/prompts": "^5.0.5", | ||
"chalk": "^5.3.0", | ||
@@ -39,3 +40,2 @@ "commander": "^12.1.0", | ||
"semantic-release-npm-github": "^5.0.0", | ||
"simple-git-hooks": "^2.11.1", | ||
"typescript": "^5.4.5", | ||
@@ -66,8 +66,2 @@ "xo": "^0.58.0" | ||
}, | ||
"simple-git-hooks": { | ||
"pre-commit": "npx lint-staged" | ||
}, | ||
"lint-staged": { | ||
"*.{js,ts}": "xo --fix" | ||
}, | ||
"prettier": { | ||
@@ -74,0 +68,0 @@ "trailingComma": "none", |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
30279
7
44
635
7
+ Added@inquirer/checkbox@^2.3.5
+ Added@inquirer/prompts@^5.0.5
+ Added@inquirer/confirm@3.2.0(transitive)
+ Added@inquirer/core@9.2.1(transitive)
+ Added@inquirer/editor@2.2.0(transitive)
+ Added@inquirer/expand@2.3.0(transitive)
+ Added@inquirer/figures@1.0.8(transitive)
+ Added@inquirer/input@2.3.0(transitive)
+ Added@inquirer/number@1.1.0(transitive)
+ Added@inquirer/password@2.2.0(transitive)
+ Added@inquirer/prompts@5.5.0(transitive)
+ Added@inquirer/rawlist@2.3.0(transitive)
+ Added@inquirer/search@1.1.0(transitive)
+ Added@inquirer/select@2.5.0(transitive)
+ Added@inquirer/type@1.5.52.0.0(transitive)
+ Added@types/mute-stream@0.0.4(transitive)
+ Added@types/node@22.10.1(transitive)
+ Added@types/wrap-ansi@3.0.0(transitive)
+ Addedansi-escapes@4.3.2(transitive)
+ Addedansi-styles@4.3.0(transitive)
+ Addedchardet@0.7.0(transitive)
+ Addedcli-width@4.1.0(transitive)
+ Addedcolor-convert@2.0.1(transitive)
+ Addedcolor-name@1.1.4(transitive)
+ Addedexternal-editor@3.1.0(transitive)
+ Addediconv-lite@0.4.24(transitive)
+ Addedmute-stream@1.0.0(transitive)
+ Addedos-tmpdir@1.0.2(transitive)
+ Addedsafer-buffer@2.1.2(transitive)
+ Addedsignal-exit@4.1.0(transitive)
+ Addedtmp@0.0.33(transitive)
+ Addedtype-fest@0.21.3(transitive)
+ Addedundici-types@6.20.0(transitive)
+ Addedwrap-ansi@6.2.0(transitive)
+ Addedyoctocolors-cjs@2.1.2(transitive)