@cloud-copilot/iam-expand 0.1.9 → 0.1.11
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.
- package/README.md +3 -3
- package/dist/cjs/cli.js +2 -2
- package/dist/cjs/cli.js.map +1 -1
- package/dist/cjs/cli_utils.d.ts +1 -1
- package/dist/cjs/cli_utils.d.ts.map +1 -1
- package/dist/cjs/cli_utils.js +1 -1
- package/dist/cjs/cli_utils.js.map +1 -1
- package/dist/cjs/expand_file.d.ts +3 -2
- package/dist/cjs/expand_file.d.ts.map +1 -1
- package/dist/cjs/expand_file.js +14 -15
- package/dist/cjs/expand_file.js.map +1 -1
- package/dist/esm/cli.js +2 -2
- package/dist/esm/cli.js.map +1 -1
- package/dist/esm/cli_utils.d.ts +1 -1
- package/dist/esm/cli_utils.d.ts.map +1 -1
- package/dist/esm/cli_utils.js +1 -1
- package/dist/esm/cli_utils.js.map +1 -1
- package/dist/esm/expand_file.d.ts +3 -2
- package/dist/esm/expand_file.d.ts.map +1 -1
- package/dist/esm/expand_file.js +14 -15
- package/dist/esm/expand_file.js.map +1 -1
- package/package.json +5 -2
- package/examples/README.md +0 -3
- package/examples/download-and-expand-authorization-details.sh +0 -8
- package/examples/download-and-expand-policies.sh +0 -22
- package/postbuild.sh +0 -13
- package/src/cli.ts +0 -94
- package/src/cli_utils.test.ts +0 -147
- package/src/cli_utils.ts +0 -84
- package/src/expand.test.ts +0 -489
- package/src/expand.ts +0 -166
- package/src/expand_file.test.ts +0 -184
- package/src/expand_file.ts +0 -39
- package/src/index.ts +0 -1
- package/src/stdin.ts +0 -34
- package/tsconfig.cjs.json +0 -11
- package/tsconfig.esm.json +0 -14
- package/tsconfig.json +0 -22
package/src/cli_utils.test.ts
DELETED
|
@@ -1,147 +0,0 @@
|
|
|
1
|
-
import { beforeEach, describe, expect, it, vi } from 'vitest';
|
|
2
|
-
import { convertOptions, dashToCamelCase, extractActionsFromLineOfInput, parseStdIn } from "./cli_utils";
|
|
3
|
-
import { InvalidActionBehavior } from './expand.js';
|
|
4
|
-
import { readStdin } from './stdin';
|
|
5
|
-
vi.mock('./stdin')
|
|
6
|
-
|
|
7
|
-
beforeEach(() => {
|
|
8
|
-
vi.resetAllMocks()
|
|
9
|
-
})
|
|
10
|
-
|
|
11
|
-
const extractScenarios = [
|
|
12
|
-
{input: ' s3:Get* ', expected: ['s3:Get*']},
|
|
13
|
-
{input: ' s3:Get* s3:Put* ', expected: ['s3:Get*', 's3:Put*']},
|
|
14
|
-
{input: ' "s3:Get*", "s3:Put*"', expected: ['s3:Get*', 's3:Put*']},
|
|
15
|
-
{input: ' `s3:Get*`, `s3:Put*`', expected: ['s3:Get*', 's3:Put*']},
|
|
16
|
-
{input: ` 's3:Get*', 's3:Put*'`, expected: ['s3:Get*', 's3:Put*']},
|
|
17
|
-
{input: ` 'resource-Groups:Get*'`, expected: ['resource-Groups:Get*']},
|
|
18
|
-
{input: `s3:Get*, s3:Put*`, expected: ['s3:Get*', 's3:Put*']},
|
|
19
|
-
{input: "s3:Put*", expected: ['s3:Put*']},
|
|
20
|
-
{input: ":s3:Put*", expected: []},
|
|
21
|
-
{input: 'arn:aws:apigateway:*::/apis', expected: []},
|
|
22
|
-
{input: 'hamburger', expected: []},
|
|
23
|
-
]
|
|
24
|
-
|
|
25
|
-
const dashToCamelCaseScenarios = [
|
|
26
|
-
{input: "--distinct", expected: "distinct"},
|
|
27
|
-
{input: "--sort", expected: "sort"},
|
|
28
|
-
{input: "--expand-asterisk", expected: "expandAsterisk"},
|
|
29
|
-
{input: "--expand-service-asterisk", expected: "expandServiceAsterisk"},
|
|
30
|
-
{input: "--error-on-missing-service", expected: "errorOnMissingService"},
|
|
31
|
-
{input: "--error-on-invalid-format", expected: "errorOnInvalidFormat"},
|
|
32
|
-
{input: "--show-data-version", expected: "showDataVersion"},
|
|
33
|
-
]
|
|
34
|
-
|
|
35
|
-
describe('cli_utils', () => {
|
|
36
|
-
describe('extractActionsFromLineOfInput', () => {
|
|
37
|
-
extractScenarios.forEach((scenario, index) => {
|
|
38
|
-
it(`should return for scenario ${index}: ${scenario.input} `, () => {
|
|
39
|
-
// Given the input
|
|
40
|
-
const input = scenario.input
|
|
41
|
-
|
|
42
|
-
// When the actions are extracted
|
|
43
|
-
const result = extractActionsFromLineOfInput(input)
|
|
44
|
-
|
|
45
|
-
// Then I should get the expected result
|
|
46
|
-
expect(result).toEqual(scenario.expected)
|
|
47
|
-
})
|
|
48
|
-
})
|
|
49
|
-
})
|
|
50
|
-
|
|
51
|
-
describe('dashToCamelCase', () => {
|
|
52
|
-
dashToCamelCaseScenarios.forEach((scenario, index) => {
|
|
53
|
-
it(`should return for scenario ${index}: ${scenario.input} `, () => {
|
|
54
|
-
// Given the input
|
|
55
|
-
const input = scenario.input
|
|
56
|
-
|
|
57
|
-
// When the input is converted
|
|
58
|
-
const result = dashToCamelCase(input)
|
|
59
|
-
|
|
60
|
-
// Then I should get the expected result
|
|
61
|
-
expect(result).toEqual(scenario.expected)
|
|
62
|
-
})
|
|
63
|
-
})
|
|
64
|
-
})
|
|
65
|
-
|
|
66
|
-
describe('convertOptions', () => {
|
|
67
|
-
it('should convert the options to keys on an object', () => {
|
|
68
|
-
// Given options as an array of strings
|
|
69
|
-
const optionArgs = ['--distinct', '--sort', '--something-cool', '--key-with-value=10']
|
|
70
|
-
|
|
71
|
-
// When the options are converted
|
|
72
|
-
const result = convertOptions(optionArgs)
|
|
73
|
-
|
|
74
|
-
// Then each option should be a key on the object
|
|
75
|
-
expect(result).toEqual({
|
|
76
|
-
distinct: true,
|
|
77
|
-
sort: true,
|
|
78
|
-
somethingCool: true,
|
|
79
|
-
keyWithValue: "10",
|
|
80
|
-
})
|
|
81
|
-
})
|
|
82
|
-
|
|
83
|
-
it('should convert the invalidActionBehavior to an enum', () => {
|
|
84
|
-
// Given an invalid action behavior option
|
|
85
|
-
const optionArgs = ['--invalid-action-behavior=error']
|
|
86
|
-
|
|
87
|
-
// When the options are converted
|
|
88
|
-
const result = convertOptions(optionArgs)
|
|
89
|
-
|
|
90
|
-
// Then the invalidActionBehavior should be an enum
|
|
91
|
-
expect(result).toEqual({
|
|
92
|
-
invalidActionBehavior: InvalidActionBehavior.Error,
|
|
93
|
-
})
|
|
94
|
-
})
|
|
95
|
-
|
|
96
|
-
it('should remove the invalidActionBehavior if the value is not valid', () => {
|
|
97
|
-
// Given an invalid action behavior option
|
|
98
|
-
const optionArgs = ['--invalid-action-behavior=not-a-real-value']
|
|
99
|
-
|
|
100
|
-
// When the options are converted
|
|
101
|
-
const result = convertOptions(optionArgs)
|
|
102
|
-
|
|
103
|
-
// Then the invalidActionBehavior should be removed
|
|
104
|
-
expect(result).toEqual({})
|
|
105
|
-
})
|
|
106
|
-
})
|
|
107
|
-
|
|
108
|
-
describe('parseStdIn', () => {
|
|
109
|
-
it('should return an empty object if no data is provided', async () => {
|
|
110
|
-
// Given no data is provided
|
|
111
|
-
vi.mocked(readStdin).mockResolvedValue('')
|
|
112
|
-
|
|
113
|
-
// When the actions are parsed
|
|
114
|
-
const result = await parseStdIn({})
|
|
115
|
-
|
|
116
|
-
// Then I should get an empty object
|
|
117
|
-
expect(result).toEqual({})
|
|
118
|
-
})
|
|
119
|
-
|
|
120
|
-
it('should return an array of actions from the data if it cannot be parsed', async () => {
|
|
121
|
-
// Given there is data with actions in multiple lines
|
|
122
|
-
vi.mocked(readStdin).mockResolvedValue('s3:GetObject\ns3:PutObject\ns3:DeleteObject\n')
|
|
123
|
-
|
|
124
|
-
// When the actions are parsed
|
|
125
|
-
const result = await parseStdIn({})
|
|
126
|
-
|
|
127
|
-
// Then I should get the expected actions
|
|
128
|
-
expect(result).toEqual({strings: ['s3:GetObject', 's3:PutObject', 's3:DeleteObject']})
|
|
129
|
-
})
|
|
130
|
-
|
|
131
|
-
it('should return an object if the data can be parsed', async () => {
|
|
132
|
-
// Given there is data that can be parsed
|
|
133
|
-
const dataValue = {
|
|
134
|
-
Action: ["s3:GetObject"],
|
|
135
|
-
Version: "2012-10-17"
|
|
136
|
-
}
|
|
137
|
-
vi.mocked(readStdin).mockResolvedValue(JSON.stringify(dataValue))
|
|
138
|
-
|
|
139
|
-
// When the actions are parsed
|
|
140
|
-
const result = await parseStdIn({})
|
|
141
|
-
|
|
142
|
-
// Then I should get the expected object
|
|
143
|
-
expect(result).toEqual({object: dataValue})
|
|
144
|
-
})
|
|
145
|
-
})
|
|
146
|
-
})
|
|
147
|
-
|
package/src/cli_utils.ts
DELETED
|
@@ -1,84 +0,0 @@
|
|
|
1
|
-
|
|
2
|
-
import { ExpandIamActionsOptions, InvalidActionBehavior } from "./expand.js";
|
|
3
|
-
import { expandJsonDocument } from "./expand_file.js";
|
|
4
|
-
import { readStdin } from "./stdin.js";
|
|
5
|
-
|
|
6
|
-
interface CliOptions extends ExpandIamActionsOptions {
|
|
7
|
-
showDataVersion: boolean
|
|
8
|
-
readWaitTime: string
|
|
9
|
-
}
|
|
10
|
-
|
|
11
|
-
/**
|
|
12
|
-
* Convert a dash-case string to camelCase
|
|
13
|
-
* @param str the string to convert
|
|
14
|
-
* @returns the camelCase string
|
|
15
|
-
*/
|
|
16
|
-
export function dashToCamelCase(str: string): string {
|
|
17
|
-
str = str.substring(2)
|
|
18
|
-
return str.replace(/-([a-z])/g, (g) => g[1].toUpperCase());
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
/**
|
|
22
|
-
* Convert an array of option strings to an object
|
|
23
|
-
*
|
|
24
|
-
* @param optionArgs the array of option strings to convert
|
|
25
|
-
* @returns the object representation of the options
|
|
26
|
-
*/
|
|
27
|
-
export function convertOptions(optionArgs: string[]): Partial<CliOptions> {
|
|
28
|
-
const options: Record<string, string | boolean> = {} ;
|
|
29
|
-
|
|
30
|
-
for(const option of optionArgs) {
|
|
31
|
-
let key: string = option
|
|
32
|
-
let value: boolean | string = true
|
|
33
|
-
if(option.includes('=')) {
|
|
34
|
-
[key,value] = option.split('=')
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
options[dashToCamelCase(key)] = value
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
if(typeof(options.invalidActionBehavior) === 'string') {
|
|
41
|
-
const behaviorString = options.invalidActionBehavior as string
|
|
42
|
-
const cleanedInput = behaviorString.charAt(0).toUpperCase() + behaviorString.slice(1).toLowerCase();
|
|
43
|
-
const behavior = InvalidActionBehavior[cleanedInput as keyof typeof InvalidActionBehavior];
|
|
44
|
-
if(behavior) {
|
|
45
|
-
options.invalidActionBehavior = behavior
|
|
46
|
-
} else {
|
|
47
|
-
delete options['invalidActionBehavior']
|
|
48
|
-
}
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
return options
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
const actionPattern = /\:?([a-zA-Z0-9-]+:[a-zA-Z0-9*]+)/g;
|
|
55
|
-
export function extractActionsFromLineOfInput(line: string): string[] {
|
|
56
|
-
const matches = line.matchAll(actionPattern)
|
|
57
|
-
|
|
58
|
-
return Array.from(matches)
|
|
59
|
-
.filter((match) => !match[0].startsWith('arn:') && !match[0].startsWith(':'))
|
|
60
|
-
.map((match) => match[1])
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
/**
|
|
64
|
-
* Parse the actions from stdin
|
|
65
|
-
*
|
|
66
|
-
* @returns an array of strings from stdin
|
|
67
|
-
*/
|
|
68
|
-
export async function parseStdIn(options: Partial<CliOptions>): Promise<{strings?: string[], object?: any}> {
|
|
69
|
-
const delay = options.readWaitTime ? parseInt(options.readWaitTime.replaceAll(/\D/g, '')) : undefined
|
|
70
|
-
const data = await readStdin(delay)
|
|
71
|
-
if(data.length === 0) {
|
|
72
|
-
return {}
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
try {
|
|
76
|
-
const object = await expandJsonDocument(options, JSON.parse(data))
|
|
77
|
-
return {object}
|
|
78
|
-
} catch (err: any) {}
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
const lines = data.split('\n')
|
|
82
|
-
const actions = lines.flatMap(line => extractActionsFromLineOfInput(line))
|
|
83
|
-
return {strings: actions}
|
|
84
|
-
}
|