@townco/secret 0.1.0 → 0.1.3
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/dist/env-file.d.ts +98 -96
- package/dist/env-file.js +199 -199
- package/dist/index.d.ts +8 -5
- package/dist/index.js +114 -107
- package/dist/onepassword.d.ts +98 -92
- package/dist/onepassword.js +197 -197
- package/package.json +2 -3
package/dist/onepassword.js
CHANGED
|
@@ -3,201 +3,201 @@
|
|
|
3
3
|
* methods to detect changes and generate appropriate `op` CLI commands.
|
|
4
4
|
*/
|
|
5
5
|
export class OnePassword {
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
6
|
+
vault;
|
|
7
|
+
item;
|
|
8
|
+
fields;
|
|
9
|
+
originalFields;
|
|
10
|
+
constructor(vault, item, fields = new Map()) {
|
|
11
|
+
this.vault = vault;
|
|
12
|
+
this.item = item;
|
|
13
|
+
this.fields = new Map(fields);
|
|
14
|
+
this.originalFields = new Map(fields);
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* Create an OpItem from a 1Password FullItem JSON response
|
|
18
|
+
*/
|
|
19
|
+
static fromFullItem(vault, itemName, fullItem) {
|
|
20
|
+
const fields = new Map();
|
|
21
|
+
if (fullItem.fields) {
|
|
22
|
+
for (const field of fullItem.fields) {
|
|
23
|
+
if (field.label && field.value) {
|
|
24
|
+
fields.set(field.label, field.value);
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
return new OnePassword(vault, itemName, fields);
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* Fetch an OpItem from 1Password using the CLI
|
|
32
|
+
*/
|
|
33
|
+
static async fetch(vault, item) {
|
|
34
|
+
try {
|
|
35
|
+
const proc = Bun.spawn([
|
|
36
|
+
"op",
|
|
37
|
+
"--format=json",
|
|
38
|
+
"item",
|
|
39
|
+
"get",
|
|
40
|
+
"--vault",
|
|
41
|
+
vault,
|
|
42
|
+
item,
|
|
43
|
+
]);
|
|
44
|
+
const output = await new Response(proc.stdout).text();
|
|
45
|
+
await proc.exited;
|
|
46
|
+
const fullItem = JSON.parse(output);
|
|
47
|
+
return OnePassword.fromFullItem(vault, item, fullItem);
|
|
48
|
+
} catch (error) {
|
|
49
|
+
throw new Error(
|
|
50
|
+
`Failed to fetch item '${item}' from vault '${vault}': ${error}`,
|
|
51
|
+
);
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
/**
|
|
55
|
+
* Sign in to 1Password CLI
|
|
56
|
+
*/
|
|
57
|
+
static async signin() {
|
|
58
|
+
await Bun.spawn(["op", "signin"]).exited;
|
|
59
|
+
}
|
|
60
|
+
/**
|
|
61
|
+
* Get a field value
|
|
62
|
+
*/
|
|
63
|
+
get(key) {
|
|
64
|
+
return this.fields.get(key);
|
|
65
|
+
}
|
|
66
|
+
/**
|
|
67
|
+
* Set a field value (marks as changed)
|
|
68
|
+
*/
|
|
69
|
+
set(key, value) {
|
|
70
|
+
this.fields.set(key, value);
|
|
71
|
+
return this;
|
|
72
|
+
}
|
|
73
|
+
/**
|
|
74
|
+
* Delete a field (marks as deleted)
|
|
75
|
+
*/
|
|
76
|
+
delete(key) {
|
|
77
|
+
this.fields.delete(key);
|
|
78
|
+
return this;
|
|
79
|
+
}
|
|
80
|
+
/**
|
|
81
|
+
* Check if a field exists
|
|
82
|
+
*/
|
|
83
|
+
has(key) {
|
|
84
|
+
return this.fields.has(key);
|
|
85
|
+
}
|
|
86
|
+
/**
|
|
87
|
+
* Get all field keys
|
|
88
|
+
*/
|
|
89
|
+
keys() {
|
|
90
|
+
return Array.from(this.fields.keys());
|
|
91
|
+
}
|
|
92
|
+
/**
|
|
93
|
+
* Get all fields as a record
|
|
94
|
+
*/
|
|
95
|
+
toRecord() {
|
|
96
|
+
return Object.fromEntries(this.fields);
|
|
97
|
+
}
|
|
98
|
+
/**
|
|
99
|
+
* Get all field entries
|
|
100
|
+
*/
|
|
101
|
+
entries() {
|
|
102
|
+
return this.fields.entries();
|
|
103
|
+
}
|
|
104
|
+
/**
|
|
105
|
+
* Build an op:// reference for a field
|
|
106
|
+
*/
|
|
107
|
+
getReference(key) {
|
|
108
|
+
return `op://${this.vault}/${this.item}/${key}`;
|
|
109
|
+
}
|
|
110
|
+
/**
|
|
111
|
+
* Detect changes between original and current state
|
|
112
|
+
*/
|
|
113
|
+
detectChanges() {
|
|
114
|
+
const changes = [];
|
|
115
|
+
// Check for deletions
|
|
116
|
+
for (const key of this.originalFields.keys()) {
|
|
117
|
+
if (!this.fields.has(key)) {
|
|
118
|
+
changes.push({ type: "delete", key });
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
// Check for additions and updates
|
|
122
|
+
for (const [key, value] of this.fields.entries()) {
|
|
123
|
+
const originalValue = this.originalFields.get(key);
|
|
124
|
+
if (originalValue === undefined) {
|
|
125
|
+
changes.push({ type: "add", key, value });
|
|
126
|
+
} else if (originalValue !== value) {
|
|
127
|
+
changes.push({ type: "update", key, value });
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
return changes;
|
|
131
|
+
}
|
|
132
|
+
/**
|
|
133
|
+
* Generate op CLI arguments for a single change
|
|
134
|
+
*/
|
|
135
|
+
buildEditArgs(change) {
|
|
136
|
+
switch (change.type) {
|
|
137
|
+
case "add":
|
|
138
|
+
case "update":
|
|
139
|
+
return [`${change.key}[password]=${change.value}`];
|
|
140
|
+
case "delete":
|
|
141
|
+
return [`${change.key}[delete]`];
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
/**
|
|
145
|
+
* Apply all changes to 1Password using the op CLI
|
|
146
|
+
* Returns the number of changes applied
|
|
147
|
+
*/
|
|
148
|
+
async sync() {
|
|
149
|
+
const changes = this.detectChanges();
|
|
150
|
+
if (changes.length === 0) {
|
|
151
|
+
return 0;
|
|
152
|
+
}
|
|
153
|
+
// Build all edit arguments
|
|
154
|
+
const editArgs = changes.flatMap((change) => this.buildEditArgs(change));
|
|
155
|
+
// Execute a single op item edit command with all changes
|
|
156
|
+
await Bun.spawn([
|
|
157
|
+
"op",
|
|
158
|
+
"item",
|
|
159
|
+
"edit",
|
|
160
|
+
this.item,
|
|
161
|
+
"--vault",
|
|
162
|
+
this.vault,
|
|
163
|
+
...editArgs,
|
|
164
|
+
]).exited;
|
|
165
|
+
// Update originalFields to match current state
|
|
166
|
+
this.originalFields = new Map(this.fields);
|
|
167
|
+
return changes.length;
|
|
168
|
+
}
|
|
169
|
+
/**
|
|
170
|
+
* Inject secrets from a template file to an output file
|
|
171
|
+
* This resolves op:// references to actual values
|
|
172
|
+
*/
|
|
173
|
+
static async inject(inputPath, outputPath) {
|
|
174
|
+
await Bun.spawn([
|
|
175
|
+
"op",
|
|
176
|
+
"inject",
|
|
177
|
+
"-i",
|
|
178
|
+
inputPath,
|
|
179
|
+
"-o",
|
|
180
|
+
outputPath,
|
|
181
|
+
"--force",
|
|
182
|
+
]).exited;
|
|
183
|
+
}
|
|
184
|
+
/**
|
|
185
|
+
* Create a clone of this OpItem
|
|
186
|
+
*/
|
|
187
|
+
clone() {
|
|
188
|
+
return new OnePassword(this.vault, this.item, new Map(this.fields));
|
|
189
|
+
}
|
|
190
|
+
/**
|
|
191
|
+
* Reset to original state (discard changes)
|
|
192
|
+
*/
|
|
193
|
+
reset() {
|
|
194
|
+
this.fields = new Map(this.originalFields);
|
|
195
|
+
return this;
|
|
196
|
+
}
|
|
197
|
+
/**
|
|
198
|
+
* Check if there are unsaved changes
|
|
199
|
+
*/
|
|
200
|
+
hasChanges() {
|
|
201
|
+
return this.detectChanges().length > 0;
|
|
202
|
+
}
|
|
203
203
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@townco/secret",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.3",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"main": "./dist/index.js",
|
|
6
6
|
"types": "./dist/index.d.ts",
|
|
@@ -12,7 +12,6 @@
|
|
|
12
12
|
"type": "git",
|
|
13
13
|
"url": "git+https://github.com/federicoweber/agent_hub.git"
|
|
14
14
|
},
|
|
15
|
-
"author": "Federico Weber",
|
|
16
15
|
"exports": {
|
|
17
16
|
".": {
|
|
18
17
|
"import": "./dist/index.js",
|
|
@@ -27,7 +26,7 @@
|
|
|
27
26
|
"@1password/connect": "^1.4.2"
|
|
28
27
|
},
|
|
29
28
|
"devDependencies": {
|
|
30
|
-
"@townco/tsconfig": "
|
|
29
|
+
"@townco/tsconfig": "workspace:*",
|
|
31
30
|
"@types/bun": "^1.3.1"
|
|
32
31
|
}
|
|
33
32
|
}
|