@mondaydotcomorg/z2h-cli 0.22.0 → 0.23.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.
- package/dist/auth.d.ts +3 -0
- package/dist/auth.d.ts.map +1 -0
- package/dist/auth.js +11 -0
- package/dist/esm/auth.d.ts +3 -0
- package/dist/esm/auth.d.ts.map +1 -0
- package/dist/esm/auth.mjs +2 -0
- package/dist/esm/s3.d.ts +3 -0
- package/dist/esm/s3.d.ts.map +1 -0
- package/dist/esm/s3.mjs +2 -0
- package/dist/esm/util/s3/upload.d.ts +1 -1
- package/dist/esm/util/s3/upload.d.ts.map +1 -1
- package/dist/esm/util/s3/upload.mjs +2 -2
- package/dist/s3.d.ts +3 -0
- package/dist/s3.d.ts.map +1 -0
- package/dist/s3.js +10 -0
- package/dist/util/s3/upload.d.ts +1 -1
- package/dist/util/s3/upload.d.ts.map +1 -1
- package/dist/util/s3/upload.js +2 -2
- package/handler-api/backend-runner/channels/snowflake-channel/run-query.ts +20 -8
- package/package.json +11 -1
- package/src/auth.ts +2 -0
- package/src/s3.ts +2 -0
- package/src/templates/workspace/package.json.tmpl +1 -1
- package/src/util/s3/upload.ts +6 -2
package/dist/auth.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"auth.d.ts","sourceRoot":"","sources":["../src/auth.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,uBAAuB,EAAE,KAAK,uBAAuB,EAAE,MAAM,+BAA+B,CAAC;AACtG,OAAO,EAAE,WAAW,EAAE,mBAAmB,EAAE,aAAa,EAAE,KAAK,OAAO,EAAE,MAAM,wBAAwB,CAAC"}
|
package/dist/auth.js
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
|
|
2
|
+
|
|
3
|
+
const commands_generateZ2hToken = require('./commands/generate-z2h-token.js');
|
|
4
|
+
const util_auth_authStore = require('./util/auth/auth-store.js');
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
exports.generateZ2HTokenCommand = commands_generateZ2hToken.generateZ2HTokenCommand;
|
|
9
|
+
exports.Z2H_AUTH_FILE = util_auth_authStore.Z2H_AUTH_FILE;
|
|
10
|
+
exports.Z2hAuthMissingError = util_auth_authStore.Z2hAuthMissingError;
|
|
11
|
+
exports.readZthAuth = util_auth_authStore.readZthAuth;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"auth.d.ts","sourceRoot":"","sources":["../../src/auth.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,uBAAuB,EAAE,KAAK,uBAAuB,EAAE,MAAM,+BAA+B,CAAC;AACtG,OAAO,EAAE,WAAW,EAAE,mBAAmB,EAAE,aAAa,EAAE,KAAK,OAAO,EAAE,MAAM,wBAAwB,CAAC"}
|
package/dist/esm/s3.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"s3.d.ts","sourceRoot":"","sources":["../../src/s3.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAC9D,OAAO,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC"}
|
package/dist/esm/s3.mjs
ADDED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
export declare function uploadDir(localDir: string, keyPrefix: string): Promise<string[]>;
|
|
1
|
+
export declare function uploadDir(localDir: string, keyPrefix: string, bucket?: string): Promise<string[]>;
|
|
2
2
|
//# sourceMappingURL=upload.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"upload.d.ts","sourceRoot":"","sources":["../../../../src/util/s3/upload.ts"],"names":[],"mappings":"AAeA,wBAAsB,SAAS,
|
|
1
|
+
{"version":3,"file":"upload.d.ts","sourceRoot":"","sources":["../../../../src/util/s3/upload.ts"],"names":[],"mappings":"AAeA,wBAAsB,SAAS,CAC7B,QAAQ,EAAE,MAAM,EAChB,SAAS,EAAE,MAAM,EACjB,MAAM,GAAE,MAA0B,GACjC,OAAO,CAAC,MAAM,EAAE,CAAC,CA0BnB"}
|
|
@@ -11,7 +11,7 @@ import { getS3Client } from './client.mjs';
|
|
|
11
11
|
// the URL itself is the cache key. Assets never need to be revalidated.
|
|
12
12
|
const FOREVER = 'public, immutable';
|
|
13
13
|
const UPLOAD_CONCURRENCY = 5;
|
|
14
|
-
async function uploadDir(localDir, keyPrefix) {
|
|
14
|
+
async function uploadDir(localDir, keyPrefix, bucket = BUCKET_WRITE_NAME) {
|
|
15
15
|
const entries = await readdir(localDir, { recursive: true, withFileTypes: true });
|
|
16
16
|
const files = entries.filter(e => e.isFile()).map(e => path.relative(localDir, path.join(e.parentPath, e.name)));
|
|
17
17
|
const s3 = getS3Client();
|
|
@@ -20,7 +20,7 @@ async function uploadDir(localDir, keyPrefix) {
|
|
|
20
20
|
const contentType = lookup(rel) || 'application/octet-stream';
|
|
21
21
|
const key = `${keyPrefix}/${rel.split(path.sep).join('/')}`;
|
|
22
22
|
await s3.send(new PutObjectCommand({
|
|
23
|
-
Bucket:
|
|
23
|
+
Bucket: bucket,
|
|
24
24
|
Key: key,
|
|
25
25
|
Body: body,
|
|
26
26
|
ContentType: contentType,
|
package/dist/s3.d.ts
ADDED
package/dist/s3.d.ts.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"s3.d.ts","sourceRoot":"","sources":["../src/s3.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAC9D,OAAO,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC"}
|
package/dist/s3.js
ADDED
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
|
|
2
|
+
|
|
3
|
+
const util_s3_client = require('./util/s3/client.js');
|
|
4
|
+
const util_s3_upload = require('./util/s3/upload.js');
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
exports.getS3Client = util_s3_client.getS3Client;
|
|
9
|
+
exports.setupS3Client = util_s3_client.setupS3Client;
|
|
10
|
+
exports.uploadDir = util_s3_upload.uploadDir;
|
package/dist/util/s3/upload.d.ts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
export declare function uploadDir(localDir: string, keyPrefix: string): Promise<string[]>;
|
|
1
|
+
export declare function uploadDir(localDir: string, keyPrefix: string, bucket?: string): Promise<string[]>;
|
|
2
2
|
//# sourceMappingURL=upload.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"upload.d.ts","sourceRoot":"","sources":["../../../src/util/s3/upload.ts"],"names":[],"mappings":"AAeA,wBAAsB,SAAS,
|
|
1
|
+
{"version":3,"file":"upload.d.ts","sourceRoot":"","sources":["../../../src/util/s3/upload.ts"],"names":[],"mappings":"AAeA,wBAAsB,SAAS,CAC7B,QAAQ,EAAE,MAAM,EAChB,SAAS,EAAE,MAAM,EACjB,MAAM,GAAE,MAA0B,GACjC,OAAO,CAAC,MAAM,EAAE,CAAC,CA0BnB"}
|
package/dist/util/s3/upload.js
CHANGED
|
@@ -18,7 +18,7 @@ const pMap__default = /*#__PURE__*/_interopDefault(pMap);
|
|
|
18
18
|
// the URL itself is the cache key. Assets never need to be revalidated.
|
|
19
19
|
const FOREVER = 'public, immutable';
|
|
20
20
|
const UPLOAD_CONCURRENCY = 5;
|
|
21
|
-
async function uploadDir(localDir, keyPrefix) {
|
|
21
|
+
async function uploadDir(localDir, keyPrefix, bucket = constants.BUCKET_WRITE_NAME) {
|
|
22
22
|
const entries = await promises.readdir(localDir, { recursive: true, withFileTypes: true });
|
|
23
23
|
const files = entries.filter(e => e.isFile()).map(e => path__default.default.relative(localDir, path__default.default.join(e.parentPath, e.name)));
|
|
24
24
|
const s3 = util_s3_client.getS3Client();
|
|
@@ -27,7 +27,7 @@ async function uploadDir(localDir, keyPrefix) {
|
|
|
27
27
|
const contentType = mimeTypes.lookup(rel) || 'application/octet-stream';
|
|
28
28
|
const key = `${keyPrefix}/${rel.split(path__default.default.sep).join('/')}`;
|
|
29
29
|
await s3.send(new clientS3.PutObjectCommand({
|
|
30
|
-
Bucket:
|
|
30
|
+
Bucket: bucket,
|
|
31
31
|
Key: key,
|
|
32
32
|
Body: body,
|
|
33
33
|
ContentType: contentType,
|
|
@@ -32,6 +32,15 @@ function hashQuery(boundSql: string, params: Record<string, SnowflakeParamValue>
|
|
|
32
32
|
return createHash('sha256').update(boundSql).update('|').update(JSON.stringify(sorted)).digest('hex').slice(0, 16);
|
|
33
33
|
}
|
|
34
34
|
|
|
35
|
+
/**
|
|
36
|
+
* Hashes the *unbound* SQL so one logical query keeps one identifier whatever its parameters are.
|
|
37
|
+
* Must agree with bigbrain-zth's `hashQueryShape`, or the same query buckets differently
|
|
38
|
+
* depending on which service ran it.
|
|
39
|
+
*/
|
|
40
|
+
function hashQueryShape(rawSql: string): string {
|
|
41
|
+
return createHash('sha256').update(rawSql.replace(/\s+/g, ' ').trim()).digest('hex').slice(0, 16);
|
|
42
|
+
}
|
|
43
|
+
|
|
35
44
|
/**
|
|
36
45
|
* The permissions-aware pool returns different rows to different people, so the
|
|
37
46
|
* cache key has to carry whatever decides that — the caller's roles and user
|
|
@@ -118,16 +127,18 @@ export async function runSnowflakeQuery(
|
|
|
118
127
|
);
|
|
119
128
|
}
|
|
120
129
|
|
|
121
|
-
|
|
130
|
+
// Cache key stays parameter-sensitive; the pool identifier deliberately is not.
|
|
131
|
+
const queryCacheKey = hashQuery(boundSql, params ?? {});
|
|
132
|
+
const queryIdentifier = hashQueryShape(sql);
|
|
122
133
|
const scope = cacheScope(useStateless);
|
|
123
|
-
const cached = scope ? await readCache(
|
|
134
|
+
const cached = scope ? await readCache(queryCacheKey, scope) : null;
|
|
124
135
|
if (cached) {
|
|
125
136
|
return cached;
|
|
126
137
|
}
|
|
127
138
|
|
|
128
139
|
const queryOptions = {
|
|
129
140
|
query: boundSql,
|
|
130
|
-
identifier: `z2h-query:${
|
|
141
|
+
identifier: `z2h-query:${queryIdentifier}`,
|
|
131
142
|
fallback: [] as SnowflakeRow[],
|
|
132
143
|
timeoutInMs,
|
|
133
144
|
convertToSingularResult: false,
|
|
@@ -157,7 +168,7 @@ export async function runSnowflakeQuery(
|
|
|
157
168
|
}
|
|
158
169
|
const rows = Array.isArray(data) ? data : [];
|
|
159
170
|
if (scope) {
|
|
160
|
-
await writeCache(
|
|
171
|
+
await writeCache(queryCacheKey, scope, rows);
|
|
161
172
|
}
|
|
162
173
|
return rows;
|
|
163
174
|
}
|
|
@@ -167,9 +178,10 @@ export async function runSnowflakeQuery(
|
|
|
167
178
|
* correctness, so a failure here falls through to the warehouse rather than
|
|
168
179
|
* failing the handler's query. Compressed, as bigbrain-zth stores the same rows.
|
|
169
180
|
*/
|
|
170
|
-
|
|
181
|
+
/** `queryHash` is pinned: it is in this pattern's `patternVariableKeys`, so it is Redis key material. */
|
|
182
|
+
async function readCache(queryCacheKey: string, scope: string): Promise<SnowflakeRow[] | null> {
|
|
171
183
|
try {
|
|
172
|
-
const hit = await getDefaultClient().getCompressed(CACHE_PATTERN, { queryHash, scope });
|
|
184
|
+
const hit = await getDefaultClient().getCompressed(CACHE_PATTERN, { queryHash: queryCacheKey, scope });
|
|
173
185
|
return hit ? (JSON.parse(hit.toString()) as SnowflakeRow[]) : null;
|
|
174
186
|
} catch (err) {
|
|
175
187
|
logger.warn({ tag: 'z2h-snowflake', error: err instanceof Error ? err.message : String(err) }, 'cache read failed');
|
|
@@ -177,9 +189,9 @@ async function readCache(queryHash: string, scope: string): Promise<SnowflakeRow
|
|
|
177
189
|
}
|
|
178
190
|
}
|
|
179
191
|
|
|
180
|
-
async function writeCache(
|
|
192
|
+
async function writeCache(queryCacheKey: string, scope: string, rows: SnowflakeRow[]): Promise<void> {
|
|
181
193
|
try {
|
|
182
|
-
await getDefaultClient().setCompressed(CACHE_PATTERN, { queryHash, scope }, JSON.stringify(rows));
|
|
194
|
+
await getDefaultClient().setCompressed(CACHE_PATTERN, { queryHash: queryCacheKey, scope }, JSON.stringify(rows));
|
|
183
195
|
} catch (err) {
|
|
184
196
|
logger.warn(
|
|
185
197
|
{ tag: 'z2h-snowflake', error: err instanceof Error ? err.message : String(err) },
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@mondaydotcomorg/z2h-cli",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.23.0",
|
|
4
4
|
"bin": "./bin/z2h-cli.js",
|
|
5
5
|
"main": "./dist/index.js",
|
|
6
6
|
"types": "./dist/index.d.ts",
|
|
@@ -15,6 +15,16 @@
|
|
|
15
15
|
"require": "./dist/constants.js",
|
|
16
16
|
"types": "./dist/constants.d.ts"
|
|
17
17
|
},
|
|
18
|
+
"./auth": {
|
|
19
|
+
"import": "./dist/esm/auth.mjs",
|
|
20
|
+
"require": "./dist/auth.js",
|
|
21
|
+
"types": "./dist/auth.d.ts"
|
|
22
|
+
},
|
|
23
|
+
"./s3": {
|
|
24
|
+
"import": "./dist/esm/s3.mjs",
|
|
25
|
+
"require": "./dist/s3.js",
|
|
26
|
+
"types": "./dist/s3.d.ts"
|
|
27
|
+
},
|
|
18
28
|
"./package.json": "./package.json"
|
|
19
29
|
},
|
|
20
30
|
"nx": {
|
package/src/auth.ts
ADDED
package/src/s3.ts
ADDED
package/src/util/s3/upload.ts
CHANGED
|
@@ -13,7 +13,11 @@ const FOREVER = 'public, immutable';
|
|
|
13
13
|
|
|
14
14
|
const UPLOAD_CONCURRENCY = 5;
|
|
15
15
|
|
|
16
|
-
export async function uploadDir(
|
|
16
|
+
export async function uploadDir(
|
|
17
|
+
localDir: string,
|
|
18
|
+
keyPrefix: string,
|
|
19
|
+
bucket: string = BUCKET_WRITE_NAME
|
|
20
|
+
): Promise<string[]> {
|
|
17
21
|
const entries = await readdir(localDir, { recursive: true, withFileTypes: true });
|
|
18
22
|
const files = entries.filter(e => e.isFile()).map(e => path.relative(localDir, path.join(e.parentPath, e.name)));
|
|
19
23
|
|
|
@@ -27,7 +31,7 @@ export async function uploadDir(localDir: string, keyPrefix: string): Promise<st
|
|
|
27
31
|
const key = `${keyPrefix}/${rel.split(path.sep).join('/')}`;
|
|
28
32
|
await s3.send(
|
|
29
33
|
new PutObjectCommand({
|
|
30
|
-
Bucket:
|
|
34
|
+
Bucket: bucket,
|
|
31
35
|
Key: key,
|
|
32
36
|
Body: body,
|
|
33
37
|
ContentType: contentType,
|