@streamline-pulse/formkrafter-core 0.15.2 → 0.17.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/README.md +2 -2
- package/dist/brick/brick.d.ts +4 -4
- package/dist/index.d.ts +1 -1
- package/dist/index.js +84 -67
- package/dist/index.js.map +9 -9
- package/dist/ops/ops.d.ts +4 -4
- package/dist/ops/pointer.d.ts +0 -1
- package/dist/services/data_source_service.d.ts +1 -0
- package/dist/utils/remote.d.ts +1 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -4,7 +4,7 @@ The framework-agnostic heart of FormKrafter: form **specs**, immutable **mutatio
|
|
|
4
4
|
|
|
5
5
|
## The spec
|
|
6
6
|
|
|
7
|
-
A form is a tree of `BrickSpec` nodes. Each brick has a `type` (`input`, `panel`, `collection`, `output`, `action`), an `id` (which registered brick renders it), `configs` (with a
|
|
7
|
+
A form is a tree of `BrickSpec` nodes. Each brick has a `type` (`input`, `panel`, `collection`, `output`, `action`), an `id` (which registered brick renders it), `configs` (with a data `key`), plus optional `validations`, `rules`, `styles`, and `children`.
|
|
8
8
|
|
|
9
9
|
```mermaid
|
|
10
10
|
flowchart TD
|
|
@@ -40,7 +40,7 @@ flowchart LR
|
|
|
40
40
|
H -->|redo → apply patches| S1[spec']
|
|
41
41
|
```
|
|
42
42
|
|
|
43
|
-
Available ops: `addBrick`, `removeBrick`, `moveBrick`, `duplicateBrick
|
|
43
|
+
Available ops: `addBrick`, `removeBrick`, `moveBrick`, `duplicateBrick`, `updateBrickConfigs`, `updateBrickStyles`, `updateBrickValidations`, `updateBrickRules`. Addressing helpers: `getBrickAt(spec, path)`, `pointerFromPath(path)`, `iterateBricks(spec)`.
|
|
44
44
|
|
|
45
45
|
Patches are plain RFC 6902 — persist them, sync them, audit them.
|
|
46
46
|
|
package/dist/brick/brick.d.ts
CHANGED
|
@@ -8,8 +8,8 @@ import type { BrickType } from "../utils/brick-type";
|
|
|
8
8
|
import type { BrickBaseConfigs, CommonBrickProps } from "../utils/common-brick-props";
|
|
9
9
|
import type { BrickMoldDropType } from "../utils/drop-type";
|
|
10
10
|
export interface BrickProps<DataType, Configs extends BrickBaseConfigs, Styles> extends CommonBrickProps<Configs, Styles> {
|
|
11
|
-
onConfigsChange?: (configs: BrickBaseConfigs & Record<string, unknown>,
|
|
12
|
-
onStylesChange?: (styles: Record<string, unknown>,
|
|
11
|
+
onConfigsChange?: (configs: BrickBaseConfigs & Record<string, unknown>, path?: string) => void;
|
|
12
|
+
onStylesChange?: (styles: Record<string, unknown>, path?: string) => void;
|
|
13
13
|
data?: DataType;
|
|
14
14
|
dataMap?: Record<string, unknown>;
|
|
15
15
|
rootSpec?: BrickSpec;
|
|
@@ -26,9 +26,9 @@ export interface BrickProps<DataType, Configs extends BrickBaseConfigs, Styles>
|
|
|
26
26
|
brickSpec?: BrickSpec;
|
|
27
27
|
editable?: boolean;
|
|
28
28
|
validations?: Validation[];
|
|
29
|
-
onValidationsChange?: (validations: Validation[],
|
|
29
|
+
onValidationsChange?: (validations: Validation[], path?: string) => void;
|
|
30
30
|
rules?: Rule[];
|
|
31
|
-
onRulesChange?: (rules: Rule[],
|
|
31
|
+
onRulesChange?: (rules: Rule[], path?: string) => void;
|
|
32
32
|
utils: Utils;
|
|
33
33
|
}
|
|
34
34
|
export declare abstract class Brick<DataType, Configs extends BrickBaseConfigs, Styles extends Record<string, unknown>> {
|
package/dist/index.d.ts
CHANGED
|
@@ -27,7 +27,7 @@ export { DataSourceService, FetchDataSourceService } from "./services/data_sourc
|
|
|
27
27
|
export { FileLike, UploadedFile, FileUploadService, FileUploadOptions, Base64FileUploadService, UrlFileUploadService, UrlFileUploadDefaults } from "./services/file_upload_service";
|
|
28
28
|
export { LocalizedText, isLocalizedObject, resolveLocalizedText, resolveLocalizedRecord } from "./utils/localized-text";
|
|
29
29
|
export { FkTranslations, setFkTranslations, fkT, fkTOr, frFkTranslations } from "./i18n";
|
|
30
|
-
export { pointerFromPath,
|
|
30
|
+
export { pointerFromPath, getBrickAt } from "./ops/pointer";
|
|
31
31
|
export { SpecUpdate, addBrick, removeBrick, moveBrick, duplicateBrick, updateBrickConfigs, updateBrickStyles, updateBrickValidations, updateBrickRules } from "./ops/ops";
|
|
32
32
|
export { SpecHistory } from "./ops/history";
|
|
33
33
|
export type { Operation } from "fast-json-patch";
|
package/dist/index.js
CHANGED
|
@@ -7125,6 +7125,7 @@ var en = {
|
|
|
7125
7125
|
"panel.content": "Content",
|
|
7126
7126
|
"panel.dataKey": "Data key",
|
|
7127
7127
|
"panel.url": "URL",
|
|
7128
|
+
"panel.responsePath": "Response path (optional)",
|
|
7128
7129
|
"panel.headers": "Headers ({token} reads form data)",
|
|
7129
7130
|
"panel.searchParam": "Server search param",
|
|
7130
7131
|
"panel.labelKey": "Label key",
|
|
@@ -7259,6 +7260,7 @@ var frFkTranslations = {
|
|
|
7259
7260
|
"panel.content": "Contenu",
|
|
7260
7261
|
"panel.dataKey": "Clé de données",
|
|
7261
7262
|
"panel.url": "URL",
|
|
7263
|
+
"panel.responsePath": "Chemin dans la réponse (optionnel)",
|
|
7262
7264
|
"panel.headers": "En-têtes ({token} lit les données du formulaire)",
|
|
7263
7265
|
"panel.searchParam": "Paramètre de recherche serveur",
|
|
7264
7266
|
"panel.labelKey": "Clé du libellé",
|
|
@@ -7710,7 +7712,68 @@ class SandboxJsRunnerService {
|
|
|
7710
7712
|
}
|
|
7711
7713
|
}
|
|
7712
7714
|
|
|
7715
|
+
// lib/utils/remote.ts
|
|
7716
|
+
function resolvePath(source, path) {
|
|
7717
|
+
if (Object.prototype.hasOwnProperty.call(source, path))
|
|
7718
|
+
return source[path];
|
|
7719
|
+
let current = source;
|
|
7720
|
+
for (const segment of path.split(".")) {
|
|
7721
|
+
if (current === null || typeof current !== "object")
|
|
7722
|
+
return;
|
|
7723
|
+
if (!Object.prototype.hasOwnProperty.call(current, segment))
|
|
7724
|
+
return;
|
|
7725
|
+
current = current[segment];
|
|
7726
|
+
}
|
|
7727
|
+
return current;
|
|
7728
|
+
}
|
|
7729
|
+
function interpolateTemplate(template, dataMap) {
|
|
7730
|
+
return template.replace(/\{([\w.]+)\}/g, (_, token) => {
|
|
7731
|
+
const value = dataMap && resolvePath(dataMap, token);
|
|
7732
|
+
return value === undefined || value === null ? "" : String(value);
|
|
7733
|
+
});
|
|
7734
|
+
}
|
|
7735
|
+
function parseHeaderLines(raw, dataMap) {
|
|
7736
|
+
if (typeof raw !== "string" || !raw.trim())
|
|
7737
|
+
return;
|
|
7738
|
+
const headers = {};
|
|
7739
|
+
for (const line of raw.split(`
|
|
7740
|
+
`)) {
|
|
7741
|
+
const separator = line.indexOf(":");
|
|
7742
|
+
if (separator <= 0)
|
|
7743
|
+
continue;
|
|
7744
|
+
const name = line.slice(0, separator).trim();
|
|
7745
|
+
const value = interpolateTemplate(line.slice(separator + 1).trim(), dataMap);
|
|
7746
|
+
if (name)
|
|
7747
|
+
headers[name] = value;
|
|
7748
|
+
}
|
|
7749
|
+
return Object.keys(headers).length ? headers : undefined;
|
|
7750
|
+
}
|
|
7751
|
+
function appendSearchParam(url, param, term) {
|
|
7752
|
+
if (!term)
|
|
7753
|
+
return url;
|
|
7754
|
+
const separator = url.includes("?") ? "&" : "?";
|
|
7755
|
+
return `${url}${separator}${encodeURIComponent(param)}=${encodeURIComponent(term)}`;
|
|
7756
|
+
}
|
|
7757
|
+
|
|
7713
7758
|
// lib/services/data_source_service.ts
|
|
7759
|
+
function optionsFromPayload(json, url, path) {
|
|
7760
|
+
if (path) {
|
|
7761
|
+
const picked = json !== null && typeof json === "object" ? resolvePath(json, path) : undefined;
|
|
7762
|
+
if (!Array.isArray(picked)) {
|
|
7763
|
+
throw new Error(`Data source has no array at "${path}": ${url}`);
|
|
7764
|
+
}
|
|
7765
|
+
return picked;
|
|
7766
|
+
}
|
|
7767
|
+
if (Array.isArray(json))
|
|
7768
|
+
return json;
|
|
7769
|
+
if (json !== null && typeof json === "object") {
|
|
7770
|
+
const envelope = json.data;
|
|
7771
|
+
if (Array.isArray(envelope))
|
|
7772
|
+
return envelope;
|
|
7773
|
+
}
|
|
7774
|
+
throw new Error(`Data source did not return an array: ${url}`);
|
|
7775
|
+
}
|
|
7776
|
+
|
|
7714
7777
|
class FetchDataSourceService {
|
|
7715
7778
|
defaults;
|
|
7716
7779
|
cache = new Map;
|
|
@@ -7724,7 +7787,7 @@ class FetchDataSourceService {
|
|
|
7724
7787
|
init.headers = headers;
|
|
7725
7788
|
if (this.defaults.credentials)
|
|
7726
7789
|
init.credentials = this.defaults.credentials;
|
|
7727
|
-
const key = `${url}|${JSON.stringify(init)}`;
|
|
7790
|
+
const key = `${url}|${JSON.stringify(init)}|${options?.path ?? ""}`;
|
|
7728
7791
|
let pending = this.cache.get(key);
|
|
7729
7792
|
if (!pending) {
|
|
7730
7793
|
pending = fetch(url, Object.keys(init).length ? init : undefined).then((response) => {
|
|
@@ -7732,12 +7795,7 @@ class FetchDataSourceService {
|
|
|
7732
7795
|
throw new Error(`Data source request failed (${response.status}): ${url}`);
|
|
7733
7796
|
}
|
|
7734
7797
|
return response.json();
|
|
7735
|
-
}).then((json) => {
|
|
7736
|
-
if (!Array.isArray(json)) {
|
|
7737
|
-
throw new Error(`Data source did not return an array: ${url}`);
|
|
7738
|
-
}
|
|
7739
|
-
return json;
|
|
7740
|
-
}).catch((error) => {
|
|
7798
|
+
}).then((json) => optionsFromPayload(json, url, options?.path)).catch((error) => {
|
|
7741
7799
|
this.cache.delete(key);
|
|
7742
7800
|
throw error;
|
|
7743
7801
|
});
|
|
@@ -8148,35 +8206,6 @@ function stripUidsFromPatches(patches) {
|
|
|
8148
8206
|
value: stripPatchValue(patch.value, patch.path)
|
|
8149
8207
|
} : patch);
|
|
8150
8208
|
}
|
|
8151
|
-
// lib/utils/remote.ts
|
|
8152
|
-
function interpolateTemplate(template, dataMap) {
|
|
8153
|
-
return template.replace(/\{(\w+)\}/g, (_, token) => {
|
|
8154
|
-
const value = dataMap?.[token];
|
|
8155
|
-
return value === undefined || value === null ? "" : String(value);
|
|
8156
|
-
});
|
|
8157
|
-
}
|
|
8158
|
-
function parseHeaderLines(raw, dataMap) {
|
|
8159
|
-
if (typeof raw !== "string" || !raw.trim())
|
|
8160
|
-
return;
|
|
8161
|
-
const headers = {};
|
|
8162
|
-
for (const line of raw.split(`
|
|
8163
|
-
`)) {
|
|
8164
|
-
const separator = line.indexOf(":");
|
|
8165
|
-
if (separator <= 0)
|
|
8166
|
-
continue;
|
|
8167
|
-
const name = line.slice(0, separator).trim();
|
|
8168
|
-
const value = interpolateTemplate(line.slice(separator + 1).trim(), dataMap);
|
|
8169
|
-
if (name)
|
|
8170
|
-
headers[name] = value;
|
|
8171
|
-
}
|
|
8172
|
-
return Object.keys(headers).length ? headers : undefined;
|
|
8173
|
-
}
|
|
8174
|
-
function appendSearchParam(url, param, term) {
|
|
8175
|
-
if (!term)
|
|
8176
|
-
return url;
|
|
8177
|
-
const separator = url.includes("?") ? "&" : "?";
|
|
8178
|
-
return `${url}${separator}${encodeURIComponent(param)}=${encodeURIComponent(term)}`;
|
|
8179
|
-
}
|
|
8180
8209
|
// lib/brick/brick.ts
|
|
8181
8210
|
class Brick {
|
|
8182
8211
|
type;
|
|
@@ -8414,19 +8443,14 @@ ${js}})();`;
|
|
|
8414
8443
|
function pointerFromPath(path) {
|
|
8415
8444
|
return path.split(".").slice(1).map((segment) => `/children/${segment}`).join("");
|
|
8416
8445
|
}
|
|
8417
|
-
function pointerOfUid(spec, uid) {
|
|
8418
|
-
if (spec.configs?.uid === uid)
|
|
8419
|
-
return "";
|
|
8420
|
-
for (const [index, child] of (spec.children ?? []).entries()) {
|
|
8421
|
-
const childPointer = pointerOfUid(child, uid);
|
|
8422
|
-
if (childPointer !== undefined)
|
|
8423
|
-
return `/children/${index}${childPointer}`;
|
|
8424
|
-
}
|
|
8425
|
-
return;
|
|
8426
|
-
}
|
|
8427
8446
|
function getBrickAt(spec, path) {
|
|
8447
|
+
const [root, ...segments] = path.split(".");
|
|
8448
|
+
if (root !== "0")
|
|
8449
|
+
return;
|
|
8428
8450
|
let current = spec;
|
|
8429
|
-
for (const segment of
|
|
8451
|
+
for (const segment of segments) {
|
|
8452
|
+
if (!/^\d+$/.test(segment))
|
|
8453
|
+
return;
|
|
8430
8454
|
current = current?.children?.[Number(segment)];
|
|
8431
8455
|
}
|
|
8432
8456
|
return current;
|
|
@@ -8448,16 +8472,10 @@ var requireBrickAt = (spec, path) => {
|
|
|
8448
8472
|
throw new Error(`No brick at path "${path}"`);
|
|
8449
8473
|
return brick;
|
|
8450
8474
|
};
|
|
8451
|
-
var
|
|
8452
|
-
|
|
8453
|
-
|
|
8454
|
-
|
|
8455
|
-
let brick = spec;
|
|
8456
|
-
for (const segment of pointer.split("/children/").slice(1)) {
|
|
8457
|
-
brick = brick.children[Number(segment)];
|
|
8458
|
-
}
|
|
8459
|
-
return { pointer, brick };
|
|
8460
|
-
};
|
|
8475
|
+
var requireBrickForUpdate = (spec, path) => ({
|
|
8476
|
+
pointer: pointerFromPath(path),
|
|
8477
|
+
brick: requireBrickAt(spec, path)
|
|
8478
|
+
});
|
|
8461
8479
|
var toJsonValue = (value) => JSON.parse(JSON.stringify(value));
|
|
8462
8480
|
function addBrick(spec, brick, parentPath, index) {
|
|
8463
8481
|
const parent = requireBrickAt(spec, parentPath);
|
|
@@ -8527,22 +8545,22 @@ var setBrickSection = (spec, brickPointer, section, value, previous) => {
|
|
|
8527
8545
|
}
|
|
8528
8546
|
return apply(spec, [{ op: "replace", path: pointer, value }], [{ op: "replace", path: pointer, value: previous }]);
|
|
8529
8547
|
};
|
|
8530
|
-
function updateBrickConfigs(spec,
|
|
8531
|
-
const { pointer, brick } =
|
|
8548
|
+
function updateBrickConfigs(spec, path, configs) {
|
|
8549
|
+
const { pointer, brick } = requireBrickForUpdate(spec, path);
|
|
8532
8550
|
const merged = { ...brick.configs, ...configs };
|
|
8533
8551
|
return setBrickSection(spec, pointer, "configs", merged, brick.configs);
|
|
8534
8552
|
}
|
|
8535
|
-
function updateBrickStyles(spec,
|
|
8536
|
-
const { pointer, brick } =
|
|
8553
|
+
function updateBrickStyles(spec, path, styles) {
|
|
8554
|
+
const { pointer, brick } = requireBrickForUpdate(spec, path);
|
|
8537
8555
|
const merged = { ...brick.styles, ...styles };
|
|
8538
8556
|
return setBrickSection(spec, pointer, "styles", merged, brick.styles);
|
|
8539
8557
|
}
|
|
8540
|
-
function updateBrickValidations(spec,
|
|
8541
|
-
const { pointer, brick } =
|
|
8558
|
+
function updateBrickValidations(spec, path, validations) {
|
|
8559
|
+
const { pointer, brick } = requireBrickForUpdate(spec, path);
|
|
8542
8560
|
return setBrickSection(spec, pointer, "validations", validations, brick.validations);
|
|
8543
8561
|
}
|
|
8544
|
-
function updateBrickRules(spec,
|
|
8545
|
-
const { pointer, brick } =
|
|
8562
|
+
function updateBrickRules(spec, path, rules) {
|
|
8563
|
+
const { pointer, brick } = requireBrickForUpdate(spec, path);
|
|
8546
8564
|
return setBrickSection(spec, pointer, "rules", rules, brick.rules);
|
|
8547
8565
|
}
|
|
8548
8566
|
// lib/ops/history.ts
|
|
@@ -9181,7 +9199,6 @@ export {
|
|
|
9181
9199
|
resolveLocalizedRecord,
|
|
9182
9200
|
removeBrick,
|
|
9183
9201
|
registerValidationMessages,
|
|
9184
|
-
pointerOfUid,
|
|
9185
9202
|
pointerFromPath,
|
|
9186
9203
|
parseHeaderLines,
|
|
9187
9204
|
normalizeOptions,
|
|
@@ -9219,5 +9236,5 @@ export {
|
|
|
9219
9236
|
Base64FileUploadService
|
|
9220
9237
|
};
|
|
9221
9238
|
|
|
9222
|
-
//# debugId=
|
|
9239
|
+
//# debugId=7CC5CCE3A23FDF4A64756E2164756E21
|
|
9223
9240
|
//# sourceMappingURL=index.js.map
|