@stapel/listings-react 0.1.0 → 0.2.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/CHANGELOG.md CHANGED
@@ -1 +1,66 @@
1
1
  # @stapel/listings-react
2
+
3
+ ## 0.2.0
4
+
5
+ ### Minor Changes
6
+
7
+ - fcc9f1e: Two axes, both on screen — the storefront's long pole
8
+
9
+ `@stapel/listings-react` is the pair for stapel-listings: the listing page, the
10
+ submission flow, the seller's dashboard, and favourites.
11
+
12
+ The module has two independent state axes and 0.5.0 made them genuinely
13
+ diverge. `status` decides whether anyone can see a listing and nothing else
14
+ does; `moderation_status` decides nothing about that. Editing a LIVE listing
15
+ keeps `status: published` and moves only the moderation axis, so "published,
16
+ and we are reviewing your changes" is a real state — one a dashboard that
17
+ derived either field from the other could not say, because it would either
18
+ hide a listing buyers are reading or never tell its owner their edit is being
19
+ screened. `model/status.ts` produces both halves of the sentence from both
20
+ fields, once; the 9 × 4 table is asserted.
21
+
22
+ A publish refusal is per-field and arrives in an unusual envelope: an invalid
23
+ draft comes back as a BARE `ValidationBatchResult`, while a promotion that
24
+ fails afterwards comes back as the ordinary one. `publishRefusal` branches on
25
+ the body rather than the status, and `featureErrorsBySlug` adds the `field`
26
+ the fleet's routing convention reads — so "this box is wrong" never degrades
27
+ into "something is wrong".
28
+
29
+ Three contracts meet on the composer and none of them is an import. L2 pairs do
30
+ not import each other, so the gallery arrives as a two-member structural bag
31
+ (`@stapel/cdn-react`'s `refs` IS `images_draft`; its `settled` is the submit
32
+ gate), the category schema as a plain `FeatureDef[]`, and a stored CDN
33
+ reference through a host-supplied resolver — because no contract in this fleet
34
+ resolves a stranger's reference, and inventing `${cdnBase}/${ref}` would be
35
+ writing a contract nobody agreed to. `@stapel/attributes-react` is a real
36
+ dependency; it is L0, and it owns the editors, the mirror and the formatter.
37
+
38
+ Four things the pair says out loud rather than papering over:
39
+
40
+ - **there is no owner-scoped list endpoint.** `GET /listings/` answers
41
+ `published()` and takes no owner parameter, so a seller's drafts are
42
+ unreachable. The counters are real and are shown; the rows come from an
43
+ injected source, and with none the dashboard reports a NAMED failure instead
44
+ of an empty grid;
45
+ - **no read returns the `*_draft` twin**, so an abandoned draft reopens empty
46
+ and the composer says so. Editing a live listing is unaffected — the
47
+ published half IS the listing;
48
+ - **`PUT`/`PATCH` skip the ownership check** that every other owner operation
49
+ in the module performs, so they are absent from `ListingsApi`;
50
+ `save-draft` does the same write with the check;
51
+ - **`GET /{pk}/` has no `published()` filter**, so a draft answers 200 to
52
+ anyone with the id. The pane reports it instead of dressing a draft up as a
53
+ shop page.
54
+
55
+ Also here: the card another pair renders (badges formatted from the stored DAO
56
+ projection, so a grid of forty costs one query and no category read); a soft
57
+ delete that reads as "this listing was removed" rather than as a typo, using
58
+ the AllowAny status probe that still answers for it; favourites (owner verdict
59
+ F7) with the heart blocked-and-explained for a visitor rather than hidden; and
60
+ ru/es carrying the UI copy, not only the error keys, because the storefront is
61
+ ru-first and a half-translated submission form is visible immediately.
62
+
63
+ Generated against stapel-listings **0.6.1** — the release that fixed
64
+ `FeatureDto`/`FeatureDao`'s `discriminator.mapping` from one bogus `"null"`
65
+ entry to the ten type slugs, which is what makes the generated union usable as
66
+ the wire type at all.
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Stapel contributors
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -146,7 +146,7 @@ export interface ListingPageParams {
146
146
  /**
147
147
  * The currency a composer starts a new listing in.
148
148
  *
149
- * RUB by owner verdict F6 (`tasks/darom-storefront-design.md`, the owner's
149
+ * RUB by owner verdict F6 (storefront spec, the owner's
150
150
  * fork verdicts of 2026-08-22), and a default rather than a constant: `currency` is
151
151
  * a free `maxLength: 8` string on the wire (stapel-listings has no currency
152
152
  * enum — the vocabulary lives in stapel-currencies), so a deployment that
package/dist/api/types.js CHANGED
@@ -27,7 +27,7 @@ export const MODERATION_STATUSES = [
27
27
  /**
28
28
  * The currency a composer starts a new listing in.
29
29
  *
30
- * RUB by owner verdict F6 (`tasks/darom-storefront-design.md`, the owner's
30
+ * RUB by owner verdict F6 (storefront spec, the owner's
31
31
  * fork verdicts of 2026-08-22), and a default rather than a constant: `currency` is
32
32
  * a free `maxLength: 8` string on the wire (stapel-listings has no currency
33
33
  * enum — the vocabulary lives in stapel-currencies), so a deployment that
package/dist/i18n/ru.d.ts CHANGED
@@ -6,7 +6,7 @@ export { listingsErrorBundleRu } from "./generated/errors.ru.gen.js";
6
6
  * register it never carry these strings (the main entry does not import this
7
7
  * module — gated by size-limit + the bundle-purity test).
8
8
  *
9
- * This is the storefront's DEFAULT language (darom-storefront verdict F1:
9
+ * This is the storefront's DEFAULT language (storefront spec verdict F1:
10
10
  * ru-first), which is why the UI copy is here in full and not only the error
11
11
  * keys: a seller filling in a listing is the surface where a half-translated
12
12
  * form is most obvious.
package/dist/i18n/ru.js CHANGED
@@ -6,7 +6,7 @@ export { listingsErrorBundleRu } from "./generated/errors.ru.gen.js";
6
6
  * register it never carry these strings (the main entry does not import this
7
7
  * module — gated by size-limit + the bundle-purity test).
8
8
  *
9
- * This is the storefront's DEFAULT language (darom-storefront verdict F1:
9
+ * This is the storefront's DEFAULT language (storefront spec verdict F1:
10
10
  * ru-first), which is why the UI copy is here in full and not only the error
11
11
  * keys: a seller filling in a listing is the surface where a half-translated
12
12
  * form is most obvious.
package/llms.txt CHANGED
@@ -1,4 +1,4 @@
1
- # @stapel/listings-react 0.1.0
1
+ # @stapel/listings-react 0.2.0
2
2
 
3
3
  Headless React flow pair for stapel-listings (contract >=0.6 <0.7) — business + state, zero visual opinion.
4
4
  Built on @stapel/core: typed client + StapelApiError envelope, auth token refresh,
package/manifest.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "$generated": "by scripts/gen-manifest.mjs — do not edit; drift-gated (pnpm gen:manifest:check)",
3
3
  "package": "@stapel/listings-react",
4
- "version": "0.1.0",
4
+ "version": "0.2.0",
5
5
  "backend": {
6
6
  "module": "stapel-listings",
7
7
  "contract": ">=0.6 <0.7"
package/nav-manifest.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "package": "@stapel/listings-react",
3
- "version": "0.1.0",
3
+ "version": "0.2.0",
4
4
  "entries": [
5
5
  {
6
6
  "id": "listings.detail",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@stapel/listings-react",
3
- "version": "0.1.0",
3
+ "version": "0.2.0",
4
4
  "description": "Headless React pair for stapel-listings: a typed client over the draft twin, the composer that turns a category schema into a submittable listing, and the owner's dashboard. Two independent axes are rendered as two — lifecycle `status` decides visibility and `moderation_status` decides nothing about it, so an edit to a live listing stays live and says 'under review' instead of vanishing. Feature values are drawn and mirrored by @stapel/attributes-react; photos arrive as an injected upload bag whose `refs` ARE `images_draft` and whose `settled` gates the submit; a publish refusal is routed onto the control that caused it by slug. Zero visual opinion in the main entry; an opt-in /default subpath ships the antd skin.",
5
5
  "license": "MIT",
6
6
  "repository": {
@@ -46,13 +46,6 @@
46
46
  "nav-manifest.json",
47
47
  "llms.txt"
48
48
  ],
49
- "scripts": {
50
- "build": "tsc -p tsconfig.json",
51
- "test": "tsc -p tsconfig.test.json && vitest run --exclude test/prodBundlePurity.test.ts",
52
- "lint": "eslint .",
53
- "size": "size-limit",
54
- "test:pack": "vitest run test/prodBundlePurity.test.ts"
55
- },
56
49
  "size-limit": [
57
50
  {
58
51
  "name": "index — the headless pair (client + status axes + draft model + hooks): no antd",
@@ -94,12 +87,6 @@
94
87
  },
95
88
  "devDependencies": {
96
89
  "@size-limit/preset-small-lib": "^11.2.0",
97
- "@stapel/attributes-react": "workspace:^",
98
- "@stapel/core": "workspace:^",
99
- "@stapel/image": "workspace:^",
100
- "@stapel/showcase": "workspace:^",
101
- "@stapel/tokens": "workspace:^",
102
- "@stapel/tokens-antd": "workspace:^",
103
90
  "@tanstack/react-query": "^5.81.0",
104
91
  "@testing-library/react": "^16.3.0",
105
92
  "@types/react": "^19.1.0",
@@ -110,12 +97,25 @@
110
97
  "react-dom": "^19.1.0",
111
98
  "size-limit": "^11.2.0",
112
99
  "typescript": "^5.8.3",
113
- "vitest": "^3.2.4"
100
+ "vitest": "^3.2.4",
101
+ "@stapel/attributes-react": "^0.2.0",
102
+ "@stapel/core": "^0.15.0",
103
+ "@stapel/image": "^0.2.0",
104
+ "@stapel/showcase": "^0.2.0",
105
+ "@stapel/tokens": "^0.5.0",
106
+ "@stapel/tokens-antd": "^0.5.0"
114
107
  },
115
108
  "engines": {
116
109
  "node": ">=22"
117
110
  },
118
111
  "publishConfig": {
119
112
  "access": "public"
113
+ },
114
+ "scripts": {
115
+ "build": "tsc -p tsconfig.json",
116
+ "test": "tsc -p tsconfig.test.json && vitest run --exclude test/prodBundlePurity.test.ts",
117
+ "lint": "eslint .",
118
+ "size": "size-limit",
119
+ "test:pack": "vitest run test/prodBundlePurity.test.ts"
120
120
  }
121
- }
121
+ }
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "$generated": "by scripts/gen-events.mjs — do not edit; drift-gated (pnpm gen:events:check)",
3
3
  "package": "@stapel/listings-react",
4
- "version": "0.1.0",
4
+ "version": "0.2.0",
5
5
  "defined": [],
6
6
  "flows": []
7
7
  }