form0-core 0.1.19 → 0.1.21

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "form0-core",
3
- "version": "0.1.19",
3
+ "version": "0.1.21",
4
4
  "publishConfig": {
5
5
  "registry": "https://registry.npmjs.org/"
6
6
  },
@@ -12,6 +12,44 @@ const AI_ATTRIBUTE_DEFINITION = {
12
12
  nullable: true,
13
13
  };
14
14
 
15
+ const MEDIA_REFERENCE_FIELDS = [
16
+ 'asset_id',
17
+ 'upload_id',
18
+ 'upload_status',
19
+ 'mime_type',
20
+ 'size',
21
+ 'size_bytes',
22
+ 'checksum_sha256',
23
+ 'original_filename',
24
+ 'thumbnail_url',
25
+ 'preview_url',
26
+ 'url',
27
+ 'public_url',
28
+ 'field_key',
29
+ 'field_data_name',
30
+ 'attached_at_client',
31
+ 'captured_at_client',
32
+ 'signed_at_client',
33
+ 'uploaded_at_server',
34
+ 'ready_at_server',
35
+ 'error',
36
+ ];
37
+
38
+ const isObjectRecord = (value) =>
39
+ Boolean(value) && typeof value === 'object' && !Array.isArray(value);
40
+
41
+ const copyPresentMediaFields = (source, target) => {
42
+ MEDIA_REFERENCE_FIELDS.forEach((fieldName) => {
43
+ if (Object.prototype.hasOwnProperty.call(source, fieldName)) {
44
+ target[fieldName] = source[fieldName];
45
+ }
46
+ });
47
+ return target;
48
+ };
49
+
50
+ const normalizeMediaId = (value, primaryKey) =>
51
+ value[primaryKey] || value.media_id || value.asset_id || null;
52
+
15
53
  /**
16
54
  * Central field specification registry
17
55
  * Each field type defines its attributes, validation rules, and behavior
@@ -73,6 +111,7 @@ export const FIELD_SPECS = {
73
111
  },
74
112
  supporting_image: { type: 'boolean', required: true, nullable: false },
75
113
  supporting_image_path: { type: 'string', required: true, nullable: true },
114
+ supporting_image_asset_id: { type: 'string', required: false, nullable: true },
76
115
  supporting_image_display: {
77
116
  type: 'string',
78
117
  required: true,
@@ -152,6 +191,7 @@ export const FIELD_SPECS = {
152
191
  },
153
192
  supporting_image: { type: 'boolean', required: true, nullable: false },
154
193
  supporting_image_path: { type: 'string', required: true, nullable: true },
194
+ supporting_image_asset_id: { type: 'string', required: false, nullable: true },
155
195
  supporting_image_display: {
156
196
  type: 'string',
157
197
  required: true,
@@ -237,6 +277,7 @@ export const FIELD_SPECS = {
237
277
  choices: { type: 'array', required: true, nullable: false },
238
278
  supporting_image: { type: 'boolean', required: true, nullable: false },
239
279
  supporting_image_path: { type: 'string', required: true, nullable: true },
280
+ supporting_image_asset_id: { type: 'string', required: false, nullable: true },
240
281
  supporting_image_display: {
241
282
  type: 'string',
242
283
  required: true,
@@ -391,6 +432,7 @@ export const FIELD_SPECS = {
391
432
  choices: { type: 'array', required: true, nullable: false },
392
433
  supporting_image: { type: 'boolean', required: true, nullable: false },
393
434
  supporting_image_path: { type: 'string', required: true, nullable: true },
435
+ supporting_image_asset_id: { type: 'string', required: false, nullable: true },
394
436
  supporting_image_display: {
395
437
  type: 'string',
396
438
  required: true,
@@ -540,6 +582,7 @@ export const FIELD_SPECS = {
540
582
  third_option_enabled: { type: 'boolean', required: true, nullable: false },
541
583
  supporting_image: { type: 'boolean', required: true, nullable: false },
542
584
  supporting_image_path: { type: 'string', required: true, nullable: true },
585
+ supporting_image_asset_id: { type: 'string', required: false, nullable: true },
543
586
  supporting_image_display: {
544
587
  type: 'string',
545
588
  required: true,
@@ -774,6 +817,7 @@ export const FIELD_SPECS = {
774
817
  calculate: { type: 'string', required: true, nullable: false },
775
818
  supporting_image: { type: 'boolean', required: true, nullable: false },
776
819
  supporting_image_path: { type: 'string', required: true, nullable: true },
820
+ supporting_image_asset_id: { type: 'string', required: false, nullable: true },
777
821
  supporting_image_display: {
778
822
  type: 'string',
779
823
  required: true,
@@ -1033,6 +1077,7 @@ export const FIELD_SPECS = {
1033
1077
  default_value: { type: 'string', required: true, nullable: true, value: null },
1034
1078
  supporting_image: { type: 'boolean', required: true, nullable: false },
1035
1079
  supporting_image_path: { type: 'string', required: true, nullable: true },
1080
+ supporting_image_asset_id: { type: 'string', required: false, nullable: true },
1036
1081
  supporting_image_display: {
1037
1082
  type: 'string',
1038
1083
  required: true,
@@ -1104,17 +1149,21 @@ export const FIELD_SPECS = {
1104
1149
  return field.default_value || null;
1105
1150
  },
1106
1151
  outputProducer: (field, value) => {
1107
- // SignatureField output structure: {signature_id: null, data: base64String}
1108
- if (value && typeof value === 'object' && value.data) {
1109
- // Value is already in the correct structure from form-renderer.js
1110
- return {
1111
- signature_id: value.signature_id || null,
1112
- data: value.data,
1113
- };
1152
+ // SignatureField preserves storage-agnostic upload metadata.
1153
+ if (isObjectRecord(value)) {
1154
+ const output = copyPresentMediaFields(value, {
1155
+ signature_id: normalizeMediaId(value, 'signature_id'),
1156
+ media_id: value.media_id || value.signature_id || value.asset_id || null,
1157
+ data: value.data || null,
1158
+ });
1159
+ return output.data || output.asset_id || output.upload_id || output.media_id
1160
+ ? output
1161
+ : null;
1114
1162
  } else if (value && typeof value === 'string') {
1115
1163
  // Fallback: if value is just the base64 string
1116
1164
  return {
1117
1165
  signature_id: null,
1166
+ media_id: null,
1118
1167
  data: value,
1119
1168
  };
1120
1169
  }
@@ -1200,13 +1249,18 @@ export const FIELD_SPECS = {
1200
1249
  return null; // PhotoField default_value must be null
1201
1250
  },
1202
1251
  outputProducer: (field, value) => {
1203
- // PhotoField output structure: array of {photo_id: null|uuid, filename: string, caption: string|null}
1252
+ // PhotoField output preserves stable client IDs and upload metadata.
1204
1253
  if (Array.isArray(value)) {
1205
- return value.map((photo) => ({
1206
- photo_id: photo.photo_id || null,
1207
- filename: photo.filename || photo.name || 'unknown',
1208
- caption: photo.caption || null,
1209
- }));
1254
+ return value
1255
+ .filter((photo) => isObjectRecord(photo))
1256
+ .map((photo) =>
1257
+ copyPresentMediaFields(photo, {
1258
+ photo_id: normalizeMediaId(photo, 'photo_id'),
1259
+ media_id: photo.media_id || photo.photo_id || photo.asset_id || null,
1260
+ filename: photo.filename || photo.name || photo.original_filename || 'unknown',
1261
+ caption: photo.caption || null,
1262
+ })
1263
+ );
1210
1264
  }
1211
1265
  return [];
1212
1266
  },
@@ -1296,14 +1350,19 @@ export const FIELD_SPECS = {
1296
1350
  return null; // VideoField default_value must be null
1297
1351
  },
1298
1352
  outputProducer: (field, value) => {
1299
- // VideoField output structure: array of {video_id: null|uuid, filename: string, duration: number, caption: string|null}
1353
+ // VideoField output preserves stable client IDs and upload metadata.
1300
1354
  if (Array.isArray(value)) {
1301
- return value.map((video) => ({
1302
- video_id: video.video_id || null,
1303
- filename: video.filename || video.name || 'unknown',
1304
- duration: video.duration || 0,
1305
- caption: video.caption || null,
1306
- }));
1355
+ return value
1356
+ .filter((video) => isObjectRecord(video))
1357
+ .map((video) =>
1358
+ copyPresentMediaFields(video, {
1359
+ video_id: normalizeMediaId(video, 'video_id'),
1360
+ media_id: video.media_id || video.video_id || video.asset_id || null,
1361
+ filename: video.filename || video.name || video.original_filename || 'unknown',
1362
+ duration: video.duration || 0,
1363
+ caption: video.caption || null,
1364
+ })
1365
+ );
1307
1366
  }
1308
1367
  return [];
1309
1368
  },