@cavulsqa/create 2.9.2 → 2.10.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 +12 -1
- package/bin/create.mjs +18 -25
- package/lib/templates.mjs +56 -0
- package/package.json +13 -5
- package/templates/f7-app/CLAUDE.md +3 -0
- package/templates/f7-app/auto-imports.d.ts +15 -0
- package/templates/f7-app/package.json +6 -3
- package/templates/f7-app/src/App.vue +1 -0
- package/templates/f7-app/src/env.d.ts +1 -0
- package/templates/f7-app/src/main.ts +3 -0
- package/templates/f7-app/src/modules/demo/router/routes/demo.routes.ts +4 -16
- package/templates/f7-app/src/modules/home/router/routes/home.routes.ts +3 -11
- package/templates/f7-app/src/modules/settings/router/routes/settings.routes.ts +2 -6
- package/templates/f7-app/src/plugins/bootstrapError.ts +2 -0
- package/templates/f7-app/src/plugins/recorder.plugin.ts +155 -0
- package/templates/f7-app/src/router/global/global.routes.ts +2 -6
- package/templates/f7-app/src/shared/composables/useNavigationGuard.ts +48 -0
- package/templates/f7-app/src/shared/recorder/capacitorSink.ts +124 -0
- package/templates/f7-app/src/shared/utils/lazyRoute.ts +25 -0
- package/templates/f7-app/tests/lazyRoute.test.ts +30 -0
- package/templates/f7-app/tests/navigationGuard.test.ts +82 -0
- package/templates/f7-app/vite.config.ts +1 -0
- package/templates/m3e-app/.claude/rules/data-fetching.md +68 -0
- package/templates/m3e-app/.claude/rules/database.md +106 -0
- package/templates/m3e-app/.claude/rules/m3e-ui.md +48 -0
- package/templates/m3e-app/.claude/rules/modules.md +43 -0
- package/templates/m3e-app/.claude/rules/native.md +60 -0
- package/templates/m3e-app/.claude/skills/m3-expressive/SKILL.md +68 -0
- package/templates/m3e-app/.claude/skills/m3-expressive/color.md +44 -0
- package/templates/m3e-app/.claude/skills/m3-expressive/components.md +325 -0
- package/templates/m3e-app/.claude/skills/m3-expressive/layout.md +42 -0
- package/templates/m3e-app/.claude/skills/m3-expressive/motion.md +51 -0
- package/templates/m3e-app/.claude/skills/m3-expressive/shapes-type.md +48 -0
- package/templates/m3e-app/.claude/skills/m3-expressive/sources.md +53 -0
- package/templates/m3e-app/.claude/skills/module-architecture/SKILL.md +65 -0
- package/templates/m3e-app/.claude/skills/module-architecture/file-templates.md +178 -0
- package/templates/m3e-app/.claude/skills/reactive-data/SKILL.md +90 -0
- package/templates/m3e-app/.claude/skills/reactive-data/testing.md +55 -0
- package/templates/m3e-app/.env.example +32 -0
- package/templates/m3e-app/CLAUDE.md +93 -0
- package/templates/m3e-app/auto-imports.d.ts +851 -0
- package/templates/m3e-app/capacitor.config.ts +44 -0
- package/templates/m3e-app/components.d.ts +252 -0
- package/templates/m3e-app/index.html +16 -0
- package/templates/m3e-app/package.json +107 -0
- package/templates/m3e-app/src/App.vue +129 -0
- package/templates/m3e-app/src/app/pragmas.config.ts +35 -0
- package/templates/m3e-app/src/app/scroll.config.ts +20 -0
- package/templates/m3e-app/src/app/storage.config.ts +65 -0
- package/templates/m3e-app/src/app/tabs.ts +33 -0
- package/templates/m3e-app/src/app/theme.config.ts +51 -0
- package/templates/m3e-app/src/assets/css/app.css +18 -0
- package/templates/m3e-app/src/assets/css/base.css +53 -0
- package/templates/m3e-app/src/assets/css/layout/container-transform.css +113 -0
- package/templates/m3e-app/src/assets/css/layout/shell.css +69 -0
- package/templates/m3e-app/src/assets/css/layout/transitions.css +121 -0
- package/templates/m3e-app/src/assets/css/m3e.css +6 -0
- package/templates/m3e-app/src/assets/css/theme/framework7.css +18 -0
- package/templates/m3e-app/src/assets/css/theme/tailwind.css +365 -0
- package/templates/m3e-app/src/domains/benchmark/benchmark.dataset.ts +209 -0
- package/templates/m3e-app/src/domains/benchmark/benchmark.suite.ts +662 -0
- package/templates/m3e-app/src/domains/sales/sales.repository.ts +458 -0
- package/templates/m3e-app/src/env.d.ts +40 -0
- package/templates/m3e-app/src/locales/ar.json +1260 -0
- package/templates/m3e-app/src/locales/en.json +1260 -0
- package/templates/m3e-app/src/locales/fr.json +1260 -0
- package/templates/m3e-app/src/main.ts +41 -0
- package/templates/m3e-app/src/modules/demo/components/DemoBenchmark.vue +119 -0
- package/templates/m3e-app/src/modules/demo/components/DemoBusLog.vue +63 -0
- package/templates/m3e-app/src/modules/demo/components/DemoCreateOrderSheet.vue +203 -0
- package/templates/m3e-app/src/modules/demo/components/DemoMetricsSheet.vue +75 -0
- package/templates/m3e-app/src/modules/demo/components/DemoOrderList.vue +75 -0
- package/templates/m3e-app/src/modules/demo/components/DemoPipelineBenchmark.vue +65 -0
- package/templates/m3e-app/src/modules/demo/components/DemoStatCards.vue +71 -0
- package/templates/m3e-app/src/modules/demo/composables/useBenchmark.ts +139 -0
- package/templates/m3e-app/src/modules/demo/composables/useOrderStatus.ts +64 -0
- package/templates/m3e-app/src/modules/demo/composables/useReactiveDemo.ts +171 -0
- package/templates/m3e-app/src/modules/demo/router/routes/demo.routes.ts +22 -0
- package/templates/m3e-app/src/modules/demo/views/DemoView.vue +210 -0
- package/templates/m3e-app/src/modules/demo/views/OrderDetailView.vue +136 -0
- package/templates/m3e-app/src/modules/demo/views/OrderSearchView.vue +74 -0
- package/templates/m3e-app/src/modules/gallery/components/GalleryBlock.vue +16 -0
- package/templates/m3e-app/src/modules/gallery/components/GalleryCarouselTile.vue +71 -0
- package/templates/m3e-app/src/modules/gallery/components/GalleryCustomerForm.vue +76 -0
- package/templates/m3e-app/src/modules/gallery/components/GalleryProofOfDelivery.vue +69 -0
- package/templates/m3e-app/src/modules/gallery/components/agenda/AgendaDay.vue +106 -0
- package/templates/m3e-app/src/modules/gallery/components/agenda/AgendaMonth.vue +40 -0
- package/templates/m3e-app/src/modules/gallery/components/agenda/AgendaVisitList.vue +45 -0
- package/templates/m3e-app/src/modules/gallery/components/chat/ChatAttachSheet.vue +106 -0
- package/templates/m3e-app/src/modules/gallery/components/chat/ChatContactPicker.vue +85 -0
- package/templates/m3e-app/src/modules/gallery/components/chat/ChatInviteComposer.vue +131 -0
- package/templates/m3e-app/src/modules/gallery/components/chat/ChatPollComposer.vue +148 -0
- package/templates/m3e-app/src/modules/gallery/components/chat/ChatRecentPhotos.vue +62 -0
- package/templates/m3e-app/src/modules/gallery/components/inputs/InputsAccount.vue +79 -0
- package/templates/m3e-app/src/modules/gallery/components/inputs/InputsTags.vue +53 -0
- package/templates/m3e-app/src/modules/gallery/components/inputs/InputsVerification.vue +73 -0
- package/templates/m3e-app/src/modules/gallery/components/inputs/PasswordStrength.vue +37 -0
- package/templates/m3e-app/src/modules/gallery/components/sections/GalleryButtons.vue +128 -0
- package/templates/m3e-app/src/modules/gallery/components/sections/GalleryCarousels.vue +236 -0
- package/templates/m3e-app/src/modules/gallery/components/sections/GalleryCharts.vue +84 -0
- package/templates/m3e-app/src/modules/gallery/components/sections/GalleryFabs.vue +70 -0
- package/templates/m3e-app/src/modules/gallery/components/sections/GalleryInputs.vue +219 -0
- package/templates/m3e-app/src/modules/gallery/components/sections/GalleryNavigation.vue +141 -0
- package/templates/m3e-app/src/modules/gallery/components/sections/GalleryOverlays.vue +368 -0
- package/templates/m3e-app/src/modules/gallery/components/sections/GalleryPickers.vue +175 -0
- package/templates/m3e-app/src/modules/gallery/components/sections/GalleryProgress.vue +118 -0
- package/templates/m3e-app/src/modules/gallery/components/sections/GalleryScale.vue +103 -0
- package/templates/m3e-app/src/modules/gallery/components/sections/GallerySelection.vue +219 -0
- package/templates/m3e-app/src/modules/gallery/components/sections/GalleryShapes.vue +48 -0
- package/templates/m3e-app/src/modules/gallery/components/sections/GallerySurfaces.vue +213 -0
- package/templates/m3e-app/src/modules/gallery/components/sections/GalleryTables.vue +185 -0
- package/templates/m3e-app/src/modules/gallery/components/surfaces/SurfacesContainerTransform.vue +46 -0
- package/templates/m3e-app/src/modules/gallery/composables/chatTeam.ts +18 -0
- package/templates/m3e-app/src/modules/gallery/composables/composeKind.ts +2 -0
- package/templates/m3e-app/src/modules/gallery/composables/currentPosition.ts +35 -0
- package/templates/m3e-app/src/modules/gallery/composables/demoOrders.ts +29 -0
- package/templates/m3e-app/src/modules/gallery/composables/featuredStories.ts +73 -0
- package/templates/m3e-app/src/modules/gallery/composables/fieldFormats.ts +36 -0
- package/templates/m3e-app/src/modules/gallery/composables/openExternal.ts +11 -0
- package/templates/m3e-app/src/modules/gallery/composables/routePlan.ts +90 -0
- package/templates/m3e-app/src/modules/gallery/composables/useAgenda.ts +61 -0
- package/templates/m3e-app/src/modules/gallery/composables/useChatCustomers.ts +31 -0
- package/templates/m3e-app/src/modules/gallery/composables/useChatDemo.ts +299 -0
- package/templates/m3e-app/src/modules/gallery/composables/useGallerySections.ts +230 -0
- package/templates/m3e-app/src/modules/gallery/composables/useLocalAttachments.ts +71 -0
- package/templates/m3e-app/src/modules/gallery/composables/useLocationShare.ts +38 -0
- package/templates/m3e-app/src/modules/gallery/composables/usePhotoScenes.ts +82 -0
- package/templates/m3e-app/src/modules/gallery/composables/useTreeDemo.ts +67 -0
- package/templates/m3e-app/src/modules/gallery/composables/wilayas.ts +67 -0
- package/templates/m3e-app/src/modules/gallery/router/routes/gallery.routes.ts +52 -0
- package/templates/m3e-app/src/modules/gallery/views/GalleryAgendaView.vue +117 -0
- package/templates/m3e-app/src/modules/gallery/views/GalleryChatView.vue +292 -0
- package/templates/m3e-app/src/modules/gallery/views/GalleryContactsView.vue +77 -0
- package/templates/m3e-app/src/modules/gallery/views/GalleryFeaturedView.vue +60 -0
- package/templates/m3e-app/src/modules/gallery/views/GalleryLoginView.vue +135 -0
- package/templates/m3e-app/src/modules/gallery/views/GalleryOnboardingView.vue +116 -0
- package/templates/m3e-app/src/modules/gallery/views/GallerySectionView.vue +27 -0
- package/templates/m3e-app/src/modules/gallery/views/GalleryTabsView.vue +135 -0
- package/templates/m3e-app/src/modules/gallery/views/GalleryView.vue +50 -0
- package/templates/m3e-app/src/modules/home/components/HomeHero.vue +57 -0
- package/templates/m3e-app/src/modules/home/composables/useHomeFeatures.ts +128 -0
- package/templates/m3e-app/src/modules/home/composables/useOpenFeature.ts +22 -0
- package/templates/m3e-app/src/modules/home/router/routes/home.routes.ts +21 -0
- package/templates/m3e-app/src/modules/home/views/FeatureDetailView.vue +66 -0
- package/templates/m3e-app/src/modules/home/views/HomeView.vue +47 -0
- package/templates/m3e-app/src/modules/settings/components/RolePalette.vue +38 -0
- package/templates/m3e-app/src/modules/settings/components/SeedSwatches.vue +41 -0
- package/templates/m3e-app/src/modules/settings/components/SettingsChoice.vue +43 -0
- package/templates/m3e-app/src/modules/settings/components/StudioPreview.vue +52 -0
- package/templates/m3e-app/src/modules/settings/router/routes/settings.routes.ts +17 -0
- package/templates/m3e-app/src/modules/settings/types.ts +7 -0
- package/templates/m3e-app/src/modules/settings/views/ColorStudioView.vue +166 -0
- package/templates/m3e-app/src/modules/settings/views/SettingsView.vue +157 -0
- package/templates/m3e-app/src/plugins/bootstrapError.ts +62 -0
- package/templates/m3e-app/src/plugins/capacitor/index.ts +14 -0
- package/templates/m3e-app/src/plugins/capacitor/useAndroidBackButton.ts +36 -0
- package/templates/m3e-app/src/plugins/capacitor/useKeyboard.ts +48 -0
- package/templates/m3e-app/src/plugins/capacitor/useSplashScreen.ts +43 -0
- package/templates/m3e-app/src/plugins/capacitor/useStatusBar.ts +16 -0
- package/templates/m3e-app/src/plugins/framework7.plugin.ts +36 -0
- package/templates/m3e-app/src/plugins/i18n.plugin.ts +87 -0
- package/templates/m3e-app/src/plugins/m3e.plugin.ts +22 -0
- package/templates/m3e-app/src/plugins/seed.plugin.ts +7 -0
- package/templates/m3e-app/src/plugins/sqlite.plugin.ts +32 -0
- package/templates/m3e-app/src/router/global/global.routes.ts +12 -0
- package/templates/m3e-app/src/router/index.ts +20 -0
- package/templates/m3e-app/src/shared/components/error/404.vue +13 -0
- package/templates/m3e-app/src/shared/components/layout/EmptyState.vue +30 -0
- package/templates/m3e-app/src/shared/components/layout/SectionHeader.vue +10 -0
- package/templates/m3e-app/src/shared/components/page/AppPage.vue +104 -0
- package/templates/m3e-app/src/shared/composables/navigation/useActiveTab.ts +39 -0
- package/templates/m3e-app/src/shared/composables/navigation/useContainerTransform.ts +117 -0
- package/templates/m3e-app/src/shared/composables/navigation/useNavigationGuard.ts +48 -0
- package/templates/m3e-app/src/shared/composables/navigation/useNavigationVisibility.ts +64 -0
- package/templates/m3e-app/src/shared/composables/navigation/useViewRouter.ts +25 -0
- package/templates/m3e-app/src/shared/composables/navigation/useWindowClass.ts +22 -0
- package/templates/m3e-app/src/shared/composables/theme/useThemeSettings.ts +155 -0
- package/templates/m3e-app/src/shared/database/candidates/capacitorSqlite.ts +36 -0
- package/templates/m3e-app/src/shared/database/candidates/index.ts +4 -0
- package/templates/m3e-app/src/shared/database/candidates/opfsSahPool.ts +25 -0
- package/templates/m3e-app/src/shared/database/candidates/types.ts +56 -0
- package/templates/m3e-app/src/shared/database/candidates/waSqlite.ts +56 -0
- package/templates/m3e-app/src/shared/database/database.ts +219 -0
- package/templates/m3e-app/src/shared/database/index.ts +3 -0
- package/templates/m3e-app/src/shared/database/migrations.ts +223 -0
- package/templates/m3e-app/src/shared/database/opfs.worker.ts +5 -0
- package/templates/m3e-app/src/shared/database/queries.ts +26 -0
- package/templates/m3e-app/src/shared/database/schema.ts +153 -0
- package/templates/m3e-app/src/shared/database/storage.ts +64 -0
- package/templates/m3e-app/src/shared/database/wa.worker.ts +5 -0
- package/templates/m3e-app/src/shared/utils/lazyRoute.ts +41 -0
- package/templates/m3e-app/src/shared/utils/resolvers/resolvers.ts +42 -0
- package/templates/m3e-app/src/shared/utils/textDirection.ts +22 -0
- package/templates/m3e-app/src/shared/utils/theme/themeSettings.ts +59 -0
- package/templates/m3e-app/src/shared/utils/tone.ts +8 -0
- package/templates/m3e-app/tests/benchmark.suite.test.ts +104 -0
- package/templates/m3e-app/tests/containerTransform.test.ts +58 -0
- package/templates/m3e-app/tests/fieldFormats.test.ts +25 -0
- package/templates/m3e-app/tests/lazyRoute.test.ts +30 -0
- package/templates/m3e-app/tests/locales.test.ts +73 -0
- package/templates/m3e-app/tests/migrations.test.ts +74 -0
- package/templates/m3e-app/tests/navigationGuard.test.ts +82 -0
- package/templates/m3e-app/tests/openDatabase.test.ts +54 -0
- package/templates/m3e-app/tests/sales.repository.test.ts +329 -0
- package/templates/m3e-app/tests/storage.test.ts +117 -0
- package/templates/m3e-app/tests/textDirection.test.ts +11 -0
- package/templates/m3e-app/tooling/linkedPackages.ts +112 -0
- package/templates/m3e-app/tsconfig.json +21 -0
- package/templates/m3e-app/vite.config.ts +144 -0
|
@@ -0,0 +1,365 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Tailwind speaks Material here and nothing else. Its default palette, radii, shadows and easings
|
|
3
|
+
* are cleared, then refilled from the M3 tokens, so `bg-red-500` or `rounded-3xl` simply do not
|
|
4
|
+
* exist - a colour that is not a role cannot be written. `inline` keeps each utility a `var()`, so
|
|
5
|
+
* a dark-mode or seed change repaints without a rebuild.
|
|
6
|
+
*/
|
|
7
|
+
@theme inline {
|
|
8
|
+
--color-*: initial;
|
|
9
|
+
--color-transparent: transparent;
|
|
10
|
+
--color-current: currentColor;
|
|
11
|
+
--color-white: #fff;
|
|
12
|
+
--color-black: #000;
|
|
13
|
+
--color-primary: var(--md-sys-color-primary);
|
|
14
|
+
--color-on-primary: var(--md-sys-color-on-primary);
|
|
15
|
+
--color-primary-container: var(--md-sys-color-primary-container);
|
|
16
|
+
--color-on-primary-container: var(--md-sys-color-on-primary-container);
|
|
17
|
+
--color-inverse-primary: var(--md-sys-color-inverse-primary);
|
|
18
|
+
--color-primary-fixed: var(--md-sys-color-primary-fixed);
|
|
19
|
+
--color-primary-fixed-dim: var(--md-sys-color-primary-fixed-dim);
|
|
20
|
+
--color-on-primary-fixed: var(--md-sys-color-on-primary-fixed);
|
|
21
|
+
--color-on-primary-fixed-variant: var(--md-sys-color-on-primary-fixed-variant);
|
|
22
|
+
--color-secondary: var(--md-sys-color-secondary);
|
|
23
|
+
--color-on-secondary: var(--md-sys-color-on-secondary);
|
|
24
|
+
--color-secondary-container: var(--md-sys-color-secondary-container);
|
|
25
|
+
--color-on-secondary-container: var(--md-sys-color-on-secondary-container);
|
|
26
|
+
--color-secondary-fixed: var(--md-sys-color-secondary-fixed);
|
|
27
|
+
--color-secondary-fixed-dim: var(--md-sys-color-secondary-fixed-dim);
|
|
28
|
+
--color-on-secondary-fixed: var(--md-sys-color-on-secondary-fixed);
|
|
29
|
+
--color-on-secondary-fixed-variant: var(--md-sys-color-on-secondary-fixed-variant);
|
|
30
|
+
--color-tertiary: var(--md-sys-color-tertiary);
|
|
31
|
+
--color-on-tertiary: var(--md-sys-color-on-tertiary);
|
|
32
|
+
--color-tertiary-container: var(--md-sys-color-tertiary-container);
|
|
33
|
+
--color-on-tertiary-container: var(--md-sys-color-on-tertiary-container);
|
|
34
|
+
--color-tertiary-fixed: var(--md-sys-color-tertiary-fixed);
|
|
35
|
+
--color-tertiary-fixed-dim: var(--md-sys-color-tertiary-fixed-dim);
|
|
36
|
+
--color-on-tertiary-fixed: var(--md-sys-color-on-tertiary-fixed);
|
|
37
|
+
--color-on-tertiary-fixed-variant: var(--md-sys-color-on-tertiary-fixed-variant);
|
|
38
|
+
--color-error: var(--md-sys-color-error);
|
|
39
|
+
--color-on-error: var(--md-sys-color-on-error);
|
|
40
|
+
--color-error-container: var(--md-sys-color-error-container);
|
|
41
|
+
--color-on-error-container: var(--md-sys-color-on-error-container);
|
|
42
|
+
--color-background: var(--md-sys-color-background);
|
|
43
|
+
--color-on-background: var(--md-sys-color-on-background);
|
|
44
|
+
--color-surface: var(--md-sys-color-surface);
|
|
45
|
+
--color-surface-dim: var(--md-sys-color-surface-dim);
|
|
46
|
+
--color-surface-bright: var(--md-sys-color-surface-bright);
|
|
47
|
+
--color-surface-container-lowest: var(--md-sys-color-surface-container-lowest);
|
|
48
|
+
--color-surface-container-low: var(--md-sys-color-surface-container-low);
|
|
49
|
+
--color-surface-container: var(--md-sys-color-surface-container);
|
|
50
|
+
--color-surface-container-high: var(--md-sys-color-surface-container-high);
|
|
51
|
+
--color-surface-container-highest: var(--md-sys-color-surface-container-highest);
|
|
52
|
+
--color-on-surface: var(--md-sys-color-on-surface);
|
|
53
|
+
--color-surface-variant: var(--md-sys-color-surface-variant);
|
|
54
|
+
--color-on-surface-variant: var(--md-sys-color-on-surface-variant);
|
|
55
|
+
--color-inverse-surface: var(--md-sys-color-inverse-surface);
|
|
56
|
+
--color-inverse-on-surface: var(--md-sys-color-inverse-on-surface);
|
|
57
|
+
--color-surface-tint: var(--md-sys-color-surface-tint);
|
|
58
|
+
--color-outline: var(--md-sys-color-outline);
|
|
59
|
+
--color-outline-variant: var(--md-sys-color-outline-variant);
|
|
60
|
+
--color-shadow: var(--md-sys-color-shadow);
|
|
61
|
+
--color-scrim: var(--md-sys-color-scrim);
|
|
62
|
+
--color-success: var(--md-sys-color-success);
|
|
63
|
+
--color-on-success: var(--md-sys-color-on-success);
|
|
64
|
+
--color-success-container: var(--md-sys-color-success-container);
|
|
65
|
+
--color-on-success-container: var(--md-sys-color-on-success-container);
|
|
66
|
+
--color-warning: var(--md-sys-color-warning);
|
|
67
|
+
--color-on-warning: var(--md-sys-color-on-warning);
|
|
68
|
+
--color-warning-container: var(--md-sys-color-warning-container);
|
|
69
|
+
--color-on-warning-container: var(--md-sys-color-on-warning-container);
|
|
70
|
+
|
|
71
|
+
--font-*: initial;
|
|
72
|
+
--font-sans: var(--md-ref-typeface-plain);
|
|
73
|
+
--font-brand: var(--md-ref-typeface-brand);
|
|
74
|
+
|
|
75
|
+
--radius-*: initial;
|
|
76
|
+
--radius-none: var(--md-sys-shape-corner-none);
|
|
77
|
+
--radius-xs: var(--md-sys-shape-corner-extra-small);
|
|
78
|
+
--radius-sm: var(--md-sys-shape-corner-small);
|
|
79
|
+
--radius-md: var(--md-sys-shape-corner-medium);
|
|
80
|
+
--radius-lg: var(--md-sys-shape-corner-large);
|
|
81
|
+
--radius-lg-increased: var(--md-sys-shape-corner-large-increased);
|
|
82
|
+
--radius-xl: var(--md-sys-shape-corner-extra-large);
|
|
83
|
+
--radius-xl-increased: var(--md-sys-shape-corner-extra-large-increased);
|
|
84
|
+
--radius-2xl: var(--md-sys-shape-corner-extra-extra-large);
|
|
85
|
+
--radius-full: var(--md-sys-shape-corner-full);
|
|
86
|
+
|
|
87
|
+
--shadow-*: initial;
|
|
88
|
+
--shadow-0: var(--md-sys-elevation-level0);
|
|
89
|
+
--shadow-1: var(--md-sys-elevation-level1);
|
|
90
|
+
--shadow-2: var(--md-sys-elevation-level2);
|
|
91
|
+
--shadow-3: var(--md-sys-elevation-level3);
|
|
92
|
+
--shadow-4: var(--md-sys-elevation-level4);
|
|
93
|
+
--shadow-5: var(--md-sys-elevation-level5);
|
|
94
|
+
|
|
95
|
+
--ease-*: initial;
|
|
96
|
+
--ease-emphasized: var(--md-sys-motion-easing-emphasized);
|
|
97
|
+
--ease-emphasized-decelerate: var(--md-sys-motion-easing-emphasized-decelerate);
|
|
98
|
+
--ease-emphasized-accelerate: var(--md-sys-motion-easing-emphasized-accelerate);
|
|
99
|
+
--ease-standard: var(--md-sys-motion-easing-standard);
|
|
100
|
+
--ease-standard-decelerate: var(--md-sys-motion-easing-standard-decelerate);
|
|
101
|
+
--ease-standard-accelerate: var(--md-sys-motion-easing-standard-accelerate);
|
|
102
|
+
--ease-fast-spatial: var(--md-sys-motion-spring-fast-spatial);
|
|
103
|
+
--ease-default-spatial: var(--md-sys-motion-spring-default-spatial);
|
|
104
|
+
--ease-slow-spatial: var(--md-sys-motion-spring-slow-spatial);
|
|
105
|
+
--ease-fast-effects: var(--md-sys-motion-spring-fast-effects);
|
|
106
|
+
--ease-default-effects: var(--md-sys-motion-spring-default-effects);
|
|
107
|
+
--ease-slow-effects: var(--md-sys-motion-spring-slow-effects);
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
@utility type-display-large {
|
|
111
|
+
font-family: var(--md-sys-typescale-display-large-font);
|
|
112
|
+
font-size: var(--md-sys-typescale-display-large-size);
|
|
113
|
+
line-height: var(--md-sys-typescale-display-large-line-height);
|
|
114
|
+
font-weight: var(--md-sys-typescale-display-large-weight);
|
|
115
|
+
letter-spacing: var(--md-sys-typescale-display-large-tracking);
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
@utility type-display-large-emphasized {
|
|
119
|
+
font-family: var(--md-sys-typescale-display-large-font);
|
|
120
|
+
font-size: var(--md-sys-typescale-display-large-size);
|
|
121
|
+
line-height: var(--md-sys-typescale-display-large-line-height);
|
|
122
|
+
font-weight: var(--md-sys-typescale-emphasized-display-large-weight);
|
|
123
|
+
letter-spacing: var(--md-sys-typescale-emphasized-display-large-tracking);
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
@utility type-display-medium {
|
|
127
|
+
font-family: var(--md-sys-typescale-display-medium-font);
|
|
128
|
+
font-size: var(--md-sys-typescale-display-medium-size);
|
|
129
|
+
line-height: var(--md-sys-typescale-display-medium-line-height);
|
|
130
|
+
font-weight: var(--md-sys-typescale-display-medium-weight);
|
|
131
|
+
letter-spacing: var(--md-sys-typescale-display-medium-tracking);
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
@utility type-display-medium-emphasized {
|
|
135
|
+
font-family: var(--md-sys-typescale-display-medium-font);
|
|
136
|
+
font-size: var(--md-sys-typescale-display-medium-size);
|
|
137
|
+
line-height: var(--md-sys-typescale-display-medium-line-height);
|
|
138
|
+
font-weight: var(--md-sys-typescale-emphasized-display-medium-weight);
|
|
139
|
+
letter-spacing: var(--md-sys-typescale-emphasized-display-medium-tracking);
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
@utility type-display-small {
|
|
143
|
+
font-family: var(--md-sys-typescale-display-small-font);
|
|
144
|
+
font-size: var(--md-sys-typescale-display-small-size);
|
|
145
|
+
line-height: var(--md-sys-typescale-display-small-line-height);
|
|
146
|
+
font-weight: var(--md-sys-typescale-display-small-weight);
|
|
147
|
+
letter-spacing: var(--md-sys-typescale-display-small-tracking);
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
@utility type-display-small-emphasized {
|
|
151
|
+
font-family: var(--md-sys-typescale-display-small-font);
|
|
152
|
+
font-size: var(--md-sys-typescale-display-small-size);
|
|
153
|
+
line-height: var(--md-sys-typescale-display-small-line-height);
|
|
154
|
+
font-weight: var(--md-sys-typescale-emphasized-display-small-weight);
|
|
155
|
+
letter-spacing: var(--md-sys-typescale-emphasized-display-small-tracking);
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
@utility type-headline-large {
|
|
159
|
+
font-family: var(--md-sys-typescale-headline-large-font);
|
|
160
|
+
font-size: var(--md-sys-typescale-headline-large-size);
|
|
161
|
+
line-height: var(--md-sys-typescale-headline-large-line-height);
|
|
162
|
+
font-weight: var(--md-sys-typescale-headline-large-weight);
|
|
163
|
+
letter-spacing: var(--md-sys-typescale-headline-large-tracking);
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
@utility type-headline-large-emphasized {
|
|
167
|
+
font-family: var(--md-sys-typescale-headline-large-font);
|
|
168
|
+
font-size: var(--md-sys-typescale-headline-large-size);
|
|
169
|
+
line-height: var(--md-sys-typescale-headline-large-line-height);
|
|
170
|
+
font-weight: var(--md-sys-typescale-emphasized-headline-large-weight);
|
|
171
|
+
letter-spacing: var(--md-sys-typescale-emphasized-headline-large-tracking);
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
@utility type-headline-medium {
|
|
175
|
+
font-family: var(--md-sys-typescale-headline-medium-font);
|
|
176
|
+
font-size: var(--md-sys-typescale-headline-medium-size);
|
|
177
|
+
line-height: var(--md-sys-typescale-headline-medium-line-height);
|
|
178
|
+
font-weight: var(--md-sys-typescale-headline-medium-weight);
|
|
179
|
+
letter-spacing: var(--md-sys-typescale-headline-medium-tracking);
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
@utility type-headline-medium-emphasized {
|
|
183
|
+
font-family: var(--md-sys-typescale-headline-medium-font);
|
|
184
|
+
font-size: var(--md-sys-typescale-headline-medium-size);
|
|
185
|
+
line-height: var(--md-sys-typescale-headline-medium-line-height);
|
|
186
|
+
font-weight: var(--md-sys-typescale-emphasized-headline-medium-weight);
|
|
187
|
+
letter-spacing: var(--md-sys-typescale-emphasized-headline-medium-tracking);
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
@utility type-headline-small {
|
|
191
|
+
font-family: var(--md-sys-typescale-headline-small-font);
|
|
192
|
+
font-size: var(--md-sys-typescale-headline-small-size);
|
|
193
|
+
line-height: var(--md-sys-typescale-headline-small-line-height);
|
|
194
|
+
font-weight: var(--md-sys-typescale-headline-small-weight);
|
|
195
|
+
letter-spacing: var(--md-sys-typescale-headline-small-tracking);
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
@utility type-headline-small-emphasized {
|
|
199
|
+
font-family: var(--md-sys-typescale-headline-small-font);
|
|
200
|
+
font-size: var(--md-sys-typescale-headline-small-size);
|
|
201
|
+
line-height: var(--md-sys-typescale-headline-small-line-height);
|
|
202
|
+
font-weight: var(--md-sys-typescale-emphasized-headline-small-weight);
|
|
203
|
+
letter-spacing: var(--md-sys-typescale-emphasized-headline-small-tracking);
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
@utility type-title-large {
|
|
207
|
+
font-family: var(--md-sys-typescale-title-large-font);
|
|
208
|
+
font-size: var(--md-sys-typescale-title-large-size);
|
|
209
|
+
line-height: var(--md-sys-typescale-title-large-line-height);
|
|
210
|
+
font-weight: var(--md-sys-typescale-title-large-weight);
|
|
211
|
+
letter-spacing: var(--md-sys-typescale-title-large-tracking);
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
@utility type-title-large-emphasized {
|
|
215
|
+
font-family: var(--md-sys-typescale-title-large-font);
|
|
216
|
+
font-size: var(--md-sys-typescale-title-large-size);
|
|
217
|
+
line-height: var(--md-sys-typescale-title-large-line-height);
|
|
218
|
+
font-weight: var(--md-sys-typescale-emphasized-title-large-weight);
|
|
219
|
+
letter-spacing: var(--md-sys-typescale-emphasized-title-large-tracking);
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
@utility type-title-medium {
|
|
223
|
+
font-family: var(--md-sys-typescale-title-medium-font);
|
|
224
|
+
font-size: var(--md-sys-typescale-title-medium-size);
|
|
225
|
+
line-height: var(--md-sys-typescale-title-medium-line-height);
|
|
226
|
+
font-weight: var(--md-sys-typescale-title-medium-weight);
|
|
227
|
+
letter-spacing: var(--md-sys-typescale-title-medium-tracking);
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
@utility type-title-medium-emphasized {
|
|
231
|
+
font-family: var(--md-sys-typescale-title-medium-font);
|
|
232
|
+
font-size: var(--md-sys-typescale-title-medium-size);
|
|
233
|
+
line-height: var(--md-sys-typescale-title-medium-line-height);
|
|
234
|
+
font-weight: var(--md-sys-typescale-emphasized-title-medium-weight);
|
|
235
|
+
letter-spacing: var(--md-sys-typescale-emphasized-title-medium-tracking);
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
@utility type-title-small {
|
|
239
|
+
font-family: var(--md-sys-typescale-title-small-font);
|
|
240
|
+
font-size: var(--md-sys-typescale-title-small-size);
|
|
241
|
+
line-height: var(--md-sys-typescale-title-small-line-height);
|
|
242
|
+
font-weight: var(--md-sys-typescale-title-small-weight);
|
|
243
|
+
letter-spacing: var(--md-sys-typescale-title-small-tracking);
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
@utility type-title-small-emphasized {
|
|
247
|
+
font-family: var(--md-sys-typescale-title-small-font);
|
|
248
|
+
font-size: var(--md-sys-typescale-title-small-size);
|
|
249
|
+
line-height: var(--md-sys-typescale-title-small-line-height);
|
|
250
|
+
font-weight: var(--md-sys-typescale-emphasized-title-small-weight);
|
|
251
|
+
letter-spacing: var(--md-sys-typescale-emphasized-title-small-tracking);
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
@utility type-body-large {
|
|
255
|
+
font-family: var(--md-sys-typescale-body-large-font);
|
|
256
|
+
font-size: var(--md-sys-typescale-body-large-size);
|
|
257
|
+
line-height: var(--md-sys-typescale-body-large-line-height);
|
|
258
|
+
font-weight: var(--md-sys-typescale-body-large-weight);
|
|
259
|
+
letter-spacing: var(--md-sys-typescale-body-large-tracking);
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
@utility type-body-large-emphasized {
|
|
263
|
+
font-family: var(--md-sys-typescale-body-large-font);
|
|
264
|
+
font-size: var(--md-sys-typescale-body-large-size);
|
|
265
|
+
line-height: var(--md-sys-typescale-body-large-line-height);
|
|
266
|
+
font-weight: var(--md-sys-typescale-emphasized-body-large-weight);
|
|
267
|
+
letter-spacing: var(--md-sys-typescale-emphasized-body-large-tracking);
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
@utility type-body-medium {
|
|
271
|
+
font-family: var(--md-sys-typescale-body-medium-font);
|
|
272
|
+
font-size: var(--md-sys-typescale-body-medium-size);
|
|
273
|
+
line-height: var(--md-sys-typescale-body-medium-line-height);
|
|
274
|
+
font-weight: var(--md-sys-typescale-body-medium-weight);
|
|
275
|
+
letter-spacing: var(--md-sys-typescale-body-medium-tracking);
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
@utility type-body-medium-emphasized {
|
|
279
|
+
font-family: var(--md-sys-typescale-body-medium-font);
|
|
280
|
+
font-size: var(--md-sys-typescale-body-medium-size);
|
|
281
|
+
line-height: var(--md-sys-typescale-body-medium-line-height);
|
|
282
|
+
font-weight: var(--md-sys-typescale-emphasized-body-medium-weight);
|
|
283
|
+
letter-spacing: var(--md-sys-typescale-emphasized-body-medium-tracking);
|
|
284
|
+
}
|
|
285
|
+
|
|
286
|
+
@utility type-body-small {
|
|
287
|
+
font-family: var(--md-sys-typescale-body-small-font);
|
|
288
|
+
font-size: var(--md-sys-typescale-body-small-size);
|
|
289
|
+
line-height: var(--md-sys-typescale-body-small-line-height);
|
|
290
|
+
font-weight: var(--md-sys-typescale-body-small-weight);
|
|
291
|
+
letter-spacing: var(--md-sys-typescale-body-small-tracking);
|
|
292
|
+
}
|
|
293
|
+
|
|
294
|
+
@utility type-body-small-emphasized {
|
|
295
|
+
font-family: var(--md-sys-typescale-body-small-font);
|
|
296
|
+
font-size: var(--md-sys-typescale-body-small-size);
|
|
297
|
+
line-height: var(--md-sys-typescale-body-small-line-height);
|
|
298
|
+
font-weight: var(--md-sys-typescale-emphasized-body-small-weight);
|
|
299
|
+
letter-spacing: var(--md-sys-typescale-emphasized-body-small-tracking);
|
|
300
|
+
}
|
|
301
|
+
|
|
302
|
+
@utility type-label-large {
|
|
303
|
+
font-family: var(--md-sys-typescale-label-large-font);
|
|
304
|
+
font-size: var(--md-sys-typescale-label-large-size);
|
|
305
|
+
line-height: var(--md-sys-typescale-label-large-line-height);
|
|
306
|
+
font-weight: var(--md-sys-typescale-label-large-weight);
|
|
307
|
+
letter-spacing: var(--md-sys-typescale-label-large-tracking);
|
|
308
|
+
}
|
|
309
|
+
|
|
310
|
+
@utility type-label-large-emphasized {
|
|
311
|
+
font-family: var(--md-sys-typescale-label-large-font);
|
|
312
|
+
font-size: var(--md-sys-typescale-label-large-size);
|
|
313
|
+
line-height: var(--md-sys-typescale-label-large-line-height);
|
|
314
|
+
font-weight: var(--md-sys-typescale-emphasized-label-large-weight);
|
|
315
|
+
letter-spacing: var(--md-sys-typescale-emphasized-label-large-tracking);
|
|
316
|
+
}
|
|
317
|
+
|
|
318
|
+
@utility type-label-medium {
|
|
319
|
+
font-family: var(--md-sys-typescale-label-medium-font);
|
|
320
|
+
font-size: var(--md-sys-typescale-label-medium-size);
|
|
321
|
+
line-height: var(--md-sys-typescale-label-medium-line-height);
|
|
322
|
+
font-weight: var(--md-sys-typescale-label-medium-weight);
|
|
323
|
+
letter-spacing: var(--md-sys-typescale-label-medium-tracking);
|
|
324
|
+
}
|
|
325
|
+
|
|
326
|
+
@utility type-label-medium-emphasized {
|
|
327
|
+
font-family: var(--md-sys-typescale-label-medium-font);
|
|
328
|
+
font-size: var(--md-sys-typescale-label-medium-size);
|
|
329
|
+
line-height: var(--md-sys-typescale-label-medium-line-height);
|
|
330
|
+
font-weight: var(--md-sys-typescale-emphasized-label-medium-weight);
|
|
331
|
+
letter-spacing: var(--md-sys-typescale-emphasized-label-medium-tracking);
|
|
332
|
+
}
|
|
333
|
+
|
|
334
|
+
@utility type-label-small {
|
|
335
|
+
font-family: var(--md-sys-typescale-label-small-font);
|
|
336
|
+
font-size: var(--md-sys-typescale-label-small-size);
|
|
337
|
+
line-height: var(--md-sys-typescale-label-small-line-height);
|
|
338
|
+
font-weight: var(--md-sys-typescale-label-small-weight);
|
|
339
|
+
letter-spacing: var(--md-sys-typescale-label-small-tracking);
|
|
340
|
+
}
|
|
341
|
+
|
|
342
|
+
@utility type-label-small-emphasized {
|
|
343
|
+
font-family: var(--md-sys-typescale-label-small-font);
|
|
344
|
+
font-size: var(--md-sys-typescale-label-small-size);
|
|
345
|
+
line-height: var(--md-sys-typescale-label-small-line-height);
|
|
346
|
+
font-weight: var(--md-sys-typescale-emphasized-label-small-weight);
|
|
347
|
+
letter-spacing: var(--md-sys-typescale-emphasized-label-small-tracking);
|
|
348
|
+
}
|
|
349
|
+
|
|
350
|
+
/* Google Sans Flex's roundness axis: the expressive face for display moments, not body text. */
|
|
351
|
+
@utility font-rounded {
|
|
352
|
+
font-variation-settings: "ROND" 100;
|
|
353
|
+
}
|
|
354
|
+
|
|
355
|
+
@utility duration-spring-fast {
|
|
356
|
+
transition-duration: var(--md-sys-motion-spring-fast-spatial-duration);
|
|
357
|
+
}
|
|
358
|
+
|
|
359
|
+
@utility duration-spring-default {
|
|
360
|
+
transition-duration: var(--md-sys-motion-spring-default-spatial-duration);
|
|
361
|
+
}
|
|
362
|
+
|
|
363
|
+
@utility duration-spring-slow {
|
|
364
|
+
transition-duration: var(--md-sys-motion-spring-slow-spatial-duration);
|
|
365
|
+
}
|
|
@@ -0,0 +1,209 @@
|
|
|
1
|
+
import { sql, type Insertable, type Kysely } from "kysely";
|
|
2
|
+
import type { Database } from "@/shared/database/schema";
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Roughly 100k rows across ten tables, with the cardinality spread a real domain has: ten regions,
|
|
6
|
+
* five thousand customers, forty thousand order lines. A join across five of these touches a 10-row
|
|
7
|
+
* table and a 40k-row table in one query, which is where index choice starts to show.
|
|
8
|
+
*/
|
|
9
|
+
export const SCALE = {
|
|
10
|
+
regions: 10,
|
|
11
|
+
cities: 200,
|
|
12
|
+
customers: 5_000,
|
|
13
|
+
categories: 50,
|
|
14
|
+
products: 2_000,
|
|
15
|
+
warehouses: 20,
|
|
16
|
+
/** warehouses x a slice of products, the biggest table here. */
|
|
17
|
+
stock: 40_000,
|
|
18
|
+
orders: 10_000,
|
|
19
|
+
/** ~4 lines per order. */
|
|
20
|
+
orderLines: 40_000,
|
|
21
|
+
payments: 8_000,
|
|
22
|
+
} as const;
|
|
23
|
+
|
|
24
|
+
export const TOTAL_ROWS = Object.values(SCALE).reduce((sum, n) => sum + n, 0);
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* SQLite caps the parameters in one statement - 999 on older builds - so a multi-row insert is
|
|
28
|
+
* chunked by parameter budget rather than by row count. One statement per chunk instead of one per
|
|
29
|
+
* row turns a 75-second seed into a few seconds; at 0.7 ms per single-row insert, 100k rows one at a
|
|
30
|
+
* time would take over a minute of pure commit.
|
|
31
|
+
*/
|
|
32
|
+
const PARAMETER_BUDGET = 900;
|
|
33
|
+
|
|
34
|
+
async function insertMany<T extends keyof Database>(
|
|
35
|
+
db: Kysely<Database>,
|
|
36
|
+
table: T & string,
|
|
37
|
+
rows: Insertable<Database[T]>[],
|
|
38
|
+
): Promise<void> {
|
|
39
|
+
if (!rows.length) return;
|
|
40
|
+
const columns = Object.keys(rows[0] as object).length;
|
|
41
|
+
const chunk = Math.max(1, Math.floor(PARAMETER_BUDGET / Math.max(columns, 1)));
|
|
42
|
+
|
|
43
|
+
for (let index = 0; index < rows.length; index += chunk) {
|
|
44
|
+
await db
|
|
45
|
+
.insertInto(table)
|
|
46
|
+
.values(rows.slice(index, index + chunk) as never)
|
|
47
|
+
.execute();
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
const NAMES = ["Alger", "Oran", "Blida", "Setif", "Annaba", "Batna", "Djelfa", "Biskra"];
|
|
52
|
+
const METHODS = ["cash", "cheque", "transfer", "credit"];
|
|
53
|
+
const STATUSES = ["draft", "confirmed", "delivered", "cancelled"];
|
|
54
|
+
|
|
55
|
+
/** Deterministic, so two runs seed the same data and a slow query is slow for the same reason. */
|
|
56
|
+
function pseudo(seed: number, modulo: number): number {
|
|
57
|
+
return ((seed * 1103515245 + 12345) >>> 8) % modulo;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
export async function datasetRowCount(db: Kysely<Database>): Promise<number> {
|
|
61
|
+
const row = await db
|
|
62
|
+
.selectNoFrom((eb) => [
|
|
63
|
+
eb
|
|
64
|
+
.selectFrom("bench_order_line")
|
|
65
|
+
.select((e) => e.fn.countAll<number>().as("n"))
|
|
66
|
+
.as("lines"),
|
|
67
|
+
eb
|
|
68
|
+
.selectFrom("bench_stock")
|
|
69
|
+
.select((e) => e.fn.countAll<number>().as("n"))
|
|
70
|
+
.as("stock"),
|
|
71
|
+
])
|
|
72
|
+
.executeTakeFirst();
|
|
73
|
+
return Number(row?.lines ?? 0) + Number(row?.stock ?? 0);
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
/**
|
|
77
|
+
* Seeds once and stays. Re-seeding on every run would dominate the measurement, and a dataset that
|
|
78
|
+
* changes between runs makes two runs incomparable - so this is skipped when the row counts already
|
|
79
|
+
* match, and the write cases below are careful to leave the dataset as they found it.
|
|
80
|
+
*/
|
|
81
|
+
export async function ensureDataset(
|
|
82
|
+
db: Kysely<Database>,
|
|
83
|
+
onProgress?: (what: string) => void,
|
|
84
|
+
): Promise<{ seeded: boolean; rows: number }> {
|
|
85
|
+
const existing = await datasetRowCount(db);
|
|
86
|
+
if (existing >= SCALE.orderLines + SCALE.stock) return { seeded: false, rows: existing };
|
|
87
|
+
|
|
88
|
+
const at = new Date(0).toISOString();
|
|
89
|
+
const step = (what: string) => onProgress?.(`seeding ${what}`);
|
|
90
|
+
|
|
91
|
+
// Cleared in dependency order; a partial previous seed must not survive.
|
|
92
|
+
step("reset");
|
|
93
|
+
for (const table of [
|
|
94
|
+
"bench_payment",
|
|
95
|
+
"bench_order_line",
|
|
96
|
+
"bench_order",
|
|
97
|
+
"bench_stock",
|
|
98
|
+
"bench_product",
|
|
99
|
+
"bench_category",
|
|
100
|
+
"bench_customer",
|
|
101
|
+
"bench_city",
|
|
102
|
+
"bench_region",
|
|
103
|
+
"bench_warehouse",
|
|
104
|
+
] as const) {
|
|
105
|
+
await sql.raw(`DELETE FROM ${table}`).execute(db);
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
step("regions and cities");
|
|
109
|
+
await insertMany(
|
|
110
|
+
db,
|
|
111
|
+
"bench_region",
|
|
112
|
+
Array.from({ length: SCALE.regions }, (_, i) => ({ name: `Region ${String(i + 1)}` })),
|
|
113
|
+
);
|
|
114
|
+
await insertMany(
|
|
115
|
+
db,
|
|
116
|
+
"bench_city",
|
|
117
|
+
Array.from({ length: SCALE.cities }, (_, i) => ({
|
|
118
|
+
region_id: (i % SCALE.regions) + 1,
|
|
119
|
+
name: `${NAMES[i % NAMES.length]} ${String(i + 1)}`,
|
|
120
|
+
})),
|
|
121
|
+
);
|
|
122
|
+
|
|
123
|
+
step("customers");
|
|
124
|
+
await insertMany(
|
|
125
|
+
db,
|
|
126
|
+
"bench_customer",
|
|
127
|
+
Array.from({ length: SCALE.customers }, (_, i) => ({
|
|
128
|
+
city_id: (i % SCALE.cities) + 1,
|
|
129
|
+
code: `C${String(i + 1).padStart(6, "0")}`,
|
|
130
|
+
name: `Customer ${String(i + 1)}`,
|
|
131
|
+
// Long enough that a LIKE scan over 5k rows is real work, and varied so it matches sparsely.
|
|
132
|
+
notes: `route ${String(pseudo(i, 40))} sector ${String(pseudo(i + 7, 12))} ${NAMES[pseudo(i, NAMES.length)]} follow-up pending review`,
|
|
133
|
+
credit_cents: pseudo(i, 500_000),
|
|
134
|
+
created_at: at,
|
|
135
|
+
})),
|
|
136
|
+
);
|
|
137
|
+
|
|
138
|
+
step("catalogue");
|
|
139
|
+
await insertMany(
|
|
140
|
+
db,
|
|
141
|
+
"bench_category",
|
|
142
|
+
Array.from({ length: SCALE.categories }, (_, i) => ({ name: `Category ${String(i + 1)}` })),
|
|
143
|
+
);
|
|
144
|
+
await insertMany(
|
|
145
|
+
db,
|
|
146
|
+
"bench_product",
|
|
147
|
+
Array.from({ length: SCALE.products }, (_, i) => ({
|
|
148
|
+
category_id: (i % SCALE.categories) + 1,
|
|
149
|
+
sku: `SKU${String(i + 1).padStart(6, "0")}`,
|
|
150
|
+
name: `Product ${String(i + 1)}`,
|
|
151
|
+
price_cents: 500 + pseudo(i, 200_000),
|
|
152
|
+
})),
|
|
153
|
+
);
|
|
154
|
+
|
|
155
|
+
step("warehouses and stock");
|
|
156
|
+
await insertMany(
|
|
157
|
+
db,
|
|
158
|
+
"bench_warehouse",
|
|
159
|
+
Array.from({ length: SCALE.warehouses }, (_, i) => ({ name: `Warehouse ${String(i + 1)}` })),
|
|
160
|
+
);
|
|
161
|
+
await insertMany(
|
|
162
|
+
db,
|
|
163
|
+
"bench_stock",
|
|
164
|
+
Array.from({ length: SCALE.stock }, (_, i) => ({
|
|
165
|
+
warehouse_id: (i % SCALE.warehouses) + 1,
|
|
166
|
+
product_id: (i % SCALE.products) + 1,
|
|
167
|
+
quantity: pseudo(i, 900),
|
|
168
|
+
})),
|
|
169
|
+
);
|
|
170
|
+
|
|
171
|
+
step("orders");
|
|
172
|
+
await insertMany(
|
|
173
|
+
db,
|
|
174
|
+
"bench_order",
|
|
175
|
+
Array.from({ length: SCALE.orders }, (_, i) => ({
|
|
176
|
+
customer_id: (i % SCALE.customers) + 1,
|
|
177
|
+
reference: `SO-${String(i + 1).padStart(7, "0")}`,
|
|
178
|
+
status: STATUSES[pseudo(i, STATUSES.length)]!,
|
|
179
|
+
created_at: at,
|
|
180
|
+
total_cents: pseudo(i, 400_000),
|
|
181
|
+
})),
|
|
182
|
+
);
|
|
183
|
+
|
|
184
|
+
step("order lines");
|
|
185
|
+
await insertMany(
|
|
186
|
+
db,
|
|
187
|
+
"bench_order_line",
|
|
188
|
+
Array.from({ length: SCALE.orderLines }, (_, i) => ({
|
|
189
|
+
order_id: (i % SCALE.orders) + 1,
|
|
190
|
+
product_id: pseudo(i, SCALE.products) + 1,
|
|
191
|
+
quantity: 1 + pseudo(i, 12),
|
|
192
|
+
unit_price_cents: 500 + pseudo(i + 3, 200_000),
|
|
193
|
+
})),
|
|
194
|
+
);
|
|
195
|
+
|
|
196
|
+
step("payments");
|
|
197
|
+
await insertMany(
|
|
198
|
+
db,
|
|
199
|
+
"bench_payment",
|
|
200
|
+
Array.from({ length: SCALE.payments }, (_, i) => ({
|
|
201
|
+
order_id: (i % SCALE.orders) + 1,
|
|
202
|
+
amount_cents: pseudo(i, 300_000),
|
|
203
|
+
method: METHODS[pseudo(i, METHODS.length)]!,
|
|
204
|
+
created_at: at,
|
|
205
|
+
})),
|
|
206
|
+
);
|
|
207
|
+
|
|
208
|
+
return { seeded: true, rows: await datasetRowCount(db) };
|
|
209
|
+
}
|