@geniee-inc/sfa-kit 1.18.0 → 1.19.2
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/GUIDE.md +35 -15
- package/package.json +1 -1
- package/src/bin/sfa-kit-bundle.js +16 -8
- package/src/bundle.d.ts +1 -2
- package/src/lib/auth/DevToolbar.js +3 -6
- package/src/lib/auth/SfaLoginGate.js +17 -8
- package/src/lib/auth/StandalonePreviewContext.d.ts +3 -3
- package/src/lib/auth/StandalonePreviewContext.js +1 -1
- package/src/lib/auth/useEmbedContext.d.ts +3 -1
- package/src/lib/auth/useEmbedContext.js +3 -1
- package/src/lib/bundle/build-static-bundle.d.ts +37 -11
- package/src/lib/bundle/build-static-bundle.js +75 -35
- package/src/lib/bundle/request-signature.d.ts +13 -1
- package/src/lib/bundle/request-signature.js +21 -6
- package/src/lib/components/FieldRenderer.d.ts +2 -1
- package/src/lib/components/FieldRenderer.js +32 -19
- package/src/lib/components/RecordList.js +32 -4
- package/src/lib/components/RecordView.js +27 -7
- package/src/lib/components/fieldDisplayText.d.ts +11 -0
- package/src/lib/components/fieldDisplayText.js +51 -0
- package/src/lib/hooks/useFieldTypes.d.ts +5 -0
- package/src/lib/hooks/useFieldTypes.js +5 -0
- package/src/lib/hooks/useObjectCatalog.d.ts +6 -0
- package/src/lib/hooks/useObjectCatalog.js +6 -0
- package/src/lib/hooks/useRecord.d.ts +20 -0
- package/src/lib/hooks/useRecord.js +53 -0
- package/src/lib/hooks/useRecordList.d.ts +7 -1
- package/src/lib/hooks/useRecordList.js +3 -3
- package/src/lib/hooks/useRelatedRecords.d.ts +5 -1
- package/src/lib/provider/SfaClient.js +13 -8
- package/src/lib/provider/types.d.ts +7 -1
- package/src/lib/signing/compute-signature.d.ts +4 -2
- package/src/lib/signing/compute-signature.js +4 -2
- package/src/lib/signing/create-manifest.d.ts +8 -6
- package/src/lib/signing/create-manifest.js +8 -6
- package/src/lib/signing/index.d.ts +1 -1
- package/src/lib/signing/types.d.ts +33 -4
- package/src/lib/version.d.ts +1 -1
- package/src/lib/version.js +1 -1
- package/src/signing.d.ts +2 -2
|
@@ -132,7 +132,7 @@ export class SfaClient {
|
|
|
132
132
|
}
|
|
133
133
|
const path = `/v1/objects/${enc(collection)}/records/query`;
|
|
134
134
|
const raw = yield this.postJson(path, body);
|
|
135
|
-
return normalizeKeystoneListResponse(raw, pageIndex
|
|
135
|
+
return normalizeKeystoneListResponse(raw, pageIndex);
|
|
136
136
|
}
|
|
137
137
|
const query = new URLSearchParams();
|
|
138
138
|
if ((params === null || params === void 0 ? void 0 : params.limit) != null)
|
|
@@ -660,7 +660,7 @@ function inferScalarKind(value) {
|
|
|
660
660
|
}
|
|
661
661
|
return 'text';
|
|
662
662
|
}
|
|
663
|
-
function normalizeKeystoneListResponse(raw, pageIndex
|
|
663
|
+
function normalizeKeystoneListResponse(raw, pageIndex) {
|
|
664
664
|
var _a, _b, _c;
|
|
665
665
|
const data = raw;
|
|
666
666
|
const rawRecords = (_a = data['records']) !== null && _a !== void 0 ? _a : [];
|
|
@@ -668,12 +668,17 @@ function normalizeKeystoneListResponse(raw, pageIndex, pageSize) {
|
|
|
668
668
|
const nextCursor = (_b = data['next_cursor']) !== null && _b !== void 0 ? _b : null;
|
|
669
669
|
const prevCursor = (_c = data['prev_cursor']) !== null && _c !== void 0 ? _c : null;
|
|
670
670
|
const hasMore = nextCursor != null;
|
|
671
|
-
// Keystone
|
|
672
|
-
//
|
|
673
|
-
|
|
674
|
-
|
|
675
|
-
|
|
676
|
-
|
|
671
|
+
// NOTE: Keystone pages with cursors and returns no total count. Report it as
|
|
672
|
+
// unknown rather than estimating one: an estimate reads as the real total
|
|
673
|
+
// ("21 records" for 500). Whether another page exists comes from hasMore
|
|
674
|
+
return {
|
|
675
|
+
items,
|
|
676
|
+
totalCount: null,
|
|
677
|
+
hasMore,
|
|
678
|
+
pageIndex,
|
|
679
|
+
nextCursor,
|
|
680
|
+
prevCursor,
|
|
681
|
+
};
|
|
677
682
|
}
|
|
678
683
|
// ── Legacy Chikyu normalization (proxy mode) ──
|
|
679
684
|
const CHIKYU_KIND_MAP = {
|
|
@@ -53,7 +53,13 @@ export interface SfaRecord {
|
|
|
53
53
|
}
|
|
54
54
|
export interface SfaListResponse {
|
|
55
55
|
readonly items: readonly SfaRecord[];
|
|
56
|
-
|
|
56
|
+
/**
|
|
57
|
+
* Records across all pages, or null when the backend does not report it.
|
|
58
|
+
*
|
|
59
|
+
* NOTE: Keystone pages with cursors and returns no total, so it is null in
|
|
60
|
+
* direct mode. Use `hasMore` to tell whether another page exists
|
|
61
|
+
*/
|
|
62
|
+
readonly totalCount: number | null;
|
|
57
63
|
readonly hasMore: boolean;
|
|
58
64
|
readonly pageIndex: number;
|
|
59
65
|
/** Cursor for fetching the next page (keystone cursor-based pagination). */
|
|
@@ -2,7 +2,9 @@
|
|
|
2
2
|
* Computes the HMAC-SHA-256 bundle signature matching Keystone's
|
|
3
3
|
* BundleSignatureVerifier.
|
|
4
4
|
*
|
|
5
|
-
* Signs the message `"{studioVersion}:{contentHash}"` with the given key.
|
|
5
|
+
* Signs the message `"{studioVersion}:{contentHash}"` with the given key. This
|
|
6
|
+
* is the legacy format; a manifest without `studio_version` is checked
|
|
7
|
+
* against `contentHash` alone (see `ContentHashManifest`).
|
|
6
8
|
*
|
|
7
9
|
* **The signing key lives only in Keystone (`KEYSTONE_STUDIO__SIGNING_KEY`),
|
|
8
10
|
* so a page build cannot call this.** Deploying the key to Studio as well was
|
|
@@ -13,7 +15,7 @@
|
|
|
13
15
|
* ```ts
|
|
14
16
|
* const files = await readBundleFiles('dist');
|
|
15
17
|
* const contentHash = computeContentHash(files);
|
|
16
|
-
* // POST /v1/pages/sign {
|
|
18
|
+
* // POST /v1/pages/sign { content_hash } -> { signature }
|
|
17
19
|
* ```
|
|
18
20
|
*
|
|
19
21
|
* Reach for this only from a service that legitimately holds the key. Signing
|
|
@@ -3,7 +3,9 @@ import { createHmac } from 'node:crypto';
|
|
|
3
3
|
* Computes the HMAC-SHA-256 bundle signature matching Keystone's
|
|
4
4
|
* BundleSignatureVerifier.
|
|
5
5
|
*
|
|
6
|
-
* Signs the message `"{studioVersion}:{contentHash}"` with the given key.
|
|
6
|
+
* Signs the message `"{studioVersion}:{contentHash}"` with the given key. This
|
|
7
|
+
* is the legacy format; a manifest without `studio_version` is checked
|
|
8
|
+
* against `contentHash` alone (see `ContentHashManifest`).
|
|
7
9
|
*
|
|
8
10
|
* **The signing key lives only in Keystone (`KEYSTONE_STUDIO__SIGNING_KEY`),
|
|
9
11
|
* so a page build cannot call this.** Deploying the key to Studio as well was
|
|
@@ -14,7 +16,7 @@ import { createHmac } from 'node:crypto';
|
|
|
14
16
|
* ```ts
|
|
15
17
|
* const files = await readBundleFiles('dist');
|
|
16
18
|
* const contentHash = computeContentHash(files);
|
|
17
|
-
* // POST /v1/pages/sign {
|
|
19
|
+
* // POST /v1/pages/sign { content_hash } -> { signature }
|
|
18
20
|
* ```
|
|
19
21
|
*
|
|
20
22
|
* Reach for this only from a service that legitimately holds the key. Signing
|
|
@@ -2,15 +2,17 @@ import type { BundleManifest, FileEntry } from './types.js';
|
|
|
2
2
|
/**
|
|
3
3
|
* Creates a signed {@link BundleManifest} from a list of bundle files.
|
|
4
4
|
*
|
|
5
|
-
* Returns the three fields
|
|
6
|
-
* Callers can spread decorative fields
|
|
7
|
-
*
|
|
5
|
+
* Returns the three fields of the legacy format, signed over
|
|
6
|
+
* `"{studio_version}:{content_hash}"`. Callers can spread decorative fields
|
|
7
|
+
* (e.g. `name`, `displayName`) on top before writing to disk.
|
|
8
8
|
*
|
|
9
9
|
* **Requires the shared signing key, which page builds do not have** — see
|
|
10
10
|
* {@link computeSignature}. A page build computes `content_hash` with
|
|
11
|
-
* {@link computeContentHash}
|
|
12
|
-
* `POST /v1/pages/sign`,
|
|
13
|
-
*
|
|
11
|
+
* {@link computeContentHash}, posts it alone to Keystone's
|
|
12
|
+
* `POST /v1/pages/sign`, and writes the current format, a
|
|
13
|
+
* `ContentHashManifest` (see GUIDE.md). It does not write `studio_version`:
|
|
14
|
+
* Keystone checks a manifest carrying one in this legacy format, so a signature
|
|
15
|
+
* over `content_hash` alone would not verify.
|
|
14
16
|
*
|
|
15
17
|
* @param studioVersion - Studio version stored as page metadata.
|
|
16
18
|
* @param files - All files in the bundle (manifest.json is automatically excluded).
|
|
@@ -3,15 +3,17 @@ import { computeSignature } from './compute-signature.js';
|
|
|
3
3
|
/**
|
|
4
4
|
* Creates a signed {@link BundleManifest} from a list of bundle files.
|
|
5
5
|
*
|
|
6
|
-
* Returns the three fields
|
|
7
|
-
* Callers can spread decorative fields
|
|
8
|
-
*
|
|
6
|
+
* Returns the three fields of the legacy format, signed over
|
|
7
|
+
* `"{studio_version}:{content_hash}"`. Callers can spread decorative fields
|
|
8
|
+
* (e.g. `name`, `displayName`) on top before writing to disk.
|
|
9
9
|
*
|
|
10
10
|
* **Requires the shared signing key, which page builds do not have** — see
|
|
11
11
|
* {@link computeSignature}. A page build computes `content_hash` with
|
|
12
|
-
* {@link computeContentHash}
|
|
13
|
-
* `POST /v1/pages/sign`,
|
|
14
|
-
*
|
|
12
|
+
* {@link computeContentHash}, posts it alone to Keystone's
|
|
13
|
+
* `POST /v1/pages/sign`, and writes the current format, a
|
|
14
|
+
* `ContentHashManifest` (see GUIDE.md). It does not write `studio_version`:
|
|
15
|
+
* Keystone checks a manifest carrying one in this legacy format, so a signature
|
|
16
|
+
* over `content_hash` alone would not verify.
|
|
15
17
|
*
|
|
16
18
|
* @param studioVersion - Studio version stored as page metadata.
|
|
17
19
|
* @param files - All files in the bundle (manifest.json is automatically excluded).
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export type { BundleManifest, FileEntry } from './types.js';
|
|
1
|
+
export type { BundleManifest, FileEntry, ContentHashManifest, } from './types.js';
|
|
2
2
|
export { computeContentHash } from './compute-content-hash.js';
|
|
3
3
|
export { readBundleFiles } from './read-bundle-files.js';
|
|
4
4
|
export { computeSignature } from './compute-signature.js';
|
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* The
|
|
3
|
-
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
2
|
+
* The legacy manifest format: the signature covers
|
|
3
|
+
* `"{studio_version}:{content_hash}"`. Keystone still accepts it, and
|
|
4
|
+
* {@link createManifest} and `buildStaticBundle` given a `studioVersion` still
|
|
5
|
+
* produce it. Callers can spread decorative fields on top before writing to
|
|
6
|
+
* disk (e.g. `name`, `displayName`, `entry`).
|
|
6
7
|
*/
|
|
7
8
|
export interface BundleManifest {
|
|
8
9
|
/** Studio version string (the build version, not the sfa-kit npm version). */
|
|
@@ -12,6 +13,34 @@ export interface BundleManifest {
|
|
|
12
13
|
/** HMAC-SHA-256 hex of `"{studio_version}:{content_hash}"`. */
|
|
13
14
|
signature: string;
|
|
14
15
|
}
|
|
16
|
+
/**
|
|
17
|
+
* The manifest `buildStaticBundle` writes when no `studioVersion` is given.
|
|
18
|
+
*
|
|
19
|
+
* Keystone reads a manifest without `studio_version` as this format and checks
|
|
20
|
+
* the signature against `content_hash` alone. `content_hash` covers every
|
|
21
|
+
* other file in the bundle, so that is what makes an edited bundle fail.
|
|
22
|
+
*/
|
|
23
|
+
export interface ContentHashManifest {
|
|
24
|
+
/**
|
|
25
|
+
* The sfa-kit version that ran the build. Not signed: Keystone stores it for
|
|
26
|
+
* troubleshooting only.
|
|
27
|
+
*
|
|
28
|
+
* NOTE: this is the copy of sfa-kit that ran the bundler. esbuild bundles
|
|
29
|
+
* whichever copy the entry module imports, which is normally the same one,
|
|
30
|
+
* but a project with two installed copies can bundle the other.
|
|
31
|
+
*/
|
|
32
|
+
sfa_kit_version: string;
|
|
33
|
+
/** SHA-256 hex digest of all non-manifest file contents. */
|
|
34
|
+
content_hash: string;
|
|
35
|
+
/** HMAC-SHA-256 hex of `content_hash`. */
|
|
36
|
+
signature: string;
|
|
37
|
+
/**
|
|
38
|
+
* Never present in this format. Keystone picks the format by whether the
|
|
39
|
+
* manifest carries `studio_version`, so one that does is a legacy
|
|
40
|
+
* {@link BundleManifest}, not this.
|
|
41
|
+
*/
|
|
42
|
+
studio_version?: never;
|
|
43
|
+
}
|
|
15
44
|
/** A single file in the bundle, used for content hash computation. */
|
|
16
45
|
export interface FileEntry {
|
|
17
46
|
/** Relative path using forward slashes (e.g. "index.html", "assets/bundle.js"). */
|
package/src/lib/version.d.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export declare const SFA_KIT_VERSION = "1.
|
|
1
|
+
export declare const SFA_KIT_VERSION = "1.19.2";
|
package/src/lib/version.js
CHANGED
package/src/signing.d.ts
CHANGED
|
@@ -14,10 +14,10 @@
|
|
|
14
14
|
* import { readBundleFiles, computeContentHash } from '@geniee-inc/sfa-kit/signing';
|
|
15
15
|
*
|
|
16
16
|
* const contentHash = computeContentHash(await readBundleFiles('./dist'));
|
|
17
|
-
* // POST /v1/pages/sign {
|
|
17
|
+
* // POST /v1/pages/sign { content_hash } -> { signature }
|
|
18
18
|
* ```
|
|
19
19
|
*
|
|
20
20
|
* @packageDocumentation
|
|
21
21
|
*/
|
|
22
|
-
export type { BundleManifest, FileEntry } from './lib/signing/index.js';
|
|
22
|
+
export type { BundleManifest, FileEntry, ContentHashManifest, } from './lib/signing/index.js';
|
|
23
23
|
export { computeContentHash, readBundleFiles, computeSignature, createManifest, createManifestFromDirectory, } from './lib/signing/index.js';
|