@lowdefy/plugin-aws 0.0.0-experimental-20260408133530 → 0.0.0-experimental-20260409102431

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.
@@ -23,9 +23,9 @@
23
23
  },
24
24
  events: {
25
25
  onBeforeUpload: {
26
- description: 'Triggered before upload starts. If any action throws, the upload is cancelled.',
26
+ description: 'Triggered before a file is uploaded. If an action throws, the upload is cancelled.',
27
27
  event: {
28
- file: 'The raw File object selected by the user.'
28
+ file: 'The file metadata (name, type, size, lastModified, uid, url).'
29
29
  }
30
30
  },
31
31
  onChange: 'Triggered when the upload state is changing.',
@@ -22,9 +22,9 @@
22
22
  },
23
23
  events: {
24
24
  onBeforeUpload: {
25
- description: 'Triggered before upload starts. If any action throws, the upload is cancelled.',
25
+ description: 'Triggered before a file is uploaded. If an action throws, the upload is cancelled.',
26
26
  event: {
27
- file: 'The raw File object selected by the user.'
27
+ file: 'The file metadata (name, type, size, lastModified, uid, url).'
28
28
  }
29
29
  },
30
30
  onChange: 'Triggered when the upload state is changing.',
@@ -12,7 +12,8 @@
12
12
  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
13
  See the License for the specific language governing permissions and
14
14
  limitations under the License.
15
- */ const getS3Upload = ({ methods, setFileList, setLoading = ()=>null })=>async ({ file })=>{
15
+ */ import { ServiceError } from '@lowdefy/errors';
16
+ const getS3Upload = ({ methods, setFileList, setLoading = ()=>null })=>async ({ file })=>{
16
17
  if (!file) {
17
18
  console.warn('File is undefined in useS3Upload');
18
19
  return;
@@ -45,37 +46,47 @@
45
46
  formData.append(field, fields[field]);
46
47
  });
47
48
  formData.append('file', file);
48
- const xhr = new XMLHttpRequest();
49
- xhr.upload.onprogress = async (event)=>{
50
- if (event.lengthComputable) {
51
- await setFileList({
52
- event: 'onProgress',
53
- file,
54
- percent: event.loaded / event.total * 80 + 20
55
- });
56
- }
57
- };
58
- xhr.addEventListener('error', async ()=>{
59
- await setFileList({
60
- event: 'onError',
61
- file
49
+ await new Promise((resolve, reject)=>{
50
+ const xhr = new XMLHttpRequest();
51
+ xhr.upload.onprogress = async (event)=>{
52
+ if (event.lengthComputable) {
53
+ await setFileList({
54
+ event: 'onProgress',
55
+ file,
56
+ percent: event.loaded / event.total * 80 + 20
57
+ });
58
+ }
59
+ };
60
+ xhr.addEventListener('load', ()=>{
61
+ if (xhr.status >= 200 && xhr.status < 300) {
62
+ resolve();
63
+ } else {
64
+ reject(new Error(`S3 upload failed with status ${xhr.status}.`));
65
+ }
62
66
  });
63
- });
64
- xhr.addEventListener('loadend', async ()=>{
65
- await setFileList({
66
- event: 'onSuccess',
67
- file
67
+ xhr.addEventListener('error', ()=>{
68
+ reject(new ServiceError(`S3 upload failed for "${name}" — CORS or network error. ` + `Check that the S3 bucket CORS configuration allows requests from this origin.`, {
69
+ service: 'S3'
70
+ }));
68
71
  });
69
- setLoading(false);
72
+ xhr.addEventListener('abort', ()=>{
73
+ reject(new Error(`S3 upload aborted for "${name}".`));
74
+ });
75
+ xhr.open('post', url);
76
+ xhr.send(formData);
77
+ });
78
+ await setFileList({
79
+ event: 'onSuccess',
80
+ file
70
81
  });
71
- xhr.open('post', url);
72
- xhr.send(formData);
82
+ setLoading(false);
73
83
  } catch (error) {
74
- console.error(error);
75
84
  await setFileList({
76
85
  event: 'onError',
77
86
  file
78
87
  });
88
+ setLoading(false);
89
+ throw error;
79
90
  }
80
91
  };
81
92
  export default getS3Upload;
@@ -91,22 +91,36 @@ const useFileList = ({ properties, methods, value = {} })=>{
91
91
  if (type.isInt(properties.maxCount) && nextFiles.filter((f)=>type.isString(f.uid)).length > properties.maxCount) {
92
92
  return false;
93
93
  }
94
+ // Extract file properties into a serialization-safe plain object.
95
+ // Raw File/Blob objects are destroyed by serializer.copy() in _event resolution.
96
+ const fileData = {
97
+ name: file.name,
98
+ type: file.type,
99
+ size: file.size,
100
+ lastModified: file.lastModified,
101
+ uid: file.uid
102
+ };
103
+ if (file instanceof Blob || file instanceof File) {
104
+ fileData.url = URL.createObjectURL(file);
105
+ }
94
106
  const result = await methods.triggerEvent({
95
107
  name: 'onBeforeUpload',
96
108
  event: {
97
- file
109
+ file: fileData
98
110
  }
99
111
  });
100
112
  if (result.success === false) {
101
113
  return false;
102
114
  }
103
- setValue({
104
- file,
115
+ const nextState = {
116
+ file: fileData,
105
117
  fileList: [
106
118
  ...nextFiles,
107
119
  ...state.fileList
108
120
  ]
109
- });
121
+ };
122
+ setValue(nextState);
123
+ methods.setValue(nextState);
110
124
  };
111
125
  const removeFile = (file)=>{
112
126
  state.fileList.splice(state.fileList.findIndex((f)=>f.uid === file.uid), 1);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lowdefy/plugin-aws",
3
- "version": "0.0.0-experimental-20260408133530",
3
+ "version": "0.0.0-experimental-20260409102431",
4
4
  "license": "Apache-2.0",
5
5
  "description": "",
6
6
  "homepage": "https://lowdefy.com",
@@ -41,9 +41,9 @@
41
41
  "dist/*"
42
42
  ],
43
43
  "dependencies": {
44
- "@lowdefy/block-utils": "0.0.0-experimental-20260408133530",
45
- "@lowdefy/blocks-antd": "0.0.0-experimental-20260408133530",
46
- "@lowdefy/helpers": "0.0.0-experimental-20260408133530",
44
+ "@lowdefy/block-utils": "0.0.0-experimental-20260409102431",
45
+ "@lowdefy/blocks-antd": "0.0.0-experimental-20260409102431",
46
+ "@lowdefy/helpers": "0.0.0-experimental-20260409102431",
47
47
  "antd": "6.3.1",
48
48
  "@aws-sdk/client-s3": "3.797.0",
49
49
  "@aws-sdk/s3-presigned-post": "3.797.0",
@@ -52,9 +52,9 @@
52
52
  "react-dom": "18.2.0"
53
53
  },
54
54
  "devDependencies": {
55
- "@lowdefy/ajv": "0.0.0-experimental-20260408133530",
56
- "@lowdefy/block-dev": "0.0.0-experimental-20260408133530",
57
- "@lowdefy/jest-yaml-transform": "0.0.0-experimental-20260408133530",
55
+ "@lowdefy/ajv": "0.0.0-experimental-20260409102431",
56
+ "@lowdefy/block-dev": "0.0.0-experimental-20260409102431",
57
+ "@lowdefy/jest-yaml-transform": "0.0.0-experimental-20260409102431",
58
58
  "@swc/cli": "0.8.0",
59
59
  "@swc/core": "1.15.18",
60
60
  "@swc/jest": "0.2.39",