@feedmepos/mf-miniprogram-v2 0.2.2-dev.22 → 0.2.2-dev.23

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.
@@ -1,5 +1,5 @@
1
1
  import { defineComponent as x, resolveComponent as p, openBlock as u, createElementBlock as h, createVNode as E, createElementVNode as P, normalizeClass as F, toDisplayString as v, createCommentVNode as g, createBlock as L, shallowReadonly as r, ref as s } from "vue";
2
- import { a as w } from "./routes-D6BQSP4i.js";
2
+ import { a as w } from "./routes-DPGrYgQQ.js";
3
3
  import { c as M, e as y, m as $ } from "./controlPlane-sXaC6pAh.js";
4
4
  const I = { class: "flex min-h-0 flex-1 flex-col items-center justify-center gap-8 p-24 text-center" }, T = {
5
5
  key: 0,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@feedmepos/mf-miniprogram-v2",
3
- "version": "0.2.2-dev.22",
3
+ "version": "0.2.2-dev.23",
4
4
  "type": "module",
5
5
  "publishConfig": {
6
6
  "access": "public",
@@ -1,364 +0,0 @@
1
- import { defineComponent as N, ref as i, computed as $, resolveComponent as T, openBlock as o, createBlock as O, withCtx as D, createElementVNode as t, createElementBlock as r, Fragment as R, createTextVNode as w, toDisplayString as u, createVNode as d, createCommentVNode as f, onMounted as M, renderList as E, unref as B } from "vue";
2
- import { a as C } from "./routes-D6BQSP4i.js";
3
- import { useDialog as L } from "@feedmepos/ui-library";
4
- import { useRouter as U } from "vue-router";
5
- import { c as F, e as P } from "./controlPlane-sXaC6pAh.js";
6
- import { _ as S } from "./_plugin-vue_export-helper-CHgC5LLL.js";
7
- const z = [
8
- // `label` and `description` are MERCHANT-FACING: the portal's picker renders
9
- // them, and they are the only thing a merchant chooses on. Say what the app does
10
- // for their customers, never which package it is built from — the SDK is real and
11
- // load-bearing and means nothing to the person making this decision. These are
12
- // the exact texts merchants were already seeing via the old choice layer's own
13
- // label/description (kept verbatim across its removal — a refactor is not the
14
- // moment to also silently change picker copy).
15
- {
16
- id: "miniprogram-vue",
17
- label: "V1 · Phone ordering",
18
- description: "The established phone ordering experience with menu, checkout, membership, rewards and order history.",
19
- industries: [],
20
- environments: ["dev", "prod"],
21
- default: !0
22
- },
23
- {
24
- id: "miniprogram-vue-v2",
25
- label: "V2 · Baseline",
26
- description: "The FeedMe v1 customer app's interface, on the v2 kernel: order medallions, the order-history rail, a category rail beside a continuous menu, and the round reviewed in a sheet. The baseline every other v2 style departs from.",
27
- industries: ["Food & beverage"],
28
- // Dev only, deliberately. It has never been provisioned end-to-end: the
29
- // preview proxy, the component-library unpack and the release build have
30
- // only been exercised locally. Add 'prod' after a real merchant has run
31
- // through all three.
32
- environments: ["dev"],
33
- restaurantStyle: "qsr"
34
- },
35
- // Forked from miniprogram-vue-v2 (2026-09): the coffee and tea styles used
36
- // to be a `restaurantStyle` sharing that one directory, which meant editing
37
- // one style's components risked changing what the other two rendered. Each
38
- // now has its own independent directory; only `templates/block-library/` is
39
- // still shared across all three.
40
- {
41
- id: "miniprogram-vue-v2-coffee",
42
- label: "V2 · Coffee house",
43
- description: "A calm, image-led experience for habitual pickup, premium drinks and considered customisation.",
44
- industries: ["Food & beverage"],
45
- environments: ["dev"],
46
- restaurantStyle: "coffee"
47
- },
48
- {
49
- id: "miniprogram-vue-v2-tea",
50
- label: "V2 · Tea & beverage",
51
- description: "A light, compact and option-forward experience for repeat beverage orders with many customisations.",
52
- industries: ["Food & beverage"],
53
- environments: ["dev"],
54
- restaurantStyle: "tea"
55
- }
56
- ], G = ["href"], H = {
57
- key: 0,
58
- class: "portal-error",
59
- role: "alert"
60
- }, J = "miniprogram-vue-v2", W = /* @__PURE__ */ N({
61
- __name: "ForkTemplateDialog",
62
- emits: ["close", "created"],
63
- setup(j, { emit: V }) {
64
- const _ = V, p = i(""), m = i(""), g = i(""), c = i(!1), s = i(""), v = i(""), A = i(0), h = /^[a-z][a-z0-9]*(-[a-z0-9]+)*$/, x = $(
65
- () => !c.value && h.test(p.value.trim()) && m.value.trim().length > 0 && g.value.trim().length > 0
66
- );
67
- async function q() {
68
- if (x.value) {
69
- c.value = !0, s.value = "";
70
- try {
71
- const y = await F(C.forkAppTemplate(), {
72
- method: "POST",
73
- body: JSON.stringify({
74
- sourceAppTemplateId: J,
75
- newAppTemplateId: p.value.trim(),
76
- label: m.value.trim(),
77
- description: g.value.trim()
78
- })
79
- });
80
- v.value = y.pullRequestUrl, A.value = y.fileCount, _("created");
81
- } catch (y) {
82
- s.value = P(y);
83
- } finally {
84
- c.value = !1;
85
- }
86
- }
87
- }
88
- return (y, n) => {
89
- const k = T("FmButton"), a = T("FmTextField"), l = T("FmTextarea"), b = T("FmCard");
90
- return o(), O(b, { class: "fork-template-dialog" }, {
91
- default: D(() => [
92
- n[7] || (n[7] = t("h2", null, "Create template", -1)),
93
- v.value ? (o(), r(R, { key: 0 }, [
94
- t("p", null, [
95
- w(" Opened a pull request copying " + u(A.value) + " file(s) into a brand-new ", 1),
96
- t("code", null, "templates/" + u(p.value) + "/", 1),
97
- n[5] || (n[5] = w(" directory, and registering it in the template catalog. It needs human review and merge — once merged and deployed, it appears here and in the merchant picker automatically; there is no separate step to enable it. ", -1))
98
- ]),
99
- t("footer", null, [
100
- t("a", {
101
- class: "fork-template-dialog__review-link",
102
- href: v.value,
103
- target: "_blank",
104
- rel: "noopener"
105
- }, "Review PR", 8, G),
106
- d(k, {
107
- label: "Done",
108
- onClick: n[0] || (n[0] = (e) => _("close"))
109
- })
110
- ])
111
- ], 64)) : (o(), r(R, { key: 1 }, [
112
- n[6] || (n[6] = t("p", { class: "fork-template-dialog__note" }, " Copies the v2 baseline template's whole directory into a brand-new, independent one — editing the new one can never affect the baseline or any other template. Use this to start a new restaurant style rather than editing a style that other merchants already share. ", -1)),
113
- d(a, {
114
- modelValue: p.value,
115
- "onUpdate:modelValue": n[1] || (n[1] = (e) => p.value = e),
116
- label: "New template id",
117
- placeholder: "e.g. miniprogram-vue-v2-bakery",
118
- "helper-text": "Lowercase, kebab-case. Also becomes the directory name and GitHub repository name.",
119
- disabled: c.value,
120
- rules: [(e) => h.test(e.trim()) || "Lowercase kebab-case, e.g. miniprogram-vue-v2-bakery"]
121
- }, null, 8, ["modelValue", "disabled", "rules"]),
122
- d(a, {
123
- modelValue: m.value,
124
- "onUpdate:modelValue": n[2] || (n[2] = (e) => m.value = e),
125
- label: "Label",
126
- placeholder: "Shown to merchants in the picker",
127
- disabled: c.value
128
- }, null, 8, ["modelValue", "disabled"]),
129
- d(l, {
130
- modelValue: g.value,
131
- "onUpdate:modelValue": n[3] || (n[3] = (e) => g.value = e),
132
- label: "Description",
133
- placeholder: "One or two sentences on what the merchant gets",
134
- disabled: c.value
135
- }, null, 8, ["modelValue", "disabled"]),
136
- s.value ? (o(), r("p", H, u(s.value), 1)) : f("", !0),
137
- t("footer", null, [
138
- d(k, {
139
- label: "Cancel",
140
- variant: "tertiary",
141
- disabled: c.value,
142
- onClick: n[4] || (n[4] = (e) => _("close"))
143
- }, null, 8, ["disabled"]),
144
- d(k, {
145
- label: "Open pull request",
146
- loading: c.value,
147
- disabled: !x.value,
148
- onClick: q
149
- }, null, 8, ["loading", "disabled"])
150
- ])
151
- ], 64))
152
- ]),
153
- _: 1
154
- });
155
- };
156
- }
157
- }), K = /* @__PURE__ */ S(W, [["__scopeId", "data-v-5a38928f"]]), Q = { class: "portal-page" }, X = { class: "portal-page-inner" }, Y = { class: "portal-page-heading" }, Z = { class: "portal-page-heading__actions" }, ee = {
158
- key: 0,
159
- class: "portal-error",
160
- role: "alert"
161
- }, te = {
162
- key: 1,
163
- "aria-label": "Templates in review"
164
- }, ae = { class: "template-section-heading" }, le = {
165
- key: 0,
166
- class: "portal-error",
167
- role: "alert"
168
- }, ne = {
169
- key: 1,
170
- class: "template-choices__list",
171
- "aria-label": "Templates in review"
172
- }, oe = { class: "template-choices__name" }, se = { class: "template-choices__label" }, re = { class: "template-choices__id" }, ie = { class: "template-choices__actions" }, ce = ["href"], ue = {
173
- class: "template-choices__list",
174
- "aria-label": "Physical templates"
175
- }, de = { class: "template-choices__name" }, pe = { class: "template-choices__label" }, me = { key: 0 }, ve = { class: "template-choices__id" }, he = { class: "template-choices__meta" }, ge = { class: "template-choices__actions" }, _e = /* @__PURE__ */ N({
176
- __name: "TemplateCenterView",
177
- setup(j) {
178
- const V = U(), _ = L(), p = i(""), m = i(null), g = i([]), c = i(!1), s = i("");
179
- async function v() {
180
- c.value = !0, s.value = "";
181
- try {
182
- const a = await F(C.pendingTemplateForks());
183
- g.value = a.forks;
184
- } catch (a) {
185
- s.value = P(a);
186
- } finally {
187
- c.value = !1;
188
- }
189
- }
190
- function A() {
191
- _.open({
192
- title: "Create template",
193
- dialogComponent: K,
194
- dialogComponentProps: { onClose: () => _.close(), onCreated: () => void v() }
195
- });
196
- }
197
- const h = i(null);
198
- async function x(a) {
199
- h.value = a.pullRequestNumber, s.value = "";
200
- try {
201
- await F(C.mergePendingTemplateFork(a.pullRequestNumber), { method: "POST" }), await v();
202
- } catch (l) {
203
- s.value = P(l);
204
- } finally {
205
- h.value = null;
206
- }
207
- }
208
- async function q(a) {
209
- h.value = a.pullRequestNumber, s.value = "";
210
- try {
211
- await F(C.rejectPendingTemplateFork(a.pullRequestNumber), { method: "POST" }), await v();
212
- } catch (l) {
213
- s.value = P(l);
214
- } finally {
215
- h.value = null;
216
- }
217
- }
218
- function y(a) {
219
- _.open({
220
- title: `Merge ${a.newAppTemplateId}?`,
221
- message: "Merges the pull request into main as-is, without a code review step here. The new template takes effect on the next control-plane deploy.",
222
- primaryActions: { text: "Merge", close: !0, variant: "primary" },
223
- secondaryActions: { text: "Cancel", close: !0, variant: "tertiary" }
224
- }).onPrimary(() => void x(a));
225
- }
226
- function n(a) {
227
- _.open({
228
- title: `Reject ${a.newAppTemplateId}?`,
229
- message: "Closes the pull request without merging and deletes its branch. Nothing of this template is kept.",
230
- primaryActions: { text: "Reject", close: !0, variant: "destructive" },
231
- secondaryActions: { text: "Cancel", close: !0, variant: "tertiary" }
232
- }).onPrimary(() => void q(a));
233
- }
234
- M(() => void v());
235
- async function k(a) {
236
- if (!m.value) {
237
- m.value = a, p.value = "";
238
- try {
239
- const l = await F(
240
- C.appTemplateEditingProject(a),
241
- { method: "POST" }
242
- );
243
- await V.push({
244
- name: "miniprogram-v2-project",
245
- params: { projectId: l.projectId, view: "workspace" },
246
- query: { tpl: "1" }
247
- });
248
- } catch (l) {
249
- p.value = P(l);
250
- } finally {
251
- m.value = null;
252
- }
253
- }
254
- }
255
- return (a, l) => {
256
- const b = T("FmButton");
257
- return o(), r("div", Q, [
258
- t("div", X, [
259
- t("header", Y, [
260
- l[1] || (l[1] = t("div", null, [
261
- t("p", { class: "portal-eyebrow" }, "Internal"),
262
- t("h1", null, "Template library")
263
- ], -1)),
264
- t("div", Z, [
265
- d(b, {
266
- label: "Create template",
267
- variant: "primary",
268
- onClick: l[0] || (l[0] = (e) => A())
269
- })
270
- ])
271
- ]),
272
- p.value ? (o(), r("p", ee, u(p.value), 1)) : f("", !0),
273
- s.value || g.value.length > 0 ? (o(), r("section", te, [
274
- t("div", ae, [
275
- l[2] || (l[2] = t("h2", { class: "template-section-title" }, "In review", -1)),
276
- d(b, {
277
- label: "Refresh",
278
- variant: "tertiary",
279
- size: "md",
280
- loading: c.value,
281
- onClick: v
282
- }, null, 8, ["loading"])
283
- ]),
284
- l[3] || (l[3] = t("p", { class: "template-section-note" }, " Waiting on PR review and merge. A row disappears on its own once its pull request merges or is closed — click Refresh to check. ", -1)),
285
- s.value ? (o(), r("p", le, [
286
- w(u(s.value) + " ", 1),
287
- d(b, {
288
- label: "Retry",
289
- variant: "tertiary",
290
- onClick: v
291
- })
292
- ])) : f("", !0),
293
- g.value.length > 0 ? (o(), r("section", ne, [
294
- (o(!0), r(R, null, E(g.value, (e) => (o(), r("article", {
295
- key: e.newAppTemplateId,
296
- class: "template-choices__row"
297
- }, [
298
- t("div", oe, [
299
- t("span", se, u(e.newAppTemplateId), 1),
300
- t("span", re, "Awaiting review — PR #" + u(e.pullRequestNumber), 1)
301
- ]),
302
- t("div", ie, [
303
- t("a", {
304
- class: "template-review-link",
305
- href: e.pullRequestUrl,
306
- target: "_blank",
307
- rel: "noopener"
308
- }, "Review PR", 8, ce),
309
- d(b, {
310
- label: "Merge",
311
- variant: "primary",
312
- loading: h.value === e.pullRequestNumber,
313
- disabled: h.value !== null,
314
- onClick: (I) => y(e)
315
- }, null, 8, ["loading", "disabled", "onClick"]),
316
- d(b, {
317
- label: "Reject",
318
- variant: "destructive",
319
- disabled: h.value !== null,
320
- onClick: (I) => n(e)
321
- }, null, 8, ["disabled", "onClick"])
322
- ])
323
- ]))), 128))
324
- ])) : f("", !0)
325
- ])) : f("", !0),
326
- l[4] || (l[4] = t("h2", { class: "template-section-title" }, "Physical templates", -1)),
327
- l[5] || (l[5] = t("p", { class: "template-section-note" }, ' "Edit code" opens the physical template directly — the same chat + live preview a merchant project gets, saving straight to a pull request against this repo instead of a merchant repo. ', -1)),
328
- t("section", ue, [
329
- (o(!0), r(R, null, E(B(z), (e) => (o(), r("article", {
330
- key: e.id,
331
- class: "template-choices__row"
332
- }, [
333
- t("div", de, [
334
- t("span", pe, [
335
- w(u(e.label), 1),
336
- e.default ? (o(), r("span", me, " · Default")) : f("", !0)
337
- ]),
338
- t("span", ve, u(e.id), 1),
339
- t("span", he, [
340
- e.restaurantStyle ? (o(), r(R, { key: 0 }, [
341
- w(u(e.restaurantStyle) + " · ", 1)
342
- ], 64)) : f("", !0),
343
- w(u(e.industries.join(", ") || "General-purpose") + " · " + u(e.environments.join(", ")), 1)
344
- ])
345
- ]),
346
- t("div", ge, [
347
- d(b, {
348
- label: "Edit code",
349
- variant: "secondary",
350
- loading: m.value === e.id,
351
- disabled: m.value !== null,
352
- onClick: (I) => k(e.id)
353
- }, null, 8, ["loading", "disabled", "onClick"])
354
- ])
355
- ]))), 128))
356
- ])
357
- ])
358
- ]);
359
- };
360
- }
361
- }), Ce = /* @__PURE__ */ S(_e, [["__scopeId", "data-v-a2c82260"]]);
362
- export {
363
- Ce as default
364
- };
@@ -1,81 +0,0 @@
1
- const t = (e, s) => `/api/businesses/${e}/projects/${s}`, r = {
2
- projects: (e) => `/api/businesses/${e}/projects`,
3
- portalContext: (e) => `/api/businesses/${e}/portal-context`,
4
- project: (e, s) => t(e, s),
5
- provision: (e, s) => `${t(e, s)}/provision`,
6
- refreshSlug: (e, s) => `${t(e, s)}/refresh-slug`,
7
- sessions: (e, s) => `${t(e, s)}/sessions`,
8
- session: (e, s, i) => `${t(e, s)}/sessions/${i}`,
9
- messages: (e, s, i) => `${r.session(e, s, i)}/messages`,
10
- startStatus: (e, s, i) => `${r.session(e, s, i)}/start-status`,
11
- changes: (e, s, i, a = !1) => `${r.session(e, s, i)}/changes${a ? "?refresh=1" : ""}`,
12
- checkpoints: (e, s, i) => `${r.session(e, s, i)}/checkpoints`,
13
- aiBillingPreflight: (e, s, i) => `${r.session(e, s, i)}/ai-billing/preflight`,
14
- restoreCheckpoint: (e, s, i, a) => `${r.checkpoints(e, s, i)}/${a}/restore`,
15
- previewBridgeTicket: (e, s, i) => `${r.session(e, s, i)}/preview-bridge/ticket`,
16
- previewBridgeSocket: (e, s, i) => `${r.session(e, s, i)}/preview-bridge/socket`,
17
- uploads: (e, s, i, a = "") => `${r.session(e, s, i)}/uploads${a ? `?${a}` : ""}`,
18
- archive: (e, s, i) => `${r.session(e, s, i)}/archive`,
19
- commit: (e, s, i) => `${r.session(e, s, i)}/commit`,
20
- resume: (e, s, i) => `${r.session(e, s, i)}/resume`,
21
- restartPreview: (e, s, i) => `${r.session(e, s, i)}/restart-preview`,
22
- fork: (e, s, i) => `${r.session(e, s, i)}/fork`,
23
- flushEvents: (e, s, i) => `${r.session(e, s, i)}/events/flush`,
24
- revertTurn: (e, s, i) => `${r.session(e, s, i)}/turns/revert`,
25
- unrevertTurn: (e, s, i) => `${r.session(e, s, i)}/turns/unrevert`,
26
- releases: (e, s) => `${t(e, s)}/releases`,
27
- /** Internal-admin only. Extracts a new restaurant style out of a session's
28
- * verified checkpoint and, once confirmed, opens a PR against this repo. */
29
- publishAsTemplate: (e, s) => `${t(e, s)}/publish-as-template`,
30
- publishRelease: (e, s, i) => `${r.releases(e, s)}/${i}/publish`,
31
- releasePreviewUrl: (e, s, i) => `${r.releases(e, s)}/${i}/preview-url`,
32
- rollbackToRelease: (e, s, i) => `${t(e, s)}/rollback-to-release/${i}`,
33
- rollbackToV1: (e, s) => `${t(e, s)}/rollback-to-v1`,
34
- start: (e, s, i) => {
35
- const a = new URLSearchParams();
36
- e && a.set("businessId", e), s && a.set("projectId", s), i && a.set("sessionId", i);
37
- const o = a.toString();
38
- return `/api/start${o ? `?${o}` : ""}`;
39
- },
40
- opencode: (e = "") => `/api/opencode${e ? `/${e.replace(/^\/+/, "")}` : ""}`,
41
- /** The shared component library's catalog. Deliberately not under a
42
- * business/project path: the library belongs to no business, and the
43
- * module centre is not inside a workspace. */
44
- componentLibraryCatalog: () => "/api/component-library/catalog",
45
- /** The self-contained preview document the module centre frames. Fetched with
46
- * the portal's bearer and assigned to an iframe's `srcdoc`, never used as an
47
- * `<iframe src>` — a navigation request carries no Authorization header,
48
- * which is what a signed URL would otherwise exist to work around. */
49
- componentLibraryPreview: () => "/api/component-library/preview",
50
- /** The application templates this environment can provision, for the portal's
51
- * picker. Not under a business/project path: the answer is a property of
52
- * the environment, and it is needed BEFORE a project exists. */
53
- appTemplates: () => "/api/app-templates",
54
- /** Whether the caller is an internal admin — for the portal to decide whether to
55
- * show internal-only entry points such as the Template Center. The real
56
- * enforcement is on every admin route itself; this is a UI convenience. */
57
- adminWhoami: () => "/api/admin/whoami",
58
- /** Template Center: fork an existing physical template directory into a
59
- * brand-new one, as a PR against this repo (see `template-fork.ts`). Not
60
- * project-scoped — a physical template belongs to no business. */
61
- forkAppTemplate: () => "/api/admin/app-templates/fork",
62
- /** Template Center: physical templates whose "create template" PR is still
63
- * open — read live from GitHub, not a stored list, so a row disappears the
64
- * moment its PR merges or is closed. */
65
- pendingTemplateForks: () => "/api/admin/app-templates/pending-forks",
66
- /** Template Center: merge a pending template fork's PR directly from the
67
- * "In review" list, without leaving the portal. Refuses to act on
68
- * anything that is not itself a pending template-fork PR. */
69
- mergePendingTemplateFork: (e) => `/api/admin/app-templates/pending-forks/${e}/merge`,
70
- /** Template Center: close a pending template fork's PR without merging and
71
- * delete its branch — the "In review" list's reject action. */
72
- rejectPendingTemplateFork: (e) => `/api/admin/app-templates/pending-forks/${e}/reject`,
73
- /** Template Center: find-or-create the template-editing project a
74
- * physical template edits through — the same chat/preview/checkpoint
75
- * workspace a merchant project gets, pointed at `templates/<id>/` in this
76
- * repo instead. Internal-admin only. */
77
- appTemplateEditingProject: (e) => `/api/admin/app-templates/${e}/editing-project`
78
- };
79
- export {
80
- r as a
81
- };