@lilaquadrat/design-core 0.1.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/README.md +236 -0
- package/html/index.html +25 -0
- package/html/index.mail.html +15 -0
- package/html/index.server.html +29 -0
- package/package.json +148 -0
- package/src/client-entry.ts +28 -0
- package/src/components/partials/action.partial.vue +30 -0
- package/src/components/partials/client-only.partial.vue +11 -0
- package/src/components/partials/error.partial.vue +73 -0
- package/src/components/partials/main-components.partial.vue +167 -0
- package/src/components/partials/mediadetection.partial.vue +71 -0
- package/src/components/partials/qrcode.partial.vue +35 -0
- package/src/customs.ts +12 -0
- package/src/env.d.ts +1 -0
- package/src/functions/PaymenyProviderFactory.ts +27 -0
- package/src/functions/lila-dom.ts +100 -0
- package/src/functions/shopify.provider.ts +378 -0
- package/src/functions/stripe.provider.ts +181 -0
- package/src/globals.d.ts +19 -0
- package/src/index.ts +47 -0
- package/src/interfaces/AppState.interface.ts +4 -0
- package/src/interfaces/EditorConfiguration.interface.ts +15 -0
- package/src/interfaces/EventDeclaration.interface.ts +19 -0
- package/src/interfaces/FrontendConfig.interface.ts +42 -0
- package/src/interfaces/GenericEvents.interface.ts +6 -0
- package/src/interfaces/GenericState.interface.ts +5 -0
- package/src/interfaces/IconsPartial.ts +9 -0
- package/src/interfaces/IdTokenExtended.interface.ts +7 -0
- package/src/interfaces/ModuleBaseProps.interface.ts +8 -0
- package/src/interfaces/PaymentProvider.interface.ts +13 -0
- package/src/libs/ActionNotice.ts +235 -0
- package/src/libs/Models.class.ts +482 -0
- package/src/main.ts +84 -0
- package/src/mixins/createCookieString.ts +78 -0
- package/src/mixins/createModelDeclaration.ts +29 -0
- package/src/mixins/createRouter.ts +30 -0
- package/src/mixins/date.ts +23 -0
- package/src/mixins/formatSize.ts +12 -0
- package/src/mixins/getAnchor.ts +14 -0
- package/src/mixins/getRoutes.ts +50 -0
- package/src/mixins/hasSlotContent.ts +32 -0
- package/src/mixins/hooks.ts +104 -0
- package/src/mixins/loadComponents.ts +107 -0
- package/src/mixins/logger.ts +32 -0
- package/src/mixins/replaceVariables.ts +19 -0
- package/src/mixins/scroll.ts +83 -0
- package/src/models/Address.model.ts +24 -0
- package/src/models/Contact.model.ts +22 -0
- package/src/models.ts +2 -0
- package/src/plugins/auth.ts +121 -0
- package/src/plugins/currency.ts +26 -0
- package/src/plugins/events.ts +156 -0
- package/src/plugins/filters.ts +43 -0
- package/src/plugins/inview.ts +351 -0
- package/src/plugins/replacer.ts +18 -0
- package/src/plugins/resize.ts +128 -0
- package/src/plugins/signupFlow.ts +89 -0
- package/src/plugins/traceable.ts +53 -0
- package/src/plugins/translations.ts +29 -0
- package/src/plugins/youtube.ts +80 -0
- package/src/routes.ts +132 -0
- package/src/server-entry.ts +113 -0
- package/src/stores/calls.store.ts +33 -0
- package/src/stores/cart.store.ts +186 -0
- package/src/stores/content.store.ts +83 -0
- package/src/stores/editor.store.ts +27 -0
- package/src/stores/files.store.ts +166 -0
- package/src/stores/main.store.ts +184 -0
- package/src/stores/user.store.ts +124 -0
- package/src/translations/de.ts +138 -0
- package/src/views/content.view.vue +219 -0
- package/src/views/download.view.vue +143 -0
- package/src/views/editor.view.vue +243 -0
- package/src/views/login.view.vue +82 -0
- package/src/views/signup-account.view.vue +64 -0
- package/tooling/cypress/config.ts +80 -0
- package/tooling/cypress/generate-manifest.js +5 -0
- package/tooling/cypress/manifest-utils.mjs +40 -0
- package/tooling/cypress/run-parallel.mjs +77 -0
- package/tooling/cypress/support/commands.ts +436 -0
- package/tooling/cypress/support/e2e.ts +17 -0
- package/tooling/eslint.config.js +223 -0
- package/tooling/preview.plugin.ts +134 -0
- package/tooling/ssr-test/index.mjs +391 -0
- package/tooling/stylelint.config.mjs +24 -0
- package/tooling/vite.ts +246 -0
|
@@ -0,0 +1,482 @@
|
|
|
1
|
+
import { v4 as uuid } from 'uuid';
|
|
2
|
+
import { hardCopy } from '@lilaquadrat/studio/lib/esm/frontend';
|
|
3
|
+
|
|
4
|
+
type DeclarationTypes = 'string' | 'number' | 'boolean' | 'object';
|
|
5
|
+
type SingleDeclaration = { type: 'string', default?: string } |
|
|
6
|
+
{ type: 'number', default?: number } |
|
|
7
|
+
{ type: 'boolean', default?: boolean } |
|
|
8
|
+
{ type: 'object', default?: Record<string, any> } |
|
|
9
|
+
{ type: 'array', contains: { type: DeclarationTypes }, default?: (string | number | boolean)[] } |
|
|
10
|
+
{ type: 'array', contains: { model: string }, default?: any[], defaultItems?: number } |
|
|
11
|
+
{ model: string, default?: any };
|
|
12
|
+
|
|
13
|
+
// interface ModelDeclaration<T = GenericModel> {
|
|
14
|
+
// [key in keyof T]: SingleDeclaration
|
|
15
|
+
// }
|
|
16
|
+
|
|
17
|
+
type ModelDeclaration<T> = Record<keyof T, SingleDeclaration>;
|
|
18
|
+
type ModelDeclarationExtended<T, E> = Record<Exclude<keyof T, keyof E>, SingleDeclaration>;
|
|
19
|
+
|
|
20
|
+
interface ModelOptions {
|
|
21
|
+
/**
|
|
22
|
+
* uuid will be automatically added
|
|
23
|
+
*/
|
|
24
|
+
uuid?: boolean
|
|
25
|
+
/**
|
|
26
|
+
* the name of the models will be added as type
|
|
27
|
+
```TS
|
|
28
|
+
type: 'text-module'
|
|
29
|
+
```
|
|
30
|
+
*/
|
|
31
|
+
nameAsType?: boolean
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* defines which available model should be used as base
|
|
35
|
+
*/
|
|
36
|
+
extends?: string
|
|
37
|
+
}
|
|
38
|
+
// eslint-disable-next-line no-unused-vars
|
|
39
|
+
type ModelHook<T> = (data: T) => void;
|
|
40
|
+
|
|
41
|
+
interface ModelHooks<T> {
|
|
42
|
+
legacy?: ModelHook<T>
|
|
43
|
+
preSave?: ModelHook<T>
|
|
44
|
+
// postSave?: ModelHook<T>
|
|
45
|
+
preAdd?: ModelHook<T>
|
|
46
|
+
// postAdd?: ModelHook<T>
|
|
47
|
+
preClone?: ModelHook<T>
|
|
48
|
+
// postClone?: ModelHook<T>
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
class Models {
|
|
52
|
+
|
|
53
|
+
registeredModels: string[] = [];
|
|
54
|
+
|
|
55
|
+
declarations: Record<string, ModelDeclaration<T>> = {};
|
|
56
|
+
|
|
57
|
+
options: Record<string, ModelOptions> = {};
|
|
58
|
+
|
|
59
|
+
hooks: Record<string, ModelHooks<T>> = {};
|
|
60
|
+
|
|
61
|
+
debug: boolean = false;
|
|
62
|
+
|
|
63
|
+
constructor (debug: boolean = false) {
|
|
64
|
+
|
|
65
|
+
this.debug = debug;
|
|
66
|
+
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
// eslint-disable-next-line no-unused-vars
|
|
70
|
+
register<T>(name: string, declaration: ModelDeclaration<T>, hooks?: ModelHooks<T>, options?: ModelOptions): void;
|
|
71
|
+
|
|
72
|
+
// eslint-disable-next-line no-unused-vars
|
|
73
|
+
register<T, E>(name: string, declaration: ModelDeclarationExtended<T, E>, hooks: ModelHooks<T> | undefined, options: ModelOptions): void;
|
|
74
|
+
|
|
75
|
+
register<T, E> (name: string, declaration: ModelDeclaration<T > | ModelDeclarationExtended<T, E>, hooks: ModelHooks<T> | undefined, options?: ModelOptions) {
|
|
76
|
+
|
|
77
|
+
if (this.debug) console.debug(`registed model ${name}`);
|
|
78
|
+
// this.registeredModels[name] = declaration;
|
|
79
|
+
this.registeredModels.push(name);
|
|
80
|
+
this.declarations[name] = options?.extends ? this.extendDeclaration(declaration, options.extends) : declaration;
|
|
81
|
+
|
|
82
|
+
if(options) this.options[name] = options;
|
|
83
|
+
if(hooks) this.hooks[name] = hooks;
|
|
84
|
+
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
getDeclaration (name: string): ModelDeclaration<any> {
|
|
88
|
+
|
|
89
|
+
if (!this.declarations[name]) console.error(`DECLARATION_NOT_FOUND - ${name}`);
|
|
90
|
+
|
|
91
|
+
return this.declarations[name] as ModelDeclaration<any> ;
|
|
92
|
+
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
getOptions (name: string): ModelOptions {
|
|
96
|
+
|
|
97
|
+
return this.options[name];
|
|
98
|
+
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
extendDeclaration (declaration: ModelDeclaration, extendBase: string) {
|
|
102
|
+
|
|
103
|
+
const base = this.getDeclaration(extendBase);
|
|
104
|
+
|
|
105
|
+
if (!base) throw new Error('MODELS_EXTENDS_BASE_NOT_FOUND');
|
|
106
|
+
|
|
107
|
+
return { ...base, ...declaration };
|
|
108
|
+
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
prepareTargetObject<T> (name: string, data: T & { uuid?: string }, usecase?: 'save' | 'add' | 'clone') {
|
|
112
|
+
|
|
113
|
+
const targetObject: GenericModel = {};
|
|
114
|
+
const options = this.getOptions(name);
|
|
115
|
+
|
|
116
|
+
if (options?.uuid) {
|
|
117
|
+
|
|
118
|
+
if (usecase === 'clone') {
|
|
119
|
+
|
|
120
|
+
targetObject.uuid = uuid();
|
|
121
|
+
|
|
122
|
+
} else {
|
|
123
|
+
|
|
124
|
+
targetObject.uuid = data.uuid || uuid();
|
|
125
|
+
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
if (options?.nameAsType) {
|
|
131
|
+
|
|
132
|
+
targetObject.type = name;
|
|
133
|
+
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
return targetObject;
|
|
137
|
+
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
add<T> (data: Partial<T>, name: string, declaration?: ModelDeclaration<T>): T {
|
|
141
|
+
|
|
142
|
+
const modelData = this.setDataV2(data, this.prepareTargetObject(name, data, 'add'), declaration || this.getDeclaration(name), name, 'add');
|
|
143
|
+
|
|
144
|
+
// if (this.hooks[name]?.preAdd) this.hooks[name].preAdd(modelData);
|
|
145
|
+
|
|
146
|
+
return modelData as T;
|
|
147
|
+
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
save<T> (data: Partial<T>, name: string, declaration?: ModelDeclaration<T>): T {
|
|
151
|
+
|
|
152
|
+
const modelData = this.setDataV2(data, this.prepareTargetObject(name, data, 'save'), declaration || this.getDeclaration(name), name, 'save') as T;
|
|
153
|
+
|
|
154
|
+
// if (this.hooks[name]?.postSave) this.hooks[name].postSave(modelData);
|
|
155
|
+
|
|
156
|
+
return modelData as T;
|
|
157
|
+
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
clone<T> (data: Partial<T>, name: string, declaration?: ModelDeclaration<T>): T {
|
|
161
|
+
|
|
162
|
+
const modelData = this.setDataV2(data, this.prepareTargetObject(name, data, 'clone'), declaration || this.getDeclaration(name), name, 'clone') as T;
|
|
163
|
+
|
|
164
|
+
// if (this.hooks[name].postClone) this.hooks[name].postClone(data);
|
|
165
|
+
|
|
166
|
+
return modelData as T;
|
|
167
|
+
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
setDataV2<T> (data: Partial<T>, targetObject: GenericModel | GenericModel[], declaration: ModelDeclaration, name: string, usecase: 'save' | 'add' | 'clone') {
|
|
171
|
+
|
|
172
|
+
if (this.debug) console.debug(data, declaration, targetObject, usecase);
|
|
173
|
+
|
|
174
|
+
const keys = Object.keys(declaration || {});
|
|
175
|
+
|
|
176
|
+
// if (typeof this.legacy === 'function' && legacy) {
|
|
177
|
+
|
|
178
|
+
// if (data) data = this.legacy(data);
|
|
179
|
+
|
|
180
|
+
// }
|
|
181
|
+
|
|
182
|
+
// if (typeof this.onSave === 'function' && usecase === 'save') {
|
|
183
|
+
|
|
184
|
+
// if (data) data = this.onSave(data);
|
|
185
|
+
|
|
186
|
+
// }
|
|
187
|
+
|
|
188
|
+
if (usecase === 'save') {
|
|
189
|
+
|
|
190
|
+
if (this.hooks[name]?.preSave) this.hooks[name].preSave(data);
|
|
191
|
+
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
if (usecase === 'clone') {
|
|
195
|
+
|
|
196
|
+
if (this.hooks[name]?.preClone) this.hooks[name].preClone(data);
|
|
197
|
+
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
if (usecase === 'add') {
|
|
201
|
+
|
|
202
|
+
if (this.hooks[name]?.preAdd) this.hooks[name].preAdd(data);
|
|
203
|
+
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
if (usecase === 'save' && Models.isEmpty(data)) return targetObject;
|
|
207
|
+
|
|
208
|
+
// remove the changed flag on save
|
|
209
|
+
// if (usecase === 'save') {
|
|
210
|
+
|
|
211
|
+
// delete this.changed;
|
|
212
|
+
|
|
213
|
+
// }
|
|
214
|
+
|
|
215
|
+
// delete this.legacy;
|
|
216
|
+
// delete this.onSave;
|
|
217
|
+
// delete this.onAdd;
|
|
218
|
+
|
|
219
|
+
keys.forEach((keyName: string) => {
|
|
220
|
+
|
|
221
|
+
if (this.debug) console.debug('START', keyName, data, declaration, declaration[keyName]);
|
|
222
|
+
|
|
223
|
+
const currentDeclaration = declaration[keyName];
|
|
224
|
+
let currentData: any;
|
|
225
|
+
let safeData: Partial<T>;
|
|
226
|
+
|
|
227
|
+
if (data && !Models.isEmpty(data)) safeData = hardCopy<Partial<T>>(data);
|
|
228
|
+
if (safeData && safeData[keyName]) currentData = hardCopy(safeData[keyName]);
|
|
229
|
+
|
|
230
|
+
if (usecase === 'save' && Models.isEmpty(currentData)) return;
|
|
231
|
+
|
|
232
|
+
/**
|
|
233
|
+
* SPECIAL CASE type
|
|
234
|
+
* dont override the type of the module
|
|
235
|
+
*/
|
|
236
|
+
// if (name === 'type' && currentData) {
|
|
237
|
+
|
|
238
|
+
// targetObject.type = currentData;
|
|
239
|
+
// return;
|
|
240
|
+
|
|
241
|
+
// }
|
|
242
|
+
|
|
243
|
+
if ('type' in currentDeclaration) {
|
|
244
|
+
|
|
245
|
+
if (currentData) {
|
|
246
|
+
|
|
247
|
+
if (this.debug) console.debug('CHECK CURRENTDATA TYPE', typeof currentData === currentDeclaration.type, currentDeclaration.type, keyName, currentData, currentDeclaration);
|
|
248
|
+
|
|
249
|
+
if (typeof currentData !== currentDeclaration.type && currentDeclaration.type !== 'array' && !Models.isModel(currentDeclaration)) currentData = undefined;
|
|
250
|
+
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
/**
|
|
254
|
+
* if usecase is save an no data is given, dont add default values
|
|
255
|
+
*/
|
|
256
|
+
if (usecase === 'save' && Models.isEmpty(currentData)) {
|
|
257
|
+
|
|
258
|
+
// delete declaration[name];
|
|
259
|
+
return;
|
|
260
|
+
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
// if (name === 'legacy') return targetObject;
|
|
264
|
+
// if (name === 'onSave') return targetObject;
|
|
265
|
+
|
|
266
|
+
/**
|
|
267
|
+
* string and number gets assigned
|
|
268
|
+
*/
|
|
269
|
+
if (['string', 'number', 'boolean', 'object'].includes(currentDeclaration.type)) {
|
|
270
|
+
|
|
271
|
+
targetObject[keyName] = currentData || Models.getDefaultValue(currentDeclaration);
|
|
272
|
+
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
/**
|
|
276
|
+
* array
|
|
277
|
+
*/
|
|
278
|
+
if (currentDeclaration.type === 'array') {
|
|
279
|
+
|
|
280
|
+
const arrayContains = currentDeclaration.contains;
|
|
281
|
+
|
|
282
|
+
if ('type' in arrayContains) {
|
|
283
|
+
|
|
284
|
+
if (['string', 'number'].includes(arrayContains.type)) {
|
|
285
|
+
|
|
286
|
+
if (this.debug) console.debug('SET ARRAY STRING/NUMBER', currentData);
|
|
287
|
+
|
|
288
|
+
targetObject[keyName] = currentData?.slice(0) || Models.getDefaultValue(currentDeclaration);
|
|
289
|
+
|
|
290
|
+
}
|
|
291
|
+
|
|
292
|
+
if (arrayContains.type === 'object') {
|
|
293
|
+
|
|
294
|
+
targetObject[keyName] = [];
|
|
295
|
+
|
|
296
|
+
// only add non empty objects to the array
|
|
297
|
+
currentData?.forEach((single) => {
|
|
298
|
+
|
|
299
|
+
// skip if single is empty
|
|
300
|
+
if (usecase === 'save' && Models.isEmpty(single)) return;
|
|
301
|
+
|
|
302
|
+
// only add if the result is not empty
|
|
303
|
+
if (!Models.isEmpty(single)) targetObject[keyName].push(single);
|
|
304
|
+
|
|
305
|
+
});
|
|
306
|
+
|
|
307
|
+
if (!targetObject[keyName].length) delete targetObject[keyName];
|
|
308
|
+
|
|
309
|
+
}
|
|
310
|
+
|
|
311
|
+
}
|
|
312
|
+
|
|
313
|
+
if ('model' in arrayContains) {
|
|
314
|
+
|
|
315
|
+
if (this.debug) console.debug('SET ARRAY MODEL', keyName, currentData, arrayContains?.model);
|
|
316
|
+
|
|
317
|
+
targetObject[keyName] = [];
|
|
318
|
+
|
|
319
|
+
if (this.debug) console.debug(keyName, currentData);
|
|
320
|
+
|
|
321
|
+
/**
|
|
322
|
+
* currentdata could be an array with an empty object [{}] which will not count as empty for the Model.isEmpty function
|
|
323
|
+
* therefore we need to handle the possible empty data here
|
|
324
|
+
*/
|
|
325
|
+
|
|
326
|
+
if (currentData) {
|
|
327
|
+
|
|
328
|
+
currentData?.forEach((single) => {
|
|
329
|
+
|
|
330
|
+
// skip if single is empty
|
|
331
|
+
if (usecase === 'save' && Models.isEmpty(single)) return;
|
|
332
|
+
|
|
333
|
+
const pushData = this.setDataV2(single, {}, this.getDeclaration(arrayContains?.model), arrayContains?.model, usecase);
|
|
334
|
+
|
|
335
|
+
// only add if the result is not empty
|
|
336
|
+
if (!Models.isEmpty(pushData)) targetObject[keyName].push(pushData);
|
|
337
|
+
|
|
338
|
+
});
|
|
339
|
+
|
|
340
|
+
if (!targetObject[keyName].length) delete targetObject[keyName];
|
|
341
|
+
|
|
342
|
+
} else if (usecase !== 'save') {
|
|
343
|
+
|
|
344
|
+
targetObject[keyName].push(this.setDataV2({}, {}, this.getDeclaration(arrayContains?.model), arrayContains?.model, usecase));
|
|
345
|
+
|
|
346
|
+
}
|
|
347
|
+
|
|
348
|
+
if ('defaultItems' in currentDeclaration && usecase !== 'save') {
|
|
349
|
+
|
|
350
|
+
if (targetObject[keyName].length < currentDeclaration.defaultItems) {
|
|
351
|
+
|
|
352
|
+
const neededItems = currentDeclaration.defaultItems - targetObject[keyName].length;
|
|
353
|
+
|
|
354
|
+
for (let index = 0; index < neededItems; index += 1) {
|
|
355
|
+
|
|
356
|
+
targetObject[keyName].push(this.setDataV2({}, {}, this.getDeclaration(arrayContains?.model), arrayContains?.model, usecase));
|
|
357
|
+
|
|
358
|
+
}
|
|
359
|
+
|
|
360
|
+
}
|
|
361
|
+
|
|
362
|
+
}
|
|
363
|
+
|
|
364
|
+
}
|
|
365
|
+
|
|
366
|
+
}
|
|
367
|
+
|
|
368
|
+
}
|
|
369
|
+
|
|
370
|
+
/**
|
|
371
|
+
* if its an object, it will be a child model
|
|
372
|
+
*/
|
|
373
|
+
if ('model' in currentDeclaration) {
|
|
374
|
+
|
|
375
|
+
if (this.debug) console.debug('its a model', keyName, currentDeclaration, currentDeclaration?.model, targetObject);
|
|
376
|
+
|
|
377
|
+
// if (usecase === 'save' && (!currentData || (Array.isArray(currentData) && !currentData.length))) {
|
|
378
|
+
|
|
379
|
+
// // delete declaration[name];
|
|
380
|
+
// return;
|
|
381
|
+
|
|
382
|
+
//
|
|
383
|
+
|
|
384
|
+
targetObject[keyName]= this.setDataV2(currentData, {}, this.getDeclaration(currentDeclaration?.model), currentDeclaration?.model, usecase);
|
|
385
|
+
|
|
386
|
+
if (usecase === 'save') {
|
|
387
|
+
|
|
388
|
+
if (this.debug) console.debug(124, this[name], Object.keys(this[name]).length);
|
|
389
|
+
|
|
390
|
+
if (Models.isEmpty(targetObject[keyName])) {
|
|
391
|
+
|
|
392
|
+
delete targetObject[keyName];
|
|
393
|
+
|
|
394
|
+
}
|
|
395
|
+
|
|
396
|
+
}
|
|
397
|
+
|
|
398
|
+
}
|
|
399
|
+
|
|
400
|
+
});
|
|
401
|
+
|
|
402
|
+
return targetObject;
|
|
403
|
+
|
|
404
|
+
}
|
|
405
|
+
|
|
406
|
+
static isEmpty (data: any[] | Record<string, any>) {
|
|
407
|
+
|
|
408
|
+
if (!data) return true;
|
|
409
|
+
|
|
410
|
+
if (Array.isArray(data)) {
|
|
411
|
+
|
|
412
|
+
return !data.length;
|
|
413
|
+
|
|
414
|
+
}
|
|
415
|
+
|
|
416
|
+
if (typeof data === 'object') {
|
|
417
|
+
|
|
418
|
+
return !Object.keys(data).length;
|
|
419
|
+
|
|
420
|
+
}
|
|
421
|
+
|
|
422
|
+
return false;
|
|
423
|
+
|
|
424
|
+
}
|
|
425
|
+
|
|
426
|
+
static isModel (declaration: SingleDeclaration) {
|
|
427
|
+
|
|
428
|
+
return 'model' in declaration;
|
|
429
|
+
|
|
430
|
+
}
|
|
431
|
+
|
|
432
|
+
static getDefaultValue (declaration: SingleDeclaration) {
|
|
433
|
+
|
|
434
|
+
if (declaration.default) {
|
|
435
|
+
|
|
436
|
+
return declaration.default;
|
|
437
|
+
|
|
438
|
+
}
|
|
439
|
+
|
|
440
|
+
if ('type' in declaration) {
|
|
441
|
+
|
|
442
|
+
if (declaration.type === 'string') {
|
|
443
|
+
|
|
444
|
+
return '';
|
|
445
|
+
|
|
446
|
+
}
|
|
447
|
+
|
|
448
|
+
if (declaration.type === 'number') {
|
|
449
|
+
|
|
450
|
+
return 0;
|
|
451
|
+
|
|
452
|
+
}
|
|
453
|
+
|
|
454
|
+
if (declaration.type === 'boolean') {
|
|
455
|
+
|
|
456
|
+
return false;
|
|
457
|
+
|
|
458
|
+
}
|
|
459
|
+
|
|
460
|
+
if (declaration.type === 'array') {
|
|
461
|
+
|
|
462
|
+
return [];
|
|
463
|
+
|
|
464
|
+
}
|
|
465
|
+
|
|
466
|
+
}
|
|
467
|
+
|
|
468
|
+
return null;
|
|
469
|
+
|
|
470
|
+
}
|
|
471
|
+
|
|
472
|
+
}
|
|
473
|
+
|
|
474
|
+
const ModelsClass = new Models();
|
|
475
|
+
|
|
476
|
+
export default ModelsClass;
|
|
477
|
+
export {
|
|
478
|
+
Models
|
|
479
|
+
};
|
|
480
|
+
export type {
|
|
481
|
+
ModelDeclaration, ModelDeclarationExtended, ModelOptions, ModelHooks, SingleDeclaration
|
|
482
|
+
};
|
package/src/main.ts
ADDED
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
import { createApp, createSSRApp, type Component } from 'vue';
|
|
2
|
+
import { createPinia, type StateTree } from 'pinia';
|
|
3
|
+
import createRouter from './mixins/createRouter';
|
|
4
|
+
import { loadViaDeclarationSync } from './mixins/loadComponents';
|
|
5
|
+
import i18n from './plugins/translations';
|
|
6
|
+
import resizePlugin from './plugins/resize';
|
|
7
|
+
import HelpersPlugin from './plugins/filters';
|
|
8
|
+
import youtubePlugin from './plugins/youtube';
|
|
9
|
+
import traceablePlugin from './plugins/traceable';
|
|
10
|
+
import authPlugin from './plugins/auth';
|
|
11
|
+
import replacerPlugin from './plugins/replacer';
|
|
12
|
+
import currencyPlugin from './plugins/currency';
|
|
13
|
+
import eventsPlugin from './plugins/events';
|
|
14
|
+
import './models';
|
|
15
|
+
import type { RouteRecordRaw } from 'vue-router';
|
|
16
|
+
import logger from './mixins/logger';
|
|
17
|
+
import useMainStore from './stores/main.store';
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* everything the project owns and the package cannot know: the root component
|
|
21
|
+
* (App.vue carries the global styles and the editor wiring) and the module and
|
|
22
|
+
* partial registries for both render targets.
|
|
23
|
+
*/
|
|
24
|
+
export interface AppComponents {
|
|
25
|
+
root: Component
|
|
26
|
+
modules: { name: string, component: Component }[]
|
|
27
|
+
partials: { name: string, component: Component }[]
|
|
28
|
+
modulesMail: { name: string, component: Component }[]
|
|
29
|
+
partialsMail: { name: string, component: Component }[]
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
export function getAppInstance (context: any, routes: readonly RouteRecordRaw[], isSSR: boolean, components: AppComponents) {
|
|
33
|
+
|
|
34
|
+
const app = isSSR
|
|
35
|
+
? createSSRApp(components.root)
|
|
36
|
+
: createApp(components.root);
|
|
37
|
+
const pinia = createPinia();
|
|
38
|
+
|
|
39
|
+
app.use(pinia);
|
|
40
|
+
|
|
41
|
+
if (isSSR) {
|
|
42
|
+
|
|
43
|
+
logger.ssr('set initial state');
|
|
44
|
+
pinia.state.value = window.__INITIAL_STATE__ as Record<string, StateTree>;
|
|
45
|
+
|
|
46
|
+
} else {
|
|
47
|
+
|
|
48
|
+
const mainStore = useMainStore();
|
|
49
|
+
|
|
50
|
+
mainStore.data = context.data;
|
|
51
|
+
mainStore.layout = context.layout;
|
|
52
|
+
mainStore.target = context.data?.target || 'browser';
|
|
53
|
+
mainStore.configuration = context.settings;
|
|
54
|
+
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
if(context.data?.target === 'mail') {
|
|
58
|
+
|
|
59
|
+
loadViaDeclarationSync(components.modulesMail, 'lila', 'module', app);
|
|
60
|
+
loadViaDeclarationSync(components.partialsMail, 'lila', 'partial', app);
|
|
61
|
+
|
|
62
|
+
} else {
|
|
63
|
+
|
|
64
|
+
loadViaDeclarationSync(components.modules, 'lila', 'module', app);
|
|
65
|
+
loadViaDeclarationSync(components.partials, 'lila', 'partial', app);
|
|
66
|
+
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
const router = createRouter(routes);
|
|
70
|
+
|
|
71
|
+
app.use(i18n);
|
|
72
|
+
app.use(HelpersPlugin);
|
|
73
|
+
app.use(resizePlugin);
|
|
74
|
+
app.use(youtubePlugin);
|
|
75
|
+
app.use(traceablePlugin);
|
|
76
|
+
app.use(authPlugin);
|
|
77
|
+
app.use(replacerPlugin);
|
|
78
|
+
app.use(currencyPlugin);
|
|
79
|
+
app.use(eventsPlugin);
|
|
80
|
+
|
|
81
|
+
app.use(router);
|
|
82
|
+
|
|
83
|
+
return { app, router, pinia };
|
|
84
|
+
}
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
import dayjs from 'dayjs';
|
|
2
|
+
|
|
3
|
+
interface CookieOptions {
|
|
4
|
+
expires?: {
|
|
5
|
+
value: number;
|
|
6
|
+
unit: 'days' | 'weeks' | 'months' | 'years';
|
|
7
|
+
};
|
|
8
|
+
dev?: boolean;
|
|
9
|
+
path?: string;
|
|
10
|
+
domain?: string;
|
|
11
|
+
// Allow overriding the automatically set values if needed
|
|
12
|
+
sameSite?: 'None' | 'Lax' | 'Strict';
|
|
13
|
+
secure?: boolean;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* Creates a cookie string for use with document.cookie
|
|
18
|
+
*
|
|
19
|
+
* @example
|
|
20
|
+
* // For production
|
|
21
|
+
* document.cookie = createCookieString('lila-cookies', '1');
|
|
22
|
+
* // For development
|
|
23
|
+
* document.cookie = createCookieString('lila-cookies', '1', { dev: true });
|
|
24
|
+
* // Custom values
|
|
25
|
+
* document.cookie = createCookieString('lila-cookies-accepted', cookieKeys.join(','), {
|
|
26
|
+
* expires: { value: 2, unit: 'years' }
|
|
27
|
+
* });
|
|
28
|
+
*/
|
|
29
|
+
export function createCookieString (
|
|
30
|
+
name: string,
|
|
31
|
+
value: string,
|
|
32
|
+
options: CookieOptions = {}
|
|
33
|
+
): string {
|
|
34
|
+
const {
|
|
35
|
+
expires = { value: 2, unit: 'years' },
|
|
36
|
+
dev = false,
|
|
37
|
+
path = '/',
|
|
38
|
+
domain
|
|
39
|
+
} = options;
|
|
40
|
+
// Set sameSite and secure based on dev mode
|
|
41
|
+
// Can be overridden by explicitly setting these values in options
|
|
42
|
+
const sameSite = options.sameSite ?? (dev ? 'Lax' : 'None');
|
|
43
|
+
const secure = options.secure ?? !dev;
|
|
44
|
+
const cookieParts = [`${name}=${value}`];
|
|
45
|
+
let isIframe = false;
|
|
46
|
+
|
|
47
|
+
try {
|
|
48
|
+
isIframe = window.self !== window.top;
|
|
49
|
+
} catch (e) {
|
|
50
|
+
// If an error occurs, assume the page is in an iframe.
|
|
51
|
+
isIframe = true;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
if (expires) {
|
|
55
|
+
cookieParts.push(`expires=${dayjs().add(expires.value, expires.unit).toString()}`);
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
cookieParts.push(`path=${path}`);
|
|
59
|
+
|
|
60
|
+
if (domain) {
|
|
61
|
+
cookieParts.push(`domain=${domain}`);
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
cookieParts.push(`SameSite=${sameSite}`);
|
|
65
|
+
|
|
66
|
+
if (secure) {
|
|
67
|
+
cookieParts.push('Secure');
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
if(isIframe) {
|
|
71
|
+
cookieParts.push('Partitioned');
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
console.log(cookieParts.join('; ').trim());
|
|
75
|
+
return cookieParts.join('; ').trim();
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
export default createCookieString;
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import type { SingleDeclaration } from '../libs/Models.class';
|
|
2
|
+
import type { BasicData, Structure } from '@lilaquadrat/interfaces';
|
|
3
|
+
|
|
4
|
+
export default function createModelDeclaration (structure: BasicData<Structure & {required: boolean}>): SingleDeclaration {
|
|
5
|
+
|
|
6
|
+
if(!structure) {
|
|
7
|
+
throw new Error('Structure is required');
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
switch(structure.type) {
|
|
11
|
+
case 'string':
|
|
12
|
+
case 'text':
|
|
13
|
+
return { type: 'string' };
|
|
14
|
+
|
|
15
|
+
case 'number':
|
|
16
|
+
return { type: 'number' };
|
|
17
|
+
|
|
18
|
+
case 'boolean':
|
|
19
|
+
return { type: 'boolean' };
|
|
20
|
+
|
|
21
|
+
case 'select':
|
|
22
|
+
return structure.multiple
|
|
23
|
+
? { type: 'array', contains: { type: 'string' } }
|
|
24
|
+
: { type: 'string' };
|
|
25
|
+
|
|
26
|
+
default:
|
|
27
|
+
return {} as SingleDeclaration;
|
|
28
|
+
}
|
|
29
|
+
}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { createMemoryHistory, createRouter, createWebHashHistory, createWebHistory, type RouteRecordRaw } from 'vue-router';
|
|
2
|
+
import { smartScrollBehavior } from './scroll';
|
|
3
|
+
|
|
4
|
+
function getHistory () {
|
|
5
|
+
|
|
6
|
+
if(import.meta.env.SSR) return createMemoryHistory('/');
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* the shareable static preview is opened straight from disk, where pushState
|
|
10
|
+
* is blocked and no server exists to rewrite deep links - so the route has
|
|
11
|
+
* to live in the hash
|
|
12
|
+
*/
|
|
13
|
+
if(__PREVIEW__) return createWebHashHistory();
|
|
14
|
+
|
|
15
|
+
return createWebHistory('/');
|
|
16
|
+
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
export default (routes: readonly RouteRecordRaw[]) => {
|
|
20
|
+
|
|
21
|
+
const historyMode = getHistory();
|
|
22
|
+
const router = createRouter({
|
|
23
|
+
history : historyMode,
|
|
24
|
+
routes,
|
|
25
|
+
scrollBehavior: smartScrollBehavior
|
|
26
|
+
});
|
|
27
|
+
|
|
28
|
+
return router;
|
|
29
|
+
|
|
30
|
+
};
|