@wcstack/upload 4.7.0 → 4.9.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/index.esm.js CHANGED
@@ -3,6 +3,7 @@ const _config = {
3
3
  triggerAttribute: "data-uploadtarget",
4
4
  tagNames: {
5
5
  upload: "wcs-upload",
6
+ uploadHeader: "wcs-upload-header",
6
7
  },
7
8
  };
8
9
  function deepFreeze(obj) {
@@ -967,9 +968,11 @@ class WcsUpload extends HTMLElement {
967
968
  _core;
968
969
  _files = null;
969
970
  _trigger = false;
970
- // The reasons `[wcs/command-not-ready]` was said for, once each per element
971
- // (docs/v4-direction-2026-10.md §5.1, the I/O command policy).
971
+ // The reasons `[wcs/command-not-ready]` was said for in this outage, once each
972
+ // (docs/v4-direction-2026-10.md §5.1, the I/O command policy); an upload starting clears them.
972
973
  _told = null;
974
+ // `[wcs/upload-helper-undefined]` was said for this element (once per element, as fetch's)
975
+ _toldUndefinedHelper = false;
973
976
  // automatic-mode files assigned while there was no url: sent when the url arrives
974
977
  _waitingForUrl = false;
975
978
  _connectedCallbackPromise = Promise.resolve();
@@ -1212,9 +1215,22 @@ class WcsUpload extends HTMLElement {
1212
1215
  this._core.setError(validationError);
1213
1216
  return null;
1214
1217
  }
1218
+ // ready again (an upload starts): a refusal in the next outage is said again
1219
+ this._told = null;
1220
+ // the <wcs-upload-header> elements inside, read now: a header bound from state goes out with
1221
+ // the value it has when the upload starts, not the one it had when the element connected
1222
+ const headers = this._collectHeaders();
1223
+ // An upload is always multipart/form-data: a manual Content-Type drops the boundary the
1224
+ // browser adds, and the server cannot read the parts. Sent as written (as fetch does), but said.
1225
+ if (Object.keys(headers).some((name) => name.toLowerCase() === "content-type")) {
1226
+ console.warn("[@wcstack/upload] A Content-Type header was set on an upload. An upload is sent as " +
1227
+ "multipart/form-data, and a manual Content-Type drops the boundary the browser adds; " +
1228
+ `remove the Content-Type <${config.tagNames.uploadHeader}>.`, this);
1229
+ }
1215
1230
  const result = await this._core.upload(this.url, files, {
1216
1231
  method: this.method,
1217
1232
  fieldName: this.fieldName,
1233
+ headers,
1218
1234
  });
1219
1235
  // 自分が開始したアップロードのファイルだけをリセット
1220
1236
  // (途中で新しい files がセットされていたら触らない)
@@ -1227,16 +1243,48 @@ class WcsUpload extends HTMLElement {
1227
1243
  }
1228
1244
  return result;
1229
1245
  }
1246
+ _collectHeaders() {
1247
+ const headers = {};
1248
+ const headerElements = this.querySelectorAll(config.tagNames.uploadHeader);
1249
+ for (const el of headerElements) {
1250
+ if (typeof el.hasHeader !== "boolean") {
1251
+ this._warnUndefinedHelper(config.tagNames.uploadHeader);
1252
+ continue;
1253
+ }
1254
+ // a header without a value attribute is not sent (WcsUploadHeader)
1255
+ if (el.hasHeader) {
1256
+ headers[el.name] = el.value;
1257
+ }
1258
+ }
1259
+ return headers;
1260
+ }
1261
+ /**
1262
+ * A `<wcs-upload-header>` whose definition never loaded is a plain element, and its header would
1263
+ * be left out of the upload without a word: a page that defines the tags itself (an autoloader's
1264
+ * wrapper module, a scoped registry) defined `<wcs-upload>` only — fetch's
1265
+ * `[wcs/fetch-helper-undefined]` (docs/seam-apps.md, fw-inventory). Said once per element.
1266
+ */
1267
+ _warnUndefinedHelper(tag) {
1268
+ if (this._toldUndefinedHelper)
1269
+ return;
1270
+ this._toldUndefinedHelper = true;
1271
+ console.warn(`[@wcstack/upload] [wcs/upload-helper-undefined] <${tag}> inside this <${config.tagNames.upload}> is not ` +
1272
+ "defined, so its header is not sent. Load @wcstack/upload/auto, or define WcsUploadHeader with WcsUpload " +
1273
+ "when the page defines the tags itself. (Said once per element.)", this);
1274
+ }
1230
1275
  // A refused upload sent nothing and said nothing (no `error`, by design): a `trigger`
1231
1276
  // written before `url` / `files` (`data-wcs` bindings and a framework's props are applied in
1232
- // the order written), a retry after the files were used up.
1277
+ // the order written), a retry after the files were used up. Said once per reason and outage:
1278
+ // once per element was once per page life — a route puts the same element back on every
1279
+ // entry, so the next outage went unsaid (docs/seam-apps.md, shift-desk).
1233
1280
  _warnNotReady(reason) {
1234
1281
  if (this._told?.has(reason))
1235
1282
  return;
1236
1283
  (this._told ??= new Set()).add(reason);
1237
1284
  console.warn(`[@wcstack/upload] [wcs/command-not-ready] The upload was refused: ${reason}, so nothing is sent. ` +
1238
1285
  "Write url and files before trigger (data-wcs bindings and a framework's props are applied in the order " +
1239
- "written), and assign files again for each retry: an upload uses them up. (Said once per element and reason.)", this);
1286
+ "written), and assign files again for each retry: an upload uses them up. " +
1287
+ "(Said once per reason until an upload is sent again.)", this);
1240
1288
  }
1241
1289
  // --- Lifecycle ---
1242
1290
  attributeChangedCallback(_name, _oldValue, newValue) {
@@ -1263,6 +1311,49 @@ class WcsUpload extends HTMLElement {
1263
1311
  }
1264
1312
  }
1265
1313
 
1314
+ /**
1315
+ * `<wcs-upload-header name value>`: one request header of the `<wcs-upload>` it sits in, read when
1316
+ * an upload starts — the same shape as `@wcstack/fetch`'s `<wcs-fetch-header>`. `name` / `value`
1317
+ * are properties too, reflected to the attributes (`null` removes one, `undefined` restores the
1318
+ * markup's), so a binding — `data-wcs="value: authHeader"` — sets the header. Without a `value`
1319
+ * attribute the header is not sent: a token that is not there yet sends no `Authorization` instead
1320
+ * of an empty one. Before this, `<wcs-upload>` sent no header at all, and an API that wants
1321
+ * `Authorization` on every request could only be reached through `UploadCore` (docs/seam-apps.md,
1322
+ * family-ledger).
1323
+ *
1324
+ * It declares no `wcBindable`: it is part of `<wcs-upload>`'s markup, not an I/O node of its own.
1325
+ */
1326
+ class WcsUploadHeader extends HTMLElement {
1327
+ connectedCallback() {
1328
+ // A value assigned before the element was upgraded sits on the instance and hides the
1329
+ // accessor: pass it through the setter (the upgrade-properties pattern, for two members).
1330
+ for (const key of ["name", "value"]) {
1331
+ if (Object.prototype.hasOwnProperty.call(this, key)) {
1332
+ const value = this[key];
1333
+ delete this[key];
1334
+ this[key] = value;
1335
+ }
1336
+ }
1337
+ this.style.display = "none";
1338
+ }
1339
+ get name() {
1340
+ return this.getAttribute("name") ?? "";
1341
+ }
1342
+ set name(value) {
1343
+ reflectAttribute(this, "name", value);
1344
+ }
1345
+ get value() {
1346
+ return this.getAttribute("value") ?? "";
1347
+ }
1348
+ set value(value) {
1349
+ reflectAttribute(this, "value", value);
1350
+ }
1351
+ /** Whether the header is sent: it has a name and a `value` attribute (an empty one included). */
1352
+ get hasHeader() {
1353
+ return this.name !== "" && this.hasAttribute("value");
1354
+ }
1355
+ }
1356
+
1266
1357
  /**
1267
1358
  * Register this package's tags. Pass a scoped `CustomElementRegistry` to define
1268
1359
  * them for a single shadow tree -- scoped registries do not inherit the global
@@ -1272,6 +1363,9 @@ function registerComponents(registry = customElements) {
1272
1363
  if (!registry.get(config.tagNames.upload)) {
1273
1364
  registry.define(config.tagNames.upload, WcsUpload);
1274
1365
  }
1366
+ if (!registry.get(config.tagNames.uploadHeader)) {
1367
+ registry.define(config.tagNames.uploadHeader, WcsUploadHeader);
1368
+ }
1275
1369
  }
1276
1370
 
1277
1371
  function bootstrapUpload(userConfig, registry) {
@@ -1281,5 +1375,5 @@ function bootstrapUpload(userConfig, registry) {
1281
1375
  registerComponents(registry);
1282
1376
  }
1283
1377
 
1284
- export { UploadCore, WCS_UPLOAD_ERROR_CODE, WcsUpload, bootstrapUpload, getConfig };
1378
+ export { UploadCore, WCS_UPLOAD_ERROR_CODE, WcsUpload, WcsUploadHeader, bootstrapUpload, getConfig };
1285
1379
  //# sourceMappingURL=index.esm.js.map