@occam-scaly/scaly-cli 0.1.0

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.
@@ -0,0 +1,91 @@
1
+ 'use strict';
2
+
3
+ const api = require('./scaly-api');
4
+
5
+ const LIST_BUILD_SECRETS = `
6
+ query ListAppBuildSecrets($appId: String!) {
7
+ listAppBuildSecrets(appId: $appId) {
8
+ id
9
+ name
10
+ secretArn
11
+ createdAt
12
+ updatedAt
13
+ rotatedAt
14
+ createdByName
15
+ }
16
+ }
17
+ `;
18
+
19
+ const CREATE_BUILD_SECRET = `
20
+ mutation CreateAppBuildSecret($input: CreateAppBuildSecretInput!) {
21
+ createAppBuildSecret(input: $input) {
22
+ id
23
+ name
24
+ secretArn
25
+ createdAt
26
+ updatedAt
27
+ rotatedAt
28
+ createdByName
29
+ }
30
+ }
31
+ `;
32
+
33
+ const UPDATE_BUILD_SECRET = `
34
+ mutation UpdateAppBuildSecret($input: UpdateAppBuildSecretInput!) {
35
+ updateAppBuildSecret(input: $input) {
36
+ id
37
+ name
38
+ secretArn
39
+ createdAt
40
+ updatedAt
41
+ rotatedAt
42
+ createdByName
43
+ }
44
+ }
45
+ `;
46
+
47
+ const DELETE_BUILD_SECRET = `
48
+ mutation DeleteAppBuildSecret($input: DeleteAppBuildSecretInput!) {
49
+ deleteAppBuildSecret(input: $input)
50
+ }
51
+ `;
52
+
53
+ async function listBuildSecrets(appId) {
54
+ const data = await api.graphqlRequest(LIST_BUILD_SECRETS, { appId });
55
+ return data?.listAppBuildSecrets || [];
56
+ }
57
+
58
+ async function setBuildSecret({ appId, name, value }) {
59
+ if (!appId) throw new Error('appId is required');
60
+ if (!name) throw new Error('name is required');
61
+ if (typeof value !== 'string' || value.length === 0) {
62
+ throw new Error('value is required');
63
+ }
64
+
65
+ const existing = await listBuildSecrets(appId);
66
+ const match = existing.find((s) => s.name === name) || null;
67
+
68
+ if (match) {
69
+ const data = await api.graphqlRequest(UPDATE_BUILD_SECRET, {
70
+ input: { id: match.id, value }
71
+ });
72
+ return { action: 'updated', secret: data?.updateAppBuildSecret };
73
+ }
74
+
75
+ const data = await api.graphqlRequest(CREATE_BUILD_SECRET, {
76
+ input: { appId, name, value }
77
+ });
78
+ return { action: 'created', secret: data?.createAppBuildSecret };
79
+ }
80
+
81
+ async function deleteBuildSecret({ id }) {
82
+ if (!id) throw new Error('id is required');
83
+ const data = await api.graphqlRequest(DELETE_BUILD_SECRET, { input: { id } });
84
+ return Boolean(data?.deleteAppBuildSecret);
85
+ }
86
+
87
+ module.exports = {
88
+ listBuildSecrets,
89
+ setBuildSecret,
90
+ deleteBuildSecret
91
+ };
@@ -0,0 +1,45 @@
1
+ 'use strict';
2
+
3
+ const crypto = require('crypto');
4
+
5
+ function isPlainObject(value) {
6
+ if (!value || typeof value !== 'object') return false;
7
+ const proto = Object.getPrototypeOf(value);
8
+ return proto === Object.prototype || proto === null;
9
+ }
10
+
11
+ function stableNormalize(value) {
12
+ if (Array.isArray(value)) {
13
+ return value.map(stableNormalize);
14
+ }
15
+ if (isPlainObject(value)) {
16
+ const out = {};
17
+ const keys = Object.keys(value).sort();
18
+ for (const key of keys) {
19
+ const v = value[key];
20
+ if (typeof v === 'undefined') continue;
21
+ out[key] = stableNormalize(v);
22
+ }
23
+ return out;
24
+ }
25
+ return value;
26
+ }
27
+
28
+ function stableStringify(value) {
29
+ return JSON.stringify(stableNormalize(value));
30
+ }
31
+
32
+ function sha256Hex(input) {
33
+ return crypto.createHash('sha256').update(input).digest('hex');
34
+ }
35
+
36
+ function sha256Prefixed(input) {
37
+ return `sha256:${sha256Hex(input)}`;
38
+ }
39
+
40
+ module.exports = {
41
+ stableNormalize,
42
+ stableStringify,
43
+ sha256Hex,
44
+ sha256Prefixed
45
+ };
package/package.json ADDED
@@ -0,0 +1,27 @@
1
+ {
2
+ "name": "@occam-scaly/scaly-cli",
3
+ "version": "0.1.0",
4
+ "description": "Scaly CLI (auth + MCP helpers)",
5
+ "bin": {
6
+ "scaly": "./bin/scaly-public.js"
7
+ },
8
+ "scripts": {
9
+ "test": "node -c ./bin/scaly-public.js && node -c ./lib/scaly-auth.js"
10
+ },
11
+ "dependencies": {
12
+ "axios": "^1.7.9"
13
+ },
14
+ "engines": {
15
+ "node": ">=18.0.0"
16
+ },
17
+ "license": "MIT",
18
+ "publishConfig": {
19
+ "access": "public"
20
+ },
21
+ "files": [
22
+ "bin",
23
+ "lib",
24
+ "README.md"
25
+ ]
26
+ }
27
+