@arkstack/view 0.8.0 → 0.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.d.ts CHANGED
@@ -26,6 +26,10 @@ declare class ViewInstance implements PromiseLike<string> {
26
26
  }
27
27
  //#endregion
28
28
  //#region src/types.d.ts
29
+ type ViewErrorValue = string | string[] | Error | {
30
+ message?: unknown;
31
+ } | unknown;
32
+ type ViewErrorRecord = Record<string, ViewErrorValue>;
29
33
  type ComposerRunner = (view: ViewInstance) => Promise<void>;
30
34
  type SyncComposerRunner = (view: ViewInstance) => void;
31
35
  type ViewData = Record<string, any>;
@@ -87,10 +91,6 @@ declare class View {
87
91
  }
88
92
  //#endregion
89
93
  //#region src/ViewErrorBag.d.ts
90
- type ViewErrorValue = string | string[] | Error | {
91
- message?: unknown;
92
- } | unknown;
93
- type ViewErrorRecord = Record<string, ViewErrorValue>;
94
94
  declare class ViewErrorBag {
95
95
  private bag;
96
96
  constructor(errors?: ViewErrorRecord | ViewErrorBag | unknown);
@@ -141,5 +141,5 @@ declare const runWithViewData: <T>(data: ViewData, callback: () => T | Promise<T
141
141
  declare const clearViewData: () => void;
142
142
  declare const collectViewData: (context: Record<string, any>) => ViewData;
143
143
  //#endregion
144
- export { ComposerRunner, Edge, SyncComposerRunner, View, ViewComposer, ViewComposerClass, ViewComposerHandler, ViewComposerName, ViewComposerObject, ViewData, ViewErrorBag, ViewFactory, ViewFactoryOptions, ViewInstance, ViewName, clearRouterViewPlugin, clearViewData, collectViewData, edge, enterViewData, getViewData, normalizeViewErrors, parsePackageViewName, resolvePackageViewsPath, runWithViewData, view };
144
+ export { ComposerRunner, Edge, SyncComposerRunner, View, ViewComposer, ViewComposerClass, ViewComposerHandler, ViewComposerName, ViewComposerObject, ViewData, ViewErrorBag, ViewErrorRecord, ViewErrorValue, ViewFactory, ViewFactoryOptions, ViewInstance, ViewName, clearRouterViewPlugin, clearViewData, collectViewData, edge, enterViewData, getViewData, normalizeViewErrors, parsePackageViewName, resolvePackageViewsPath, runWithViewData, view };
145
145
  //# sourceMappingURL=index.d.ts.map
package/dist/index.js CHANGED
@@ -1,255 +1,3 @@
1
- import { a as getViewData, c as normalizeViewErrors, i as enterViewData, n as clearViewData, o as runWithViewData, r as collectViewData, s as ViewErrorBag, t as clearRouterViewPlugin } from "./plugins-C5X8pT4o.js";
2
- import { existsSync } from "node:fs";
3
- import { resolve } from "node:path";
4
- import edge, { Edge, Edge as Edge$1 } from "edge.js";
5
- //#region src/helpers.ts
6
- function view(name, data = {}) {
7
- if (name === void 0) return View.factoryInstance();
8
- return View.make(name, data);
9
- }
10
- const isClass = (target) => {
11
- return typeof target === "function" && /^class\s/.test(Function.prototype.toString.call(target));
12
- };
13
- const normalizeViewData = (data = {}) => {
14
- return {
15
- ...data,
16
- errors: normalizeViewErrors(data.errors)
17
- };
18
- };
19
- const mergeData = (target, data) => {
20
- if (data.length === 0) return target;
21
- if (typeof data[0] === "string") {
22
- target[data[0]] = data[0] === "errors" ? normalizeViewErrors(data[1]) : data[1];
23
- return target;
24
- }
25
- for (const value of data) if (value && typeof value === "object" && !Array.isArray(value)) Object.assign(target, normalizeViewData(value));
26
- return target;
27
- };
28
- const runComposerSync = (composer, view) => {
29
- const result = runComposer(composer, view);
30
- if (result && typeof result.then === "function") throw new Error("Async view composers cannot be used with renderSync.");
31
- };
32
- const runComposer = (composer, view) => {
33
- if (typeof composer === "function") {
34
- if (isClass(composer)) return new composer().compose(view);
35
- return composer(view);
36
- }
37
- return composer.compose(view);
38
- };
39
- //#endregion
40
- //#region src/packageViews.ts
41
- const parsePackageViewName = (name) => {
42
- if (!name.startsWith("~")) return null;
43
- const source = name.slice(1);
44
- const slashIndex = source.indexOf("/");
45
- const dotIndex = slashIndex === -1 ? source.indexOf(".") : source.indexOf(".", slashIndex);
46
- if (dotIndex <= 0) throw new Error(`Invalid package view name: ${name}`);
47
- const packageName = source.slice(0, dotIndex);
48
- const viewName = source.slice(dotIndex + 1);
49
- if (!viewName) throw new Error(`Invalid package view name: ${name}`);
50
- const nodePackageName = slashIndex === -1 ? packageName : `@${packageName}`;
51
- const diskName = `package_${packageName.replace(/[^a-zA-Z0-9_-]/g, "_")}`;
52
- return {
53
- source: name,
54
- packageName,
55
- nodePackageName,
56
- diskName,
57
- viewName,
58
- edgeName: `${diskName}::${viewName}`
59
- };
60
- };
61
- const resolvePackageViewsPath = (nodePackageName, viewPath = "resources/views") => {
62
- const viewsPath = resolve(resolve(process.cwd(), "node_modules", nodePackageName), viewPath);
63
- if (!existsSync(viewsPath)) throw new Error(`Package views directory not found: ${viewsPath}`);
64
- return viewsPath;
65
- };
66
- //#endregion
67
- //#region src/ViewInstance.ts
68
- var ViewInstance = class {
69
- name;
70
- renderer;
71
- runComposers;
72
- runComposersSync;
73
- renderName;
74
- payload;
75
- composersHaveRun = false;
76
- constructor(name, data = {}, renderer, runComposers, runComposersSync, renderName = name) {
77
- this.name = name;
78
- this.renderer = renderer;
79
- this.runComposers = runComposers;
80
- this.runComposersSync = runComposersSync;
81
- this.renderName = renderName;
82
- this.payload = normalizeViewData({ ...data });
83
- }
84
- get data() {
85
- return this.payload;
86
- }
87
- with(...data) {
88
- mergeData(this.payload, data);
89
- return this;
90
- }
91
- async render() {
92
- await this.compose();
93
- return await this.renderer.render(this.renderName, this.payload);
94
- }
95
- renderSync() {
96
- this.composeSync();
97
- return this.renderer.renderSync(this.renderName, this.payload);
98
- }
99
- then(onfulfilled, onrejected) {
100
- return this.render().then(onfulfilled, onrejected);
101
- }
102
- async compose() {
103
- if (this.composersHaveRun) return;
104
- this.composersHaveRun = true;
105
- await this.runComposers(this);
106
- }
107
- composeSync() {
108
- if (this.composersHaveRun) return;
109
- this.composersHaveRun = true;
110
- this.runComposersSync(this);
111
- }
112
- };
113
- //#endregion
114
- //#region src/ViewFactory.ts
115
- var ViewFactory = class {
116
- edge;
117
- sharedData = {};
118
- composers = /* @__PURE__ */ new Map();
119
- mountedPackages = /* @__PURE__ */ new Set();
120
- packageViewsPath;
121
- constructor(options = {}) {
122
- this.edge = options.edge ?? Edge$1.create({ cache: options.cache });
123
- this.packageViewsPath = options.packageViewsPath ?? "resources/views";
124
- this.mount(options.viewsPath ?? resolve(process.cwd(), "src", "resources", "views"));
125
- }
126
- make(name, data = {}) {
127
- const edgeName = this.resolveName(name);
128
- return new ViewInstance(name, normalizeViewData({
129
- ...this.sharedData,
130
- ...getViewData(),
131
- ...data
132
- }), this.edge, async (view) => await this.runComposers(name, view), (view) => this.runComposersSync(name, view), edgeName);
133
- }
134
- first(names, data = {}) {
135
- const name = names.find((candidate) => this.exists(candidate));
136
- if (!name) throw new Error(`None of the given views exist: ${names.join(", ")}`);
137
- return this.make(name, data);
138
- }
139
- exists(name) {
140
- const edgeName = this.resolveName(name);
141
- if (this.edge.loader.templates[edgeName]) return true;
142
- try {
143
- return existsSync(this.edge.loader.makePath(edgeName));
144
- } catch {
145
- return false;
146
- }
147
- }
148
- share(...data) {
149
- mergeData(this.sharedData, data);
150
- return this;
151
- }
152
- composer(names, composer) {
153
- for (const name of Array.isArray(names) ? names : [names]) this.composers.set(name, [...this.composers.get(name) ?? [], composer]);
154
- return this;
155
- }
156
- mount(diskName, viewsDirectory) {
157
- if (viewsDirectory === void 0) {
158
- this.edge.mount(diskName);
159
- return this;
160
- }
161
- this.edge.mount(diskName, viewsDirectory);
162
- return this;
163
- }
164
- raw(name, contents) {
165
- this.edge.registerTemplate(name, { template: contents });
166
- return this;
167
- }
168
- flushShared() {
169
- this.sharedData = {};
170
- return this;
171
- }
172
- flushComposers() {
173
- this.composers.clear();
174
- return this;
175
- }
176
- getComposers(name) {
177
- const edgeName = this.resolveName(name);
178
- return [
179
- ...this.composers.get("*") ?? [],
180
- ...this.composers.get(edgeName) ?? [],
181
- ...this.composers.get(name) ?? []
182
- ];
183
- }
184
- async runComposers(name, view) {
185
- for (const composer of this.getComposers(name)) await runComposer(composer, view);
186
- }
187
- runComposersSync(name, view) {
188
- for (const composer of this.getComposers(name)) runComposerSync(composer, view);
189
- }
190
- resolveName(name) {
191
- const packageView = parsePackageViewName(name);
192
- if (!packageView) return name;
193
- if (!this.mountedPackages.has(packageView.diskName)) {
194
- this.mount(packageView.diskName, resolvePackageViewsPath(packageView.nodePackageName, this.packageViewsPath));
195
- this.mountedPackages.add(packageView.diskName);
196
- }
197
- return packageView.edgeName;
198
- }
199
- };
200
- //#endregion
201
- //#region src/View.ts
202
- var View = class View {
203
- static factory = new ViewFactory();
204
- /**
205
- * Bootstrap the view service
206
- */
207
- static boot() {
208
- Object.defineProperty(globalThis, "view", {
209
- value: (name, data = {}) => {
210
- if (name === void 0) return View.factoryInstance();
211
- return View.make(name, data);
212
- },
213
- configurable: true,
214
- writable: true
215
- });
216
- }
217
- static configure(options = {}) {
218
- this.factory = new ViewFactory(options);
219
- return this.factory;
220
- }
221
- static factoryInstance() {
222
- return this.factory;
223
- }
224
- static make(name, data = {}) {
225
- return this.factory.make(name, data);
226
- }
227
- static first(names, data = {}) {
228
- return this.factory.first(names, data);
229
- }
230
- static exists(name) {
231
- return this.factory.exists(name);
232
- }
233
- static share(...data) {
234
- if (typeof data[0] === "string") this.factory.share(data[0], data[1]);
235
- else this.factory.share(data[0] ?? {});
236
- return this;
237
- }
238
- static composer(names, composer) {
239
- this.factory.composer(names, composer);
240
- return this;
241
- }
242
- static mount(diskName, viewsDirectory) {
243
- if (viewsDirectory === void 0) this.factory.mount(diskName);
244
- else this.factory.mount(diskName, viewsDirectory);
245
- return this;
246
- }
247
- static raw(name, contents) {
248
- this.factory.raw(name, contents);
249
- return this;
250
- }
251
- };
252
- //#endregion
1
+ import { a as collectViewData, c as runWithViewData, d as resolvePackageViewsPath, f as view, i as clearViewData, l as ViewInstance, m as normalizeViewErrors, n as View, o as enterViewData, p as ViewErrorBag, r as ViewFactory, s as getViewData, t as clearRouterViewPlugin, u as parsePackageViewName } from "./plugins-OaO2BC-T.js";
2
+ import edge, { Edge } from "edge.js";
253
3
  export { Edge, View, ViewErrorBag, ViewFactory, ViewInstance, clearRouterViewPlugin, clearViewData, collectViewData, edge, enterViewData, getViewData, normalizeViewErrors, parsePackageViewName, resolvePackageViewsPath, runWithViewData, view };
254
-
255
- //# sourceMappingURL=index.js.map
@@ -0,0 +1,460 @@
1
+ import { existsSync } from "node:fs";
2
+ import { resolve } from "node:path";
3
+ import { Edge } from "edge.js";
4
+ import { AsyncLocalStorage } from "node:async_hooks";
5
+ import { definePlugin } from "clear-router/core";
6
+ //#region src/ViewErrorBag.ts
7
+ const defaultErrorKey = "_";
8
+ var ViewErrorBag = class ViewErrorBag {
9
+ bag = {};
10
+ constructor(errors) {
11
+ if (errors) this.merge(errors);
12
+ }
13
+ add(field, message) {
14
+ const key = field || defaultErrorKey;
15
+ const messages = toMessages(message);
16
+ if (!messages.length) return this;
17
+ this.bag[key] = [...this.bag[key] || [], ...messages];
18
+ return this;
19
+ }
20
+ merge(errors) {
21
+ const incoming = errors instanceof ViewErrorBag ? errors.toJSON() : getMessageRecord(errors) || (isRecord(errors) ? errors : void 0);
22
+ if (!incoming) return this;
23
+ for (const [field, messages] of Object.entries(incoming)) this.add(field, messages);
24
+ return this;
25
+ }
26
+ keys() {
27
+ return Object.keys(this.bag);
28
+ }
29
+ get(field = defaultErrorKey) {
30
+ return [...this.bag[field] || []];
31
+ }
32
+ first(field) {
33
+ if (field) return this.bag[field]?.[0] || "";
34
+ return this.all()[0] || "";
35
+ }
36
+ has(field) {
37
+ if (Array.isArray(field)) return field.every((key) => this.has(key));
38
+ if (field) return (this.bag[field]?.length || 0) > 0;
39
+ return this.any();
40
+ }
41
+ hasAny(fields) {
42
+ return (Array.isArray(fields) ? fields : [fields]).some((key) => this.has(key));
43
+ }
44
+ missing(fields) {
45
+ return (Array.isArray(fields) ? fields : [fields]).every((key) => !this.has(key));
46
+ }
47
+ any() {
48
+ return Object.values(this.bag).some((messages) => messages.length > 0);
49
+ }
50
+ isEmpty() {
51
+ return !this.any();
52
+ }
53
+ isNotEmpty() {
54
+ return this.any();
55
+ }
56
+ count() {
57
+ return Object.values(this.bag).reduce((total, messages) => total + messages.length, 0);
58
+ }
59
+ all() {
60
+ return Object.values(this.bag).flat();
61
+ }
62
+ unique() {
63
+ return [...new Set(this.all())];
64
+ }
65
+ clear(field) {
66
+ if (Array.isArray(field)) {
67
+ for (const key of field) delete this.bag[key];
68
+ return this;
69
+ }
70
+ if (field) {
71
+ delete this.bag[field];
72
+ return this;
73
+ }
74
+ this.bag = {};
75
+ return this;
76
+ }
77
+ forget(field) {
78
+ return this.clear(field);
79
+ }
80
+ messagesRaw() {
81
+ return this.toJSON();
82
+ }
83
+ getMessages() {
84
+ return this.messagesRaw();
85
+ }
86
+ getMessageBag() {
87
+ return this;
88
+ }
89
+ toArray() {
90
+ return this.toJSON();
91
+ }
92
+ toJSON() {
93
+ return Object.entries(this.bag).reduce((errors, [field, messages]) => {
94
+ errors[field] = [...messages];
95
+ return errors;
96
+ }, {});
97
+ }
98
+ };
99
+ const isViewErrorBag = (value) => {
100
+ return isRecord(value) && typeof value.all === "function" && typeof value.first === "function" && typeof value.get === "function" && typeof value.has === "function";
101
+ };
102
+ const normalizeViewErrors = (errors) => {
103
+ if (isViewErrorBag(errors)) return errors;
104
+ return new ViewErrorBag(errors);
105
+ };
106
+ //#endregion
107
+ //#region src/helpers.ts
108
+ function view(name, data = {}) {
109
+ if (name === void 0) return View.factoryInstance();
110
+ return View.make(name, data);
111
+ }
112
+ const isClass = (target) => {
113
+ return typeof target === "function" && /^class\s/.test(Function.prototype.toString.call(target));
114
+ };
115
+ const currentHttpSession = () => {
116
+ try {
117
+ const session = globalThis.session?.();
118
+ return session && typeof session === "object" ? session : void 0;
119
+ } catch {
120
+ return;
121
+ }
122
+ };
123
+ const hasRenderableErrors = (errors) => {
124
+ if (!errors || typeof errors !== "object") return false;
125
+ const bag = errors;
126
+ if (typeof bag.any === "function") return Boolean(bag.any());
127
+ if (typeof bag.has === "function") return Boolean(bag.has());
128
+ if (typeof bag.isNotEmpty === "function") return Boolean(bag.isNotEmpty());
129
+ if (typeof bag.all === "function") {
130
+ const messages = bag.all();
131
+ if (Array.isArray(messages)) return messages.length > 0;
132
+ return !!messages && typeof messages === "object" && Object.keys(messages).length > 0;
133
+ }
134
+ return Object.keys(bag).length > 0;
135
+ };
136
+ const normalizeViewData = (data = {}) => {
137
+ const session = currentHttpSession();
138
+ const ownErrors = normalizeViewErrors(data.errors);
139
+ const sessionErrors = session?.errors;
140
+ const errors = hasRenderableErrors(ownErrors) || !sessionErrors ? ownErrors : normalizeViewErrors(sessionErrors);
141
+ return {
142
+ ...session && !("session" in data) ? { session } : {},
143
+ ...session && !("httpSession" in data) ? { httpSession: session } : {},
144
+ ...data,
145
+ errors
146
+ };
147
+ };
148
+ const mergeData = (target, data) => {
149
+ if (data.length === 0) return target;
150
+ if (typeof data[0] === "string") {
151
+ target[data[0]] = data[0] === "errors" ? normalizeViewErrors(data[1]) : data[1];
152
+ return target;
153
+ }
154
+ for (const value of data) if (value && typeof value === "object" && !Array.isArray(value)) Object.assign(target, normalizeViewData(value));
155
+ return target;
156
+ };
157
+ const runComposerSync = (composer, view) => {
158
+ const result = runComposer(composer, view);
159
+ if (result && typeof result.then === "function") throw new Error("Async view composers cannot be used with renderSync.");
160
+ };
161
+ const runComposer = (composer, view) => {
162
+ if (typeof composer === "function") {
163
+ if (isClass(composer)) return new composer().compose(view);
164
+ return composer(view);
165
+ }
166
+ return composer.compose(view);
167
+ };
168
+ const isRecord = (value) => {
169
+ return !!value && typeof value === "object" && !Array.isArray(value);
170
+ };
171
+ const toMessages = (value) => {
172
+ if (Array.isArray(value)) return value.flatMap((item) => toMessages(item));
173
+ if (value instanceof Error) return [value.message];
174
+ if (isRecord(value) && typeof value.message === "string") return [value.message];
175
+ if (value === null || typeof value === "undefined") return [];
176
+ return [String(value)];
177
+ };
178
+ const getMessageRecord = (source) => {
179
+ if (!isRecord(source)) return;
180
+ if (typeof source.getMessageBag === "function") {
181
+ const bag = source.getMessageBag();
182
+ if (bag && bag !== source) {
183
+ const messages = getMessageRecord(bag);
184
+ if (messages) return messages;
185
+ }
186
+ }
187
+ for (const method of [
188
+ "getMessages",
189
+ "messagesRaw",
190
+ "toArray"
191
+ ]) if (typeof source[method] === "function") {
192
+ const messages = source[method]();
193
+ if (isRecord(messages)) return messages;
194
+ }
195
+ if (typeof source.errors === "function") {
196
+ const errors = source.errors();
197
+ const messages = getMessageRecord(errors) || (isRecord(errors) ? errors : void 0);
198
+ if (messages) return messages;
199
+ }
200
+ return getMessageRecord(source.errors) || (isRecord(source.errors) ? source.errors : void 0);
201
+ };
202
+ //#endregion
203
+ //#region src/packageViews.ts
204
+ const parsePackageViewName = (name) => {
205
+ if (!name.startsWith("~")) return null;
206
+ const source = name.slice(1);
207
+ const slashIndex = source.indexOf("/");
208
+ const dotIndex = slashIndex === -1 ? source.indexOf(".") : source.indexOf(".", slashIndex);
209
+ if (dotIndex <= 0) throw new Error(`Invalid package view name: ${name}`);
210
+ const packageName = source.slice(0, dotIndex);
211
+ const viewName = source.slice(dotIndex + 1);
212
+ if (!viewName) throw new Error(`Invalid package view name: ${name}`);
213
+ const nodePackageName = slashIndex === -1 ? packageName : `@${packageName}`;
214
+ const diskName = `package_${packageName.replace(/[^a-zA-Z0-9_-]/g, "_")}`;
215
+ return {
216
+ source: name,
217
+ packageName,
218
+ nodePackageName,
219
+ diskName,
220
+ viewName,
221
+ edgeName: `${diskName}::${viewName}`
222
+ };
223
+ };
224
+ const resolvePackageViewsPath = (nodePackageName, viewPath = "resources/views") => {
225
+ const viewsPath = resolve(resolve(process.cwd(), "node_modules", nodePackageName), viewPath);
226
+ if (!existsSync(viewsPath)) throw new Error(`Package views directory not found: ${viewsPath}`);
227
+ return viewsPath;
228
+ };
229
+ //#endregion
230
+ //#region src/ViewInstance.ts
231
+ var ViewInstance = class {
232
+ name;
233
+ renderer;
234
+ runComposers;
235
+ runComposersSync;
236
+ renderName;
237
+ payload;
238
+ composersHaveRun = false;
239
+ constructor(name, data = {}, renderer, runComposers, runComposersSync, renderName = name) {
240
+ this.name = name;
241
+ this.renderer = renderer;
242
+ this.runComposers = runComposers;
243
+ this.runComposersSync = runComposersSync;
244
+ this.renderName = renderName;
245
+ this.payload = normalizeViewData({ ...data });
246
+ }
247
+ get data() {
248
+ return this.payload;
249
+ }
250
+ with(...data) {
251
+ mergeData(this.payload, data);
252
+ return this;
253
+ }
254
+ async render() {
255
+ await this.compose();
256
+ return await this.renderer.render(this.renderName, this.payload);
257
+ }
258
+ renderSync() {
259
+ this.composeSync();
260
+ return this.renderer.renderSync(this.renderName, this.payload);
261
+ }
262
+ then(onfulfilled, onrejected) {
263
+ return this.render().then(onfulfilled, onrejected);
264
+ }
265
+ async compose() {
266
+ if (this.composersHaveRun) return;
267
+ this.composersHaveRun = true;
268
+ await this.runComposers(this);
269
+ }
270
+ composeSync() {
271
+ if (this.composersHaveRun) return;
272
+ this.composersHaveRun = true;
273
+ this.runComposersSync(this);
274
+ }
275
+ };
276
+ //#endregion
277
+ //#region src/viewContext.ts
278
+ const store = new AsyncLocalStorage();
279
+ const normalizeContextData = (data = {}) => normalizeViewData(data);
280
+ const getViewData = () => store.getStore() || {};
281
+ const enterViewData = (data = {}) => {
282
+ store.enterWith(normalizeContextData({
283
+ ...getViewData(),
284
+ ...data
285
+ }));
286
+ };
287
+ const runWithViewData = async (data, callback) => {
288
+ return await store.run(normalizeContextData(data), callback);
289
+ };
290
+ const clearViewData = () => {
291
+ store.disable();
292
+ };
293
+ const collectViewData = (context) => {
294
+ const ctx = isRecord(context.ctx) ? context.ctx : context;
295
+ const response = isRecord(context.response) ? context.response : void 0;
296
+ const locals = {
297
+ ...isRecord(ctx.res?.locals) ? ctx.res.locals : {},
298
+ ...isRecord(ctx.response?.source?.locals) ? ctx.response.source.locals : {},
299
+ ...isRecord(response?.source?.locals) ? response.source.locals : {}
300
+ };
301
+ return normalizeContextData({
302
+ ..."session" in ctx ? { session: ctx.session } : {},
303
+ ..."httpSession" in ctx ? { httpSession: ctx.httpSession } : {},
304
+ ..."errors" in ctx ? { errors: ctx.errors } : {},
305
+ ...locals
306
+ });
307
+ };
308
+ //#endregion
309
+ //#region src/ViewFactory.ts
310
+ var ViewFactory = class {
311
+ edge;
312
+ sharedData = {};
313
+ composers = /* @__PURE__ */ new Map();
314
+ mountedPackages = /* @__PURE__ */ new Set();
315
+ packageViewsPath;
316
+ constructor(options = {}) {
317
+ this.edge = options.edge ?? Edge.create({ cache: options.cache });
318
+ this.packageViewsPath = options.packageViewsPath ?? "resources/views";
319
+ this.mount(options.viewsPath ?? resolve(process.cwd(), "src", "resources", "views"));
320
+ }
321
+ make(name, data = {}) {
322
+ const edgeName = this.resolveName(name);
323
+ return new ViewInstance(name, normalizeViewData({
324
+ ...this.sharedData,
325
+ ...getViewData(),
326
+ ...data
327
+ }), this.edge, async (view) => await this.runComposers(name, view), (view) => this.runComposersSync(name, view), edgeName);
328
+ }
329
+ first(names, data = {}) {
330
+ const name = names.find((candidate) => this.exists(candidate));
331
+ if (!name) throw new Error(`None of the given views exist: ${names.join(", ")}`);
332
+ return this.make(name, data);
333
+ }
334
+ exists(name) {
335
+ const edgeName = this.resolveName(name);
336
+ if (this.edge.loader.templates[edgeName]) return true;
337
+ try {
338
+ return existsSync(this.edge.loader.makePath(edgeName));
339
+ } catch {
340
+ return false;
341
+ }
342
+ }
343
+ share(...data) {
344
+ mergeData(this.sharedData, data);
345
+ return this;
346
+ }
347
+ composer(names, composer) {
348
+ for (const name of Array.isArray(names) ? names : [names]) this.composers.set(name, [...this.composers.get(name) ?? [], composer]);
349
+ return this;
350
+ }
351
+ mount(diskName, viewsDirectory) {
352
+ if (viewsDirectory === void 0) {
353
+ this.edge.mount(diskName);
354
+ return this;
355
+ }
356
+ this.edge.mount(diskName, viewsDirectory);
357
+ return this;
358
+ }
359
+ raw(name, contents) {
360
+ this.edge.registerTemplate(name, { template: contents });
361
+ return this;
362
+ }
363
+ flushShared() {
364
+ this.sharedData = {};
365
+ return this;
366
+ }
367
+ flushComposers() {
368
+ this.composers.clear();
369
+ return this;
370
+ }
371
+ getComposers(name) {
372
+ const edgeName = this.resolveName(name);
373
+ return [
374
+ ...this.composers.get("*") ?? [],
375
+ ...this.composers.get(edgeName) ?? [],
376
+ ...this.composers.get(name) ?? []
377
+ ];
378
+ }
379
+ async runComposers(name, view) {
380
+ for (const composer of this.getComposers(name)) await runComposer(composer, view);
381
+ }
382
+ runComposersSync(name, view) {
383
+ for (const composer of this.getComposers(name)) runComposerSync(composer, view);
384
+ }
385
+ resolveName(name) {
386
+ const packageView = parsePackageViewName(name);
387
+ if (!packageView) return name;
388
+ if (!this.mountedPackages.has(packageView.diskName)) {
389
+ this.mount(packageView.diskName, resolvePackageViewsPath(packageView.nodePackageName, this.packageViewsPath));
390
+ this.mountedPackages.add(packageView.diskName);
391
+ }
392
+ return packageView.edgeName;
393
+ }
394
+ };
395
+ //#endregion
396
+ //#region src/View.ts
397
+ var View = class View {
398
+ static factory = new ViewFactory();
399
+ /**
400
+ * Bootstrap the view service
401
+ */
402
+ static boot() {
403
+ Object.defineProperty(globalThis, "view", {
404
+ value: (name, data = {}) => {
405
+ if (name === void 0) return View.factoryInstance();
406
+ return View.make(name, data);
407
+ },
408
+ configurable: true,
409
+ writable: true
410
+ });
411
+ }
412
+ static configure(options = {}) {
413
+ this.factory = new ViewFactory(options);
414
+ return this.factory;
415
+ }
416
+ static factoryInstance() {
417
+ return this.factory;
418
+ }
419
+ static make(name, data = {}) {
420
+ return this.factory.make(name, data);
421
+ }
422
+ static first(names, data = {}) {
423
+ return this.factory.first(names, data);
424
+ }
425
+ static exists(name) {
426
+ return this.factory.exists(name);
427
+ }
428
+ static share(...data) {
429
+ if (typeof data[0] === "string") this.factory.share(data[0], data[1]);
430
+ else this.factory.share(data[0] ?? {});
431
+ return this;
432
+ }
433
+ static composer(names, composer) {
434
+ this.factory.composer(names, composer);
435
+ return this;
436
+ }
437
+ static mount(diskName, viewsDirectory) {
438
+ if (viewsDirectory === void 0) this.factory.mount(diskName);
439
+ else this.factory.mount(diskName, viewsDirectory);
440
+ return this;
441
+ }
442
+ static raw(name, contents) {
443
+ this.factory.raw(name, contents);
444
+ return this;
445
+ }
446
+ };
447
+ //#endregion
448
+ //#region src/plugins.ts
449
+ const clearRouterViewPlugin = definePlugin({
450
+ name: "arkstack-view",
451
+ setup: ({ useHttpContext }) => {
452
+ useHttpContext((context) => {
453
+ enterViewData(collectViewData(context));
454
+ });
455
+ }
456
+ });
457
+ //#endregion
458
+ export { collectViewData as a, runWithViewData as c, resolvePackageViewsPath as d, view as f, clearViewData as i, ViewInstance as l, normalizeViewErrors as m, View as n, enterViewData as o, ViewErrorBag as p, ViewFactory as r, getViewData as s, clearRouterViewPlugin as t, parsePackageViewName as u };
459
+
460
+ //# sourceMappingURL=plugins-OaO2BC-T.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"plugins-OaO2BC-T.js","names":["defineClearRouterPlugin"],"sources":["../src/ViewErrorBag.ts","../src/helpers.ts","../src/packageViews.ts","../src/ViewInstance.ts","../src/viewContext.ts","../src/ViewFactory.ts","../src/View.ts","../src/plugins.ts"],"sourcesContent":["import { ViewErrorRecord, ViewErrorValue } from './types'\nimport { getMessageRecord, isRecord, toMessages } from './helpers'\n\nconst defaultErrorKey = '_'\n\nexport class ViewErrorBag {\n private bag: Record<string, string[]> = {}\n\n constructor(errors?: ViewErrorRecord | ViewErrorBag | unknown) {\n if (errors) {\n this.merge(errors)\n }\n }\n\n add (field: string, message: ViewErrorValue) {\n const key = field || defaultErrorKey\n const messages = toMessages(message)\n\n if (!messages.length) {\n return this\n }\n\n this.bag[key] = [\n ...(this.bag[key] || []),\n ...messages,\n ]\n\n return this\n }\n\n merge (errors: ViewErrorRecord | ViewErrorBag | unknown) {\n const incoming = errors instanceof ViewErrorBag\n ? errors.toJSON()\n : getMessageRecord(errors) || (isRecord(errors) ? errors as ViewErrorRecord : undefined)\n\n if (!incoming) {\n return this\n }\n\n for (const [field, messages] of Object.entries(incoming)) {\n this.add(field, messages)\n }\n\n return this\n }\n\n keys () {\n return Object.keys(this.bag)\n }\n\n get (field: string = defaultErrorKey) {\n return [...(this.bag[field] || [])]\n }\n\n first (field?: string | null) {\n if (field) {\n return this.bag[field]?.[0] || ''\n }\n\n return this.all()[0] || ''\n }\n\n has (field?: string | string[] | null): boolean {\n if (Array.isArray(field)) {\n return field.every(key => this.has(key))\n }\n\n if (field) {\n return (this.bag[field]?.length || 0) > 0\n }\n\n return this.any()\n }\n\n hasAny (fields: string | string[]) {\n const keys = Array.isArray(fields) ? fields : [fields]\n\n return keys.some(key => this.has(key))\n }\n\n missing (fields: string | string[]) {\n const keys = Array.isArray(fields) ? fields : [fields]\n\n return keys.every(key => !this.has(key))\n }\n\n any () {\n return Object.values(this.bag).some(messages => messages.length > 0)\n }\n\n isEmpty () {\n return !this.any()\n }\n\n isNotEmpty () {\n return this.any()\n }\n\n count () {\n return Object.values(this.bag).reduce((total, messages) => total + messages.length, 0)\n }\n\n all () {\n return Object.values(this.bag).flat()\n }\n\n unique () {\n return [...new Set(this.all())]\n }\n\n clear (field?: string | string[]) {\n if (Array.isArray(field)) {\n for (const key of field) {\n delete this.bag[key]\n }\n\n return this\n }\n\n if (field) {\n delete this.bag[field]\n\n return this\n }\n\n this.bag = {}\n\n return this\n }\n\n forget (field: string) {\n return this.clear(field)\n }\n\n messagesRaw () {\n return this.toJSON()\n }\n\n getMessages () {\n return this.messagesRaw()\n }\n\n getMessageBag () {\n return this\n }\n\n toArray () {\n return this.toJSON()\n }\n\n toJSON () {\n return Object\n .entries(this.bag)\n .reduce<Record<string, string[]>>((errors, [field, messages]) => {\n errors[field] = [...messages]\n\n return errors\n }, {})\n }\n}\n\nexport const isViewErrorBag = (value: unknown): value is Pick<ViewErrorBag, 'all' | 'first' | 'get' | 'has'> => {\n return isRecord(value)\n && typeof value.all === 'function'\n && typeof value.first === 'function'\n && typeof value.get === 'function'\n && typeof value.has === 'function'\n}\n\nexport const normalizeViewErrors = (errors?: unknown) => {\n if (isViewErrorBag(errors)) {\n return errors\n }\n\n return new ViewErrorBag(errors)\n}\n","import type { ViewComposer, ViewComposerObject, ViewData, ViewErrorRecord, ViewErrorValue, ViewName } from './types'\n\nimport { View } from './View'\nimport { ViewFactory } from './ViewFactory'\nimport { ViewInstance } from './ViewInstance'\nimport { normalizeViewErrors } from './ViewErrorBag'\n\nexport function view (): ViewFactory\nexport function view (name: ViewName, data?: ViewData): ViewInstance\nexport function view (name?: ViewName, data: ViewData = {}) {\n if (name === undefined) {\n return View.factoryInstance()\n }\n\n return View.make(name, data)\n}\n\nexport const isClass = <T = unknown> (\n target: unknown\n): target is new (...args: any[]) => T => {\n return typeof target === 'function'\n && /^class\\s/.test(Function.prototype.toString.call(target))\n}\n\nconst currentHttpSession = () => {\n try {\n const session = globalThis.session?.()\n\n return session && typeof session === 'object' ? session as Record<string, any> : undefined\n } catch {\n return undefined\n }\n}\n\nconst hasRenderableErrors = (errors: unknown) => {\n if (!errors || typeof errors !== 'object') {\n return false\n }\n\n const bag = errors as Record<string, any>\n\n if (typeof bag.any === 'function') {\n return Boolean(bag.any())\n }\n\n if (typeof bag.has === 'function') {\n return Boolean(bag.has())\n }\n\n if (typeof bag.isNotEmpty === 'function') {\n return Boolean(bag.isNotEmpty())\n }\n\n if (typeof bag.all === 'function') {\n const messages = bag.all()\n\n if (Array.isArray(messages)) {\n return messages.length > 0\n }\n\n return !!messages && typeof messages === 'object' && Object.keys(messages).length > 0\n }\n\n return Object.keys(bag).length > 0\n}\n\nexport const normalizeViewData = (data: ViewData = {}) => {\n const session = currentHttpSession()\n const ownErrors = normalizeViewErrors(data.errors)\n const sessionErrors = session?.errors\n const errors = hasRenderableErrors(ownErrors) || !sessionErrors\n ? ownErrors\n : normalizeViewErrors(sessionErrors)\n\n return {\n ...(session && !('session' in data) ? { session } : {}),\n ...(session && !('httpSession' in data) ? { httpSession: session } : {}),\n ...data,\n errors,\n }\n}\n\nexport const mergeData = (target: ViewData, data: any[]) => {\n if (data.length === 0) {\n return target\n }\n\n if (typeof data[0] === 'string') {\n target[data[0]] = data[0] === 'errors' ? normalizeViewErrors(data[1]) : data[1]\n\n return target\n }\n\n for (const value of data) {\n if (value && typeof value === 'object' && !Array.isArray(value)) {\n Object.assign(target, normalizeViewData(value))\n }\n }\n\n return target\n}\n\nexport const runComposerSync = (composer: ViewComposer, view: ViewInstance) => {\n const result = runComposer(composer, view)\n\n if (result && typeof result.then === 'function') {\n throw new Error('Async view composers cannot be used with renderSync.')\n }\n}\n\nexport const runComposer = (composer: ViewComposer, view: ViewInstance) => {\n if (typeof composer === 'function') {\n if (isClass<ViewComposerObject>(composer)) {\n return new composer().compose(view)\n }\n\n return composer(view)\n }\n\n return composer.compose(view)\n}\n\nexport const isRecord = (value: unknown): value is Record<string, any> => {\n return !!value && typeof value === 'object' && !Array.isArray(value)\n}\n\nexport const toMessages = (value: ViewErrorValue): string[] => {\n if (Array.isArray(value)) {\n return value.flatMap(item => toMessages(item))\n }\n\n if (value instanceof Error) {\n return [value.message]\n }\n\n if (isRecord(value) && typeof value.message === 'string') {\n return [value.message]\n }\n\n if (value === null || typeof value === 'undefined') {\n return []\n }\n\n return [String(value)]\n}\n\nexport const getMessageRecord = (source: unknown): ViewErrorRecord | undefined => {\n if (!isRecord(source)) {\n return undefined\n }\n\n if (typeof source.getMessageBag === 'function') {\n const bag = source.getMessageBag()\n\n if (bag && bag !== source) {\n const messages = getMessageRecord(bag)\n\n if (messages) {\n return messages\n }\n }\n }\n\n for (const method of ['getMessages', 'messagesRaw', 'toArray']) {\n if (typeof source[method] === 'function') {\n const messages = source[method]()\n\n if (isRecord(messages)) {\n return messages\n }\n }\n }\n\n if (typeof source.errors === 'function') {\n const errors = source.errors()\n const messages = getMessageRecord(errors) || (isRecord(errors) ? errors : undefined)\n\n if (messages) {\n return messages\n }\n }\n\n return getMessageRecord(source.errors) || (isRecord(source.errors) ? source.errors : undefined)\n}","import { existsSync } from 'node:fs'\nimport { resolve } from 'node:path'\n\nexport type PackageViewReference = {\n source: string\n packageName: string\n nodePackageName: string\n diskName: string\n viewName: string\n edgeName: string\n}\n\nexport const parsePackageViewName = (name: string): PackageViewReference | null => {\n if (!name.startsWith('~')) {\n return null\n }\n\n const source = name.slice(1)\n const slashIndex = source.indexOf('/')\n const dotIndex = slashIndex === -1\n ? source.indexOf('.')\n : source.indexOf('.', slashIndex)\n\n if (dotIndex <= 0) {\n throw new Error(`Invalid package view name: ${name}`)\n }\n\n const packageName = source.slice(0, dotIndex)\n const viewName = source.slice(dotIndex + 1)\n\n if (!viewName) {\n throw new Error(`Invalid package view name: ${name}`)\n }\n\n const nodePackageName = slashIndex === -1\n ? packageName\n : `@${packageName}`\n const diskName = `package_${packageName.replace(/[^a-zA-Z0-9_-]/g, '_')}`\n\n return {\n source: name,\n packageName,\n nodePackageName,\n diskName,\n viewName,\n edgeName: `${diskName}::${viewName}`,\n }\n}\n\nexport const resolvePackageViewsPath = (\n nodePackageName: string,\n viewPath = 'resources/views',\n) => {\n const packageRoot = resolve(process.cwd(), 'node_modules', nodePackageName)\n const viewsPath = resolve(packageRoot, viewPath)\n\n if (!existsSync(viewsPath)) {\n throw new Error(`Package views directory not found: ${viewsPath}`)\n }\n\n return viewsPath\n}\n","import type { ComposerRunner, SyncComposerRunner, ViewData } from './types'\n\nimport { mergeData, normalizeViewData } from './helpers'\n\nexport class ViewInstance implements PromiseLike<string> {\n private payload: ViewData\n private composersHaveRun = false\n\n constructor(\n readonly name: string,\n data: ViewData = {},\n private renderer: {\n render: (name: string, data?: ViewData) => Promise<string>\n renderSync: (name: string, data?: ViewData) => string\n },\n private runComposers: ComposerRunner,\n private runComposersSync: SyncComposerRunner,\n private renderName = name,\n ) {\n this.payload = normalizeViewData({ ...data })\n }\n\n get data () {\n return this.payload\n }\n\n with (key: string, value: any): this\n with (data: ViewData): this\n with (...data: any[]): this {\n mergeData(this.payload, data)\n\n return this\n }\n\n async render () {\n await this.compose()\n\n return await this.renderer.render(this.renderName, this.payload)\n }\n\n renderSync () {\n this.composeSync()\n\n return this.renderer.renderSync(this.renderName, this.payload)\n }\n\n then<TResult1 = string, TResult2 = never> (\n onfulfilled?: ((value: string) => TResult1 | PromiseLike<TResult1>) | null,\n onrejected?: ((reason: any) => TResult2 | PromiseLike<TResult2>) | null,\n ): PromiseLike<TResult1 | TResult2> {\n return this.render().then(onfulfilled, onrejected)\n }\n\n private async compose () {\n if (this.composersHaveRun) {\n return\n }\n\n this.composersHaveRun = true\n await this.runComposers(this)\n }\n\n private composeSync () {\n if (this.composersHaveRun) {\n return\n }\n\n this.composersHaveRun = true\n this.runComposersSync(this)\n }\n}\n","import { AsyncLocalStorage } from 'node:async_hooks'\nimport type { ViewData } from './types'\nimport { isRecord, normalizeViewData } from './helpers'\n\nconst store = new AsyncLocalStorage<ViewData>()\n\nconst normalizeContextData = (data: ViewData = {}) => normalizeViewData(data)\n\nexport const getViewData = () => store.getStore() || {}\n\nexport const enterViewData = (data: ViewData = {}) => {\n store.enterWith(normalizeContextData({ ...getViewData(), ...data }))\n}\n\nexport const runWithViewData = async <T> (data: ViewData, callback: () => T | Promise<T>) => {\n return await store.run(normalizeContextData(data), callback)\n}\n\nexport const clearViewData = () => {\n store.disable()\n}\n\nexport const collectViewData = (context: Record<string, any>): ViewData => {\n const ctx = isRecord(context.ctx) ? context.ctx : context\n const response = isRecord(context.response) ? context.response : undefined\n const locals = {\n ...(isRecord(ctx.res?.locals) ? ctx.res.locals : {}),\n ...(isRecord(ctx.response?.source?.locals) ? ctx.response.source.locals : {}),\n ...(isRecord(response?.source?.locals) ? response.source.locals : {}),\n }\n\n return normalizeContextData({\n ...('session' in ctx ? { session: ctx.session } : {}),\n ...('httpSession' in ctx ? { httpSession: ctx.httpSession } : {}),\n ...('errors' in ctx ? { errors: ctx.errors } : {}),\n ...locals,\n })\n}\n","import type { ViewComposer, ViewComposerName, ViewData, ViewFactoryOptions, ViewName } from './types'\nimport { mergeData, normalizeViewData, runComposer, runComposerSync } from './helpers'\nimport { parsePackageViewName, resolvePackageViewsPath } from './packageViews'\n\nimport { Edge } from 'edge.js'\nimport { ViewInstance } from './ViewInstance'\nimport { existsSync } from 'node:fs'\nimport { getViewData } from './viewContext'\nimport { resolve } from 'node:path'\n\nexport class ViewFactory {\n readonly edge: Edge\n private sharedData: ViewData = {}\n private composers = new Map<ViewName, ViewComposer[]>()\n private mountedPackages = new Set<string>()\n private packageViewsPath: string\n\n constructor(options: ViewFactoryOptions = {}) {\n this.edge = options.edge ?? Edge.create({ cache: options.cache })\n this.packageViewsPath = options.packageViewsPath ?? 'resources/views'\n this.mount(options.viewsPath ?? resolve(process.cwd(), 'src', 'resources', 'views'))\n }\n\n make (name: ViewName, data: ViewData = {}) {\n const edgeName = this.resolveName(name)\n\n return new ViewInstance(\n name,\n normalizeViewData({ ...this.sharedData, ...getViewData(), ...data }),\n this.edge,\n async view => await this.runComposers(name, view),\n view => this.runComposersSync(name, view),\n edgeName,\n )\n }\n\n first (names: ViewName[], data: ViewData = {}) {\n const name = names.find(candidate => this.exists(candidate))\n\n if (!name) {\n throw new Error(`None of the given views exist: ${names.join(', ')}`)\n }\n\n return this.make(name, data)\n }\n\n exists (name: ViewName) {\n const edgeName = this.resolveName(name)\n\n if (this.edge.loader.templates[edgeName]) {\n return true\n }\n\n try {\n return existsSync(this.edge.loader.makePath(edgeName))\n } catch {\n return false\n }\n }\n\n share (key: string, value: any): this\n share (data: ViewData): this\n share (...data: any[]): this {\n mergeData(this.sharedData, data)\n\n return this\n }\n\n composer (names: ViewComposerName, composer: ViewComposer): this {\n for (const name of Array.isArray(names) ? names : [names]) {\n this.composers.set(name, [\n ...(this.composers.get(name) ?? []),\n composer,\n ])\n }\n\n return this\n }\n\n mount (viewsDirectory: string | URL): this\n mount (diskName: string, viewsDirectory: string | URL): this\n mount (diskName: string | URL, viewsDirectory?: string | URL): this {\n if (viewsDirectory === undefined) {\n this.edge.mount(diskName)\n\n return this\n }\n\n this.edge.mount(diskName as string, viewsDirectory)\n\n return this\n }\n\n raw (name: ViewName, contents: string): this {\n this.edge.registerTemplate(name, { template: contents })\n\n return this\n }\n\n flushShared () {\n this.sharedData = {}\n\n return this\n }\n\n flushComposers () {\n this.composers.clear()\n\n return this\n }\n\n private getComposers (name: ViewName) {\n const edgeName = this.resolveName(name)\n\n return [\n ...(this.composers.get('*') ?? []),\n ...(this.composers.get(edgeName) ?? []),\n ...(this.composers.get(name) ?? []),\n ]\n }\n\n private async runComposers (name: ViewName, view: ViewInstance) {\n for (const composer of this.getComposers(name)) {\n await runComposer(composer, view)\n }\n }\n\n private runComposersSync (name: ViewName, view: ViewInstance) {\n for (const composer of this.getComposers(name)) {\n runComposerSync(composer, view)\n }\n }\n\n private resolveName (name: ViewName) {\n const packageView = parsePackageViewName(name)\n\n if (!packageView) {\n return name\n }\n\n if (!this.mountedPackages.has(packageView.diskName)) {\n this.mount(\n packageView.diskName,\n resolvePackageViewsPath(packageView.nodePackageName, this.packageViewsPath),\n )\n this.mountedPackages.add(packageView.diskName)\n }\n\n return packageView.edgeName\n }\n}\n","import type { ViewComposer, ViewComposerName, ViewData, ViewFactoryOptions, ViewName } from './types'\n\nimport { ViewFactory } from './ViewFactory'\nimport type { ViewInstance } from './ViewInstance'\n\nexport class View {\n private static factory = new ViewFactory()\n\n /**\n * Bootstrap the view service\n */\n static boot () {\n Object.defineProperty(globalThis, 'view', {\n value: (name?: ViewName, data: ViewData = {}) => {\n if (name === undefined) {\n return View.factoryInstance()\n }\n\n return View.make(name, data)\n },\n configurable: true,\n writable: true,\n })\n }\n\n static configure (options: ViewFactoryOptions = {}) {\n this.factory = new ViewFactory(options)\n\n return this.factory\n }\n\n static factoryInstance () {\n return this.factory\n }\n\n static make (name: ViewName, data: ViewData = {}): ViewInstance {\n return this.factory.make(name, data)\n }\n\n static first (names: ViewName[], data: ViewData = {}): ViewInstance {\n return this.factory.first(names, data)\n }\n\n static exists (name: ViewName) {\n return this.factory.exists(name)\n }\n\n static share (key: string, value: any): typeof View\n static share (data: ViewData): typeof View\n static share (...data: any[]) {\n if (typeof data[0] === 'string') {\n this.factory.share(data[0], data[1])\n } else {\n this.factory.share(data[0] ?? {})\n }\n\n return this\n }\n\n static composer (names: ViewComposerName, composer: ViewComposer): typeof View {\n this.factory.composer(names, composer)\n\n return this\n }\n\n static mount (viewsDirectory: string | URL): typeof View\n static mount (diskName: string, viewsDirectory: string | URL): typeof View\n static mount (diskName: string | URL, viewsDirectory?: string | URL) {\n if (viewsDirectory === undefined) {\n this.factory.mount(diskName)\n } else {\n this.factory.mount(diskName as string, viewsDirectory)\n }\n\n return this\n }\n\n static raw (name: ViewName, contents: string) {\n this.factory.raw(name, contents)\n\n return this\n }\n}\n","import { collectViewData, enterViewData } from './viewContext'\n\nimport { definePlugin as defineClearRouterPlugin } from 'clear-router/core'\n\nexport const clearRouterViewPlugin = defineClearRouterPlugin({\n name: 'arkstack-view',\n setup: ({ useHttpContext }) => {\n useHttpContext((context) => {\n enterViewData(collectViewData(context))\n })\n },\n})"],"mappings":"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"}
package/dist/setup.js CHANGED
@@ -1,4 +1,4 @@
1
- import { t as clearRouterViewPlugin } from "./plugins-C5X8pT4o.js";
1
+ import { t as clearRouterViewPlugin } from "./plugins-OaO2BC-T.js";
2
2
  import { CoreRouter } from "clear-router/core";
3
3
  //#region src/setup.ts
4
4
  CoreRouter.use(clearRouterViewPlugin);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@arkstack/view",
3
- "version": "0.8.0",
3
+ "version": "0.9.0",
4
4
  "type": "module",
5
5
  "description": "View module for Arkstack, providing template rendering and view integration utilities.",
6
6
  "homepage": "https://arkstack.toneflix.net/guide/views",
@@ -36,8 +36,8 @@
36
36
  },
37
37
  "peerDependencies": {
38
38
  "@h3ravel/musket": "^0.10.1",
39
- "clear-router": "^2.7.2",
40
- "@arkstack/common": "^0.8.0"
39
+ "clear-router": "^2.7.7",
40
+ "@arkstack/common": "^0.9.0"
41
41
  },
42
42
  "peerDependenciesMeta": {
43
43
  "@h3ravel/musket": {
package/dist/index.js.map DELETED
@@ -1 +0,0 @@
1
- {"version":3,"file":"index.js","names":["Edge"],"sources":["../src/helpers.ts","../src/packageViews.ts","../src/ViewInstance.ts","../src/ViewFactory.ts","../src/View.ts"],"sourcesContent":["import type { ViewComposer, ViewComposerObject, ViewData, ViewName } from './types'\n\nimport { View } from './View'\nimport { normalizeViewErrors } from './ViewErrorBag'\nimport { ViewFactory } from './ViewFactory'\nimport { ViewInstance } from './ViewInstance'\n\nexport function view (): ViewFactory\nexport function view (name: ViewName, data?: ViewData): ViewInstance\nexport function view (name?: ViewName, data: ViewData = {}) {\n if (name === undefined) {\n return View.factoryInstance()\n }\n\n return View.make(name, data)\n}\n\nexport const isClass = <T = unknown> (\n target: unknown\n): target is new (...args: any[]) => T => {\n return typeof target === 'function'\n && /^class\\s/.test(Function.prototype.toString.call(target))\n}\n\nexport const normalizeViewData = (data: ViewData = {}) => {\n return {\n ...data,\n errors: normalizeViewErrors(data.errors),\n }\n}\n\nexport const mergeData = (target: ViewData, data: any[]) => {\n if (data.length === 0) {\n return target\n }\n\n if (typeof data[0] === 'string') {\n target[data[0]] = data[0] === 'errors' ? normalizeViewErrors(data[1]) : data[1]\n\n return target\n }\n\n for (const value of data) {\n if (value && typeof value === 'object' && !Array.isArray(value)) {\n Object.assign(target, normalizeViewData(value))\n }\n }\n\n return target\n}\n\nexport const runComposerSync = (composer: ViewComposer, view: ViewInstance) => {\n const result = runComposer(composer, view)\n\n if (result && typeof result.then === 'function') {\n throw new Error('Async view composers cannot be used with renderSync.')\n }\n}\n\nexport const runComposer = (composer: ViewComposer, view: ViewInstance) => {\n if (typeof composer === 'function') {\n if (isClass<ViewComposerObject>(composer)) {\n return new composer().compose(view)\n }\n\n return composer(view)\n }\n\n return composer.compose(view)\n}\n","import { existsSync } from 'node:fs'\nimport { resolve } from 'node:path'\n\nexport type PackageViewReference = {\n source: string\n packageName: string\n nodePackageName: string\n diskName: string\n viewName: string\n edgeName: string\n}\n\nexport const parsePackageViewName = (name: string): PackageViewReference | null => {\n if (!name.startsWith('~')) {\n return null\n }\n\n const source = name.slice(1)\n const slashIndex = source.indexOf('/')\n const dotIndex = slashIndex === -1\n ? source.indexOf('.')\n : source.indexOf('.', slashIndex)\n\n if (dotIndex <= 0) {\n throw new Error(`Invalid package view name: ${name}`)\n }\n\n const packageName = source.slice(0, dotIndex)\n const viewName = source.slice(dotIndex + 1)\n\n if (!viewName) {\n throw new Error(`Invalid package view name: ${name}`)\n }\n\n const nodePackageName = slashIndex === -1\n ? packageName\n : `@${packageName}`\n const diskName = `package_${packageName.replace(/[^a-zA-Z0-9_-]/g, '_')}`\n\n return {\n source: name,\n packageName,\n nodePackageName,\n diskName,\n viewName,\n edgeName: `${diskName}::${viewName}`,\n }\n}\n\nexport const resolvePackageViewsPath = (\n nodePackageName: string,\n viewPath = 'resources/views',\n) => {\n const packageRoot = resolve(process.cwd(), 'node_modules', nodePackageName)\n const viewsPath = resolve(packageRoot, viewPath)\n\n if (!existsSync(viewsPath)) {\n throw new Error(`Package views directory not found: ${viewsPath}`)\n }\n\n return viewsPath\n}\n","import type { ComposerRunner, SyncComposerRunner, ViewData } from './types'\n\nimport { mergeData, normalizeViewData } from './helpers'\n\nexport class ViewInstance implements PromiseLike<string> {\n private payload: ViewData\n private composersHaveRun = false\n\n constructor(\n readonly name: string,\n data: ViewData = {},\n private renderer: {\n render: (name: string, data?: ViewData) => Promise<string>\n renderSync: (name: string, data?: ViewData) => string\n },\n private runComposers: ComposerRunner,\n private runComposersSync: SyncComposerRunner,\n private renderName = name,\n ) {\n this.payload = normalizeViewData({ ...data })\n }\n\n get data () {\n return this.payload\n }\n\n with (key: string, value: any): this\n with (data: ViewData): this\n with (...data: any[]): this {\n mergeData(this.payload, data)\n\n return this\n }\n\n async render () {\n await this.compose()\n\n return await this.renderer.render(this.renderName, this.payload)\n }\n\n renderSync () {\n this.composeSync()\n\n return this.renderer.renderSync(this.renderName, this.payload)\n }\n\n then<TResult1 = string, TResult2 = never> (\n onfulfilled?: ((value: string) => TResult1 | PromiseLike<TResult1>) | null,\n onrejected?: ((reason: any) => TResult2 | PromiseLike<TResult2>) | null,\n ): PromiseLike<TResult1 | TResult2> {\n return this.render().then(onfulfilled, onrejected)\n }\n\n private async compose () {\n if (this.composersHaveRun) {\n return\n }\n\n this.composersHaveRun = true\n await this.runComposers(this)\n }\n\n private composeSync () {\n if (this.composersHaveRun) {\n return\n }\n\n this.composersHaveRun = true\n this.runComposersSync(this)\n }\n}\n","import type { ViewComposer, ViewComposerName, ViewData, ViewFactoryOptions, ViewName } from './types'\nimport { mergeData, normalizeViewData, runComposer, runComposerSync } from './helpers'\nimport { parsePackageViewName, resolvePackageViewsPath } from './packageViews'\nimport { getViewData } from './viewContext'\n\nimport { Edge } from 'edge.js'\nimport { ViewInstance } from './ViewInstance'\nimport { existsSync } from 'node:fs'\nimport { resolve } from 'node:path'\n\nexport class ViewFactory {\n readonly edge: Edge\n private sharedData: ViewData = {}\n private composers = new Map<ViewName, ViewComposer[]>()\n private mountedPackages = new Set<string>()\n private packageViewsPath: string\n\n constructor(options: ViewFactoryOptions = {}) {\n this.edge = options.edge ?? Edge.create({ cache: options.cache })\n this.packageViewsPath = options.packageViewsPath ?? 'resources/views'\n this.mount(options.viewsPath ?? resolve(process.cwd(), 'src', 'resources', 'views'))\n }\n\n make (name: ViewName, data: ViewData = {}) {\n const edgeName = this.resolveName(name)\n\n return new ViewInstance(\n name,\n normalizeViewData({ ...this.sharedData, ...getViewData(), ...data }),\n this.edge,\n async view => await this.runComposers(name, view),\n view => this.runComposersSync(name, view),\n edgeName,\n )\n }\n\n first (names: ViewName[], data: ViewData = {}) {\n const name = names.find(candidate => this.exists(candidate))\n\n if (!name) {\n throw new Error(`None of the given views exist: ${names.join(', ')}`)\n }\n\n return this.make(name, data)\n }\n\n exists (name: ViewName) {\n const edgeName = this.resolveName(name)\n\n if (this.edge.loader.templates[edgeName]) {\n return true\n }\n\n try {\n return existsSync(this.edge.loader.makePath(edgeName))\n } catch {\n return false\n }\n }\n\n share (key: string, value: any): this\n share (data: ViewData): this\n share (...data: any[]): this {\n mergeData(this.sharedData, data)\n\n return this\n }\n\n composer (names: ViewComposerName, composer: ViewComposer): this {\n for (const name of Array.isArray(names) ? names : [names]) {\n this.composers.set(name, [\n ...(this.composers.get(name) ?? []),\n composer,\n ])\n }\n\n return this\n }\n\n mount (viewsDirectory: string | URL): this\n mount (diskName: string, viewsDirectory: string | URL): this\n mount (diskName: string | URL, viewsDirectory?: string | URL): this {\n if (viewsDirectory === undefined) {\n this.edge.mount(diskName)\n\n return this\n }\n\n this.edge.mount(diskName as string, viewsDirectory)\n\n return this\n }\n\n raw (name: ViewName, contents: string): this {\n this.edge.registerTemplate(name, { template: contents })\n\n return this\n }\n\n flushShared () {\n this.sharedData = {}\n\n return this\n }\n\n flushComposers () {\n this.composers.clear()\n\n return this\n }\n\n private getComposers (name: ViewName) {\n const edgeName = this.resolveName(name)\n\n return [\n ...(this.composers.get('*') ?? []),\n ...(this.composers.get(edgeName) ?? []),\n ...(this.composers.get(name) ?? []),\n ]\n }\n\n private async runComposers (name: ViewName, view: ViewInstance) {\n for (const composer of this.getComposers(name)) {\n await runComposer(composer, view)\n }\n }\n\n private runComposersSync (name: ViewName, view: ViewInstance) {\n for (const composer of this.getComposers(name)) {\n runComposerSync(composer, view)\n }\n }\n\n private resolveName (name: ViewName) {\n const packageView = parsePackageViewName(name)\n\n if (!packageView) {\n return name\n }\n\n if (!this.mountedPackages.has(packageView.diskName)) {\n this.mount(\n packageView.diskName,\n resolvePackageViewsPath(packageView.nodePackageName, this.packageViewsPath),\n )\n this.mountedPackages.add(packageView.diskName)\n }\n\n return packageView.edgeName\n }\n}\n","import type { ViewComposer, ViewComposerName, ViewData, ViewFactoryOptions, ViewName } from './types'\n\nimport { ViewFactory } from './ViewFactory'\nimport type { ViewInstance } from './ViewInstance'\n\nexport class View {\n private static factory = new ViewFactory()\n\n /**\n * Bootstrap the view service\n */\n static boot () {\n Object.defineProperty(globalThis, 'view', {\n value: (name?: ViewName, data: ViewData = {}) => {\n if (name === undefined) {\n return View.factoryInstance()\n }\n\n return View.make(name, data)\n },\n configurable: true,\n writable: true,\n })\n }\n\n static configure (options: ViewFactoryOptions = {}) {\n this.factory = new ViewFactory(options)\n\n return this.factory\n }\n\n static factoryInstance () {\n return this.factory\n }\n\n static make (name: ViewName, data: ViewData = {}): ViewInstance {\n return this.factory.make(name, data)\n }\n\n static first (names: ViewName[], data: ViewData = {}): ViewInstance {\n return this.factory.first(names, data)\n }\n\n static exists (name: ViewName) {\n return this.factory.exists(name)\n }\n\n static share (key: string, value: any): typeof View\n static share (data: ViewData): typeof View\n static share (...data: any[]) {\n if (typeof data[0] === 'string') {\n this.factory.share(data[0], data[1])\n } else {\n this.factory.share(data[0] ?? {})\n }\n\n return this\n }\n\n static composer (names: ViewComposerName, composer: ViewComposer): typeof View {\n this.factory.composer(names, composer)\n\n return this\n }\n\n static mount (viewsDirectory: string | URL): typeof View\n static mount (diskName: string, viewsDirectory: string | URL): typeof View\n static mount (diskName: string | URL, viewsDirectory?: string | URL) {\n if (viewsDirectory === undefined) {\n this.factory.mount(diskName)\n } else {\n this.factory.mount(diskName as string, viewsDirectory)\n }\n\n return this\n }\n\n static raw (name: ViewName, contents: string) {\n this.factory.raw(name, contents)\n\n return this\n }\n}\n"],"mappings":"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"}
@@ -1,188 +0,0 @@
1
- import { AsyncLocalStorage } from "node:async_hooks";
2
- import { definePlugin } from "clear-router/core";
3
- //#region src/ViewErrorBag.ts
4
- const defaultErrorKey = "_";
5
- const isRecord$1 = (value) => {
6
- return !!value && typeof value === "object" && !Array.isArray(value);
7
- };
8
- const toMessages = (value) => {
9
- if (Array.isArray(value)) return value.flatMap((item) => toMessages(item));
10
- if (value instanceof Error) return [value.message];
11
- if (isRecord$1(value) && typeof value.message === "string") return [value.message];
12
- if (value === null || typeof value === "undefined") return [];
13
- return [String(value)];
14
- };
15
- const getMessageRecord = (source) => {
16
- if (!isRecord$1(source)) return;
17
- if (typeof source.getMessageBag === "function") {
18
- const bag = source.getMessageBag();
19
- if (bag && bag !== source) {
20
- const messages = getMessageRecord(bag);
21
- if (messages) return messages;
22
- }
23
- }
24
- for (const method of [
25
- "getMessages",
26
- "messagesRaw",
27
- "toArray"
28
- ]) if (typeof source[method] === "function") {
29
- const messages = source[method]();
30
- if (isRecord$1(messages)) return messages;
31
- }
32
- if (typeof source.errors === "function") {
33
- const errors = source.errors();
34
- const messages = getMessageRecord(errors) || (isRecord$1(errors) ? errors : void 0);
35
- if (messages) return messages;
36
- }
37
- return getMessageRecord(source.errors) || (isRecord$1(source.errors) ? source.errors : void 0);
38
- };
39
- var ViewErrorBag = class ViewErrorBag {
40
- bag = {};
41
- constructor(errors) {
42
- if (errors) this.merge(errors);
43
- }
44
- add(field, message) {
45
- const key = field || defaultErrorKey;
46
- const messages = toMessages(message);
47
- if (!messages.length) return this;
48
- this.bag[key] = [...this.bag[key] || [], ...messages];
49
- return this;
50
- }
51
- merge(errors) {
52
- const incoming = errors instanceof ViewErrorBag ? errors.toJSON() : getMessageRecord(errors) || (isRecord$1(errors) ? errors : void 0);
53
- if (!incoming) return this;
54
- for (const [field, messages] of Object.entries(incoming)) this.add(field, messages);
55
- return this;
56
- }
57
- keys() {
58
- return Object.keys(this.bag);
59
- }
60
- get(field = defaultErrorKey) {
61
- return [...this.bag[field] || []];
62
- }
63
- first(field) {
64
- if (field) return this.bag[field]?.[0] || "";
65
- return this.all()[0] || "";
66
- }
67
- has(field) {
68
- if (Array.isArray(field)) return field.every((key) => this.has(key));
69
- if (field) return (this.bag[field]?.length || 0) > 0;
70
- return this.any();
71
- }
72
- hasAny(fields) {
73
- return (Array.isArray(fields) ? fields : [fields]).some((key) => this.has(key));
74
- }
75
- missing(fields) {
76
- return (Array.isArray(fields) ? fields : [fields]).every((key) => !this.has(key));
77
- }
78
- any() {
79
- return Object.values(this.bag).some((messages) => messages.length > 0);
80
- }
81
- isEmpty() {
82
- return !this.any();
83
- }
84
- isNotEmpty() {
85
- return this.any();
86
- }
87
- count() {
88
- return Object.values(this.bag).reduce((total, messages) => total + messages.length, 0);
89
- }
90
- all() {
91
- return Object.values(this.bag).flat();
92
- }
93
- unique() {
94
- return [...new Set(this.all())];
95
- }
96
- clear(field) {
97
- if (Array.isArray(field)) {
98
- for (const key of field) delete this.bag[key];
99
- return this;
100
- }
101
- if (field) {
102
- delete this.bag[field];
103
- return this;
104
- }
105
- this.bag = {};
106
- return this;
107
- }
108
- forget(field) {
109
- return this.clear(field);
110
- }
111
- messagesRaw() {
112
- return this.toJSON();
113
- }
114
- getMessages() {
115
- return this.messagesRaw();
116
- }
117
- getMessageBag() {
118
- return this;
119
- }
120
- toArray() {
121
- return this.toJSON();
122
- }
123
- toJSON() {
124
- return Object.entries(this.bag).reduce((errors, [field, messages]) => {
125
- errors[field] = [...messages];
126
- return errors;
127
- }, {});
128
- }
129
- };
130
- const isViewErrorBag = (value) => {
131
- return isRecord$1(value) && typeof value.all === "function" && typeof value.first === "function" && typeof value.get === "function" && typeof value.has === "function";
132
- };
133
- const normalizeViewErrors = (errors) => {
134
- if (isViewErrorBag(errors)) return errors;
135
- return new ViewErrorBag(errors);
136
- };
137
- //#endregion
138
- //#region src/viewContext.ts
139
- const store = new AsyncLocalStorage();
140
- const normalizeContextData = (data = {}) => ({
141
- ...data,
142
- errors: normalizeViewErrors(data.errors)
143
- });
144
- const isRecord = (value) => {
145
- return !!value && typeof value === "object" && !Array.isArray(value);
146
- };
147
- const getViewData = () => store.getStore() || {};
148
- const enterViewData = (data = {}) => {
149
- store.enterWith(normalizeContextData({
150
- ...getViewData(),
151
- ...data
152
- }));
153
- };
154
- const runWithViewData = async (data, callback) => {
155
- return await store.run(normalizeContextData(data), callback);
156
- };
157
- const clearViewData = () => {
158
- store.disable();
159
- };
160
- const collectViewData = (context) => {
161
- const ctx = isRecord(context.ctx) ? context.ctx : context;
162
- const response = isRecord(context.response) ? context.response : void 0;
163
- const locals = {
164
- ...isRecord(ctx.res?.locals) ? ctx.res.locals : {},
165
- ...isRecord(ctx.response?.source?.locals) ? ctx.response.source.locals : {},
166
- ...isRecord(response?.source?.locals) ? response.source.locals : {}
167
- };
168
- return normalizeContextData({
169
- ..."session" in ctx ? { session: ctx.session } : {},
170
- ..."httpSession" in ctx ? { httpSession: ctx.httpSession } : {},
171
- ..."errors" in ctx ? { errors: ctx.errors } : {},
172
- ...locals
173
- });
174
- };
175
- //#endregion
176
- //#region src/plugins.ts
177
- const clearRouterViewPlugin = definePlugin({
178
- name: "arkstack-view",
179
- setup: ({ useHttpContext }) => {
180
- useHttpContext((context) => {
181
- enterViewData(collectViewData(context));
182
- });
183
- }
184
- });
185
- //#endregion
186
- export { getViewData as a, normalizeViewErrors as c, enterViewData as i, clearViewData as n, runWithViewData as o, collectViewData as r, ViewErrorBag as s, clearRouterViewPlugin as t };
187
-
188
- //# sourceMappingURL=plugins-C5X8pT4o.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"plugins-C5X8pT4o.js","names":["isRecord","defineClearRouterPlugin"],"sources":["../src/ViewErrorBag.ts","../src/viewContext.ts","../src/plugins.ts"],"sourcesContent":["export type ViewErrorValue = string | string[] | Error | { message?: unknown } | unknown\nexport type ViewErrorRecord = Record<string, ViewErrorValue>\n\nconst defaultErrorKey = '_'\n\nconst isRecord = (value: unknown): value is Record<string, any> => {\n return !!value && typeof value === 'object' && !Array.isArray(value)\n}\n\nconst toMessages = (value: ViewErrorValue): string[] => {\n if (Array.isArray(value)) {\n return value.flatMap(item => toMessages(item))\n }\n\n if (value instanceof Error) {\n return [value.message]\n }\n\n if (isRecord(value) && typeof value.message === 'string') {\n return [value.message]\n }\n\n if (value === null || typeof value === 'undefined') {\n return []\n }\n\n return [String(value)]\n}\n\nconst getMessageRecord = (source: unknown): ViewErrorRecord | undefined => {\n if (!isRecord(source)) {\n return undefined\n }\n\n if (typeof source.getMessageBag === 'function') {\n const bag = source.getMessageBag()\n\n if (bag && bag !== source) {\n const messages = getMessageRecord(bag)\n\n if (messages) {\n return messages\n }\n }\n }\n\n for (const method of ['getMessages', 'messagesRaw', 'toArray']) {\n if (typeof source[method] === 'function') {\n const messages = source[method]()\n\n if (isRecord(messages)) {\n return messages\n }\n }\n }\n\n if (typeof source.errors === 'function') {\n const errors = source.errors()\n const messages = getMessageRecord(errors) || (isRecord(errors) ? errors : undefined)\n\n if (messages) {\n return messages\n }\n }\n\n return getMessageRecord(source.errors) || (isRecord(source.errors) ? source.errors : undefined)\n}\n\nexport class ViewErrorBag {\n private bag: Record<string, string[]> = {}\n\n constructor(errors?: ViewErrorRecord | ViewErrorBag | unknown) {\n if (errors) {\n this.merge(errors)\n }\n }\n\n add (field: string, message: ViewErrorValue) {\n const key = field || defaultErrorKey\n const messages = toMessages(message)\n\n if (!messages.length) {\n return this\n }\n\n this.bag[key] = [\n ...(this.bag[key] || []),\n ...messages,\n ]\n\n return this\n }\n\n merge (errors: ViewErrorRecord | ViewErrorBag | unknown) {\n const incoming = errors instanceof ViewErrorBag\n ? errors.toJSON()\n : getMessageRecord(errors) || (isRecord(errors) ? errors as ViewErrorRecord : undefined)\n\n if (!incoming) {\n return this\n }\n\n for (const [field, messages] of Object.entries(incoming)) {\n this.add(field, messages)\n }\n\n return this\n }\n\n keys () {\n return Object.keys(this.bag)\n }\n\n get (field: string = defaultErrorKey) {\n return [...(this.bag[field] || [])]\n }\n\n first (field?: string | null) {\n if (field) {\n return this.bag[field]?.[0] || ''\n }\n\n return this.all()[0] || ''\n }\n\n has (field?: string | string[] | null): boolean {\n if (Array.isArray(field)) {\n return field.every(key => this.has(key))\n }\n\n if (field) {\n return (this.bag[field]?.length || 0) > 0\n }\n\n return this.any()\n }\n\n hasAny (fields: string | string[]) {\n const keys = Array.isArray(fields) ? fields : [fields]\n\n return keys.some(key => this.has(key))\n }\n\n missing (fields: string | string[]) {\n const keys = Array.isArray(fields) ? fields : [fields]\n\n return keys.every(key => !this.has(key))\n }\n\n any () {\n return Object.values(this.bag).some(messages => messages.length > 0)\n }\n\n isEmpty () {\n return !this.any()\n }\n\n isNotEmpty () {\n return this.any()\n }\n\n count () {\n return Object.values(this.bag).reduce((total, messages) => total + messages.length, 0)\n }\n\n all () {\n return Object.values(this.bag).flat()\n }\n\n unique () {\n return [...new Set(this.all())]\n }\n\n clear (field?: string | string[]) {\n if (Array.isArray(field)) {\n for (const key of field) {\n delete this.bag[key]\n }\n\n return this\n }\n\n if (field) {\n delete this.bag[field]\n\n return this\n }\n\n this.bag = {}\n\n return this\n }\n\n forget (field: string) {\n return this.clear(field)\n }\n\n messagesRaw () {\n return this.toJSON()\n }\n\n getMessages () {\n return this.messagesRaw()\n }\n\n getMessageBag () {\n return this\n }\n\n toArray () {\n return this.toJSON()\n }\n\n toJSON () {\n return Object.entries(this.bag).reduce<Record<string, string[]>>((errors, [field, messages]) => {\n errors[field] = [...messages]\n\n return errors\n }, {})\n }\n}\n\nexport const isViewErrorBag = (value: unknown): value is Pick<ViewErrorBag, 'all' | 'first' | 'get' | 'has'> => {\n return isRecord(value)\n && typeof value.all === 'function'\n && typeof value.first === 'function'\n && typeof value.get === 'function'\n && typeof value.has === 'function'\n}\n\nexport const normalizeViewErrors = (errors?: unknown) => {\n if (isViewErrorBag(errors)) {\n return errors\n }\n\n return new ViewErrorBag(errors)\n}\n","import type { ViewData } from './types'\n\nimport { AsyncLocalStorage } from 'node:async_hooks'\nimport { normalizeViewErrors } from './ViewErrorBag'\n\nconst store = new AsyncLocalStorage<ViewData>()\n\nconst normalizeContextData = (data: ViewData = {}) => ({\n ...data,\n errors: normalizeViewErrors(data.errors),\n})\n\nconst isRecord = (value: unknown): value is Record<string, any> => {\n return !!value && typeof value === 'object' && !Array.isArray(value)\n}\n\nexport const getViewData = () => store.getStore() || {}\n\nexport const enterViewData = (data: ViewData = {}) => {\n store.enterWith(normalizeContextData({ ...getViewData(), ...data }))\n}\n\nexport const runWithViewData = async <T> (data: ViewData, callback: () => T | Promise<T>) => {\n return await store.run(normalizeContextData(data), callback)\n}\n\nexport const clearViewData = () => {\n store.disable()\n}\n\nexport const collectViewData = (context: Record<string, any>): ViewData => {\n const ctx = isRecord(context.ctx) ? context.ctx : context\n const response = isRecord(context.response) ? context.response : undefined\n const locals = {\n ...(isRecord(ctx.res?.locals) ? ctx.res.locals : {}),\n ...(isRecord(ctx.response?.source?.locals) ? ctx.response.source.locals : {}),\n ...(isRecord(response?.source?.locals) ? response.source.locals : {}),\n }\n\n return normalizeContextData({\n ...('session' in ctx ? { session: ctx.session } : {}),\n ...('httpSession' in ctx ? { httpSession: ctx.httpSession } : {}),\n ...('errors' in ctx ? { errors: ctx.errors } : {}),\n ...locals,\n })\n}\n","import { collectViewData, enterViewData } from './viewContext'\n\nimport { definePlugin as defineClearRouterPlugin } from 'clear-router/core'\n\nexport const clearRouterViewPlugin = defineClearRouterPlugin({\n name: 'arkstack-view',\n setup: ({ useHttpContext }) => {\n useHttpContext((context) => {\n enterViewData(collectViewData(context))\n })\n },\n})"],"mappings":"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"}