@antelopejs/dms-mailing 0.7.0 → 0.8.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.
Files changed (219) hide show
  1. package/README.md +28 -10
  2. package/dist/constants.d.ts +0 -2
  3. package/dist/constants.js +1 -3
  4. package/dist/constants.js.map +1 -1
  5. package/dist/crons/jobs.d.ts +1 -1
  6. package/dist/data/body.js +2 -1
  7. package/dist/data/body.js.map +1 -1
  8. package/dist/data/templates-table.js +5 -11
  9. package/dist/data/templates-table.js.map +1 -1
  10. package/dist/db/models/index.d.ts +0 -1
  11. package/dist/db/models/index.js +0 -1
  12. package/dist/db/models/index.js.map +1 -1
  13. package/dist/db/models/send-events.model.js +2 -3
  14. package/dist/db/models/send-events.model.js.map +1 -1
  15. package/dist/db/models/sends.model.js +2 -3
  16. package/dist/db/models/sends.model.js.map +1 -1
  17. package/dist/db/models/template-versions.model.js.map +1 -1
  18. package/dist/db/models/templates.model.js +4 -10
  19. package/dist/db/models/templates.model.js.map +1 -1
  20. package/dist/db/tables/index.d.ts +0 -1
  21. package/dist/db/tables/index.js +0 -1
  22. package/dist/db/tables/index.js.map +1 -1
  23. package/dist/db/tables/settings.table.d.ts +0 -1
  24. package/dist/db/tables/settings.table.js +0 -4
  25. package/dist/db/tables/settings.table.js.map +1 -1
  26. package/dist/db/tables/templates.table.d.ts +0 -3
  27. package/dist/db/tables/templates.table.js +1 -13
  28. package/dist/db/tables/templates.table.js.map +1 -1
  29. package/dist/engine/changes.js +2 -1
  30. package/dist/engine/changes.js.map +1 -1
  31. package/dist/engine/conditions.js +2 -3
  32. package/dist/engine/conditions.js.map +1 -1
  33. package/dist/engine/fallback-html.js +8 -8
  34. package/dist/engine/fallback-html.js.map +1 -1
  35. package/dist/engine/formats.js +6 -6
  36. package/dist/engine/formats.js.map +1 -1
  37. package/dist/engine/paths.js +2 -3
  38. package/dist/engine/paths.js.map +1 -1
  39. package/dist/engine/system-variables.js +1 -1
  40. package/dist/engine/system-variables.js.map +1 -1
  41. package/dist/engine/tokens.js.map +1 -1
  42. package/dist/hooks/index.d.ts +0 -1
  43. package/dist/hooks/index.js +0 -1
  44. package/dist/hooks/index.js.map +1 -1
  45. package/dist/implementations/dms-mailing/index.d.ts +3 -4
  46. package/dist/implementations/dms-mailing/index.js +8 -9
  47. package/dist/implementations/dms-mailing/index.js.map +1 -1
  48. package/dist/index.js +0 -1
  49. package/dist/index.js.map +1 -1
  50. package/dist/pages/sends.js.map +1 -1
  51. package/dist/pages/settings/form.js +8 -0
  52. package/dist/pages/settings/form.js.map +1 -1
  53. package/dist/pages/toolbar.js.map +1 -1
  54. package/dist/routes/events.js +2 -2
  55. package/dist/routes/events.js.map +1 -1
  56. package/dist/routes/metrics.js +6 -5
  57. package/dist/routes/metrics.js.map +1 -1
  58. package/dist/routes/sends.js +1 -1
  59. package/dist/routes/sends.js.map +1 -1
  60. package/dist/routes/settings.js +6 -6
  61. package/dist/routes/settings.js.map +1 -1
  62. package/dist/routes/templates.js +6 -10
  63. package/dist/routes/templates.js.map +1 -1
  64. package/dist/services/attention.js +2 -1
  65. package/dist/services/attention.js.map +1 -1
  66. package/dist/services/categories.js +6 -6
  67. package/dist/services/categories.js.map +1 -1
  68. package/dist/services/checked-send.js +16 -9
  69. package/dist/services/checked-send.js.map +1 -1
  70. package/dist/services/declarations.js +42 -184
  71. package/dist/services/declarations.js.map +1 -1
  72. package/dist/services/events.js +11 -7
  73. package/dist/services/events.js.map +1 -1
  74. package/dist/services/localized-text.d.ts +2 -1
  75. package/dist/services/localized-text.js +2 -1
  76. package/dist/services/localized-text.js.map +1 -1
  77. package/dist/services/metrics.js.map +1 -1
  78. package/dist/services/render.js.map +1 -1
  79. package/dist/services/send-import.js +7 -5
  80. package/dist/services/send-import.js.map +1 -1
  81. package/dist/services/send.js +4 -3
  82. package/dist/services/send.js.map +1 -1
  83. package/dist/services/settings.d.ts +1 -1
  84. package/dist/services/settings.js +1 -5
  85. package/dist/services/settings.js.map +1 -1
  86. package/dist/services/starters.js +5 -5
  87. package/dist/services/starters.js.map +1 -1
  88. package/dist/services/template-stats.js +5 -2
  89. package/dist/services/template-stats.js.map +1 -1
  90. package/dist/services/templates.d.ts +2 -2
  91. package/dist/services/templates.js +54 -29
  92. package/dist/services/templates.js.map +1 -1
  93. package/dist/types/settings.d.ts +2 -0
  94. package/dist/types/settings.js +8 -1
  95. package/dist/types/settings.js.map +1 -1
  96. package/dist/validation/declarations.schema.d.ts +16 -16
  97. package/dist/validation/declarations.schema.js +2 -2
  98. package/dist/validation/declarations.schema.js.map +1 -1
  99. package/dist/validation/guards.d.ts +4 -0
  100. package/dist/validation/guards.js +19 -0
  101. package/dist/validation/guards.js.map +1 -0
  102. package/dist/validation/send-event-type.schema.d.ts +2 -0
  103. package/dist/validation/send-event-type.schema.js +11 -0
  104. package/dist/validation/send-event-type.schema.js.map +1 -0
  105. package/dist/validation/settings.schema.d.ts +16 -16
  106. package/dist/validation/settings.schema.js +1 -1
  107. package/dist/validation/settings.schema.js.map +1 -1
  108. package/dist/validation/templates.schema.d.ts +19 -18
  109. package/dist/validation/templates.schema.js.map +1 -1
  110. package/frontend-vue/app/build/components/TemplateDrawerFooter.vue +45 -0
  111. package/frontend-vue/app/build/components/TemplateDrawerPerformance.vue +102 -0
  112. package/frontend-vue/app/build/components/TemplateDrawerVariables.vue +110 -0
  113. package/frontend-vue/app/build/composables/useDrawerStats.ts +78 -0
  114. package/frontend-vue/app/components/DuplicateModal.vue +3 -11
  115. package/frontend-vue/app/components/FixAddressModal.vue +2 -1
  116. package/frontend-vue/app/components/NewTemplateModal.vue +3 -11
  117. package/frontend-vue/app/components/RealSendModal.vue +6 -17
  118. package/frontend-vue/app/components/RenderingModal.vue +2 -1
  119. package/frontend-vue/app/components/SendDrawer.vue +5 -4
  120. package/frontend-vue/app/components/StarterGallery.vue +3 -11
  121. package/frontend-vue/app/components/TemplateDrawer.vue +40 -269
  122. package/frontend-vue/app/components/TestSendModal.vue +7 -18
  123. package/frontend-vue/app/components/VersionHistory.vue +2 -7
  124. package/frontend-vue/app/components/WebhookStatus.vue +2 -1
  125. package/frontend-vue/app/components/editor/EditorWorkspace.vue +2 -7
  126. package/frontend-vue/build/backend-boundary.ts +122 -0
  127. package/frontend-vue/dms.frontend.build.ts +7 -0
  128. package/frontend-vue/eslint.config.mjs +13 -0
  129. package/frontend-vue/package.json +4 -2
  130. package/frontend-vue/pnpm-lock.yaml +210 -61
  131. package/frontend-vue/tests/backend-boundary.test.ts +203 -0
  132. package/frontend-vue/tests/dnd.test.ts +1 -2
  133. package/frontend-vue/tests/editor-block-list.test.ts +136 -53
  134. package/frontend-vue/tests/helpers/auth-fetch.ts +123 -0
  135. package/frontend-vue/tests/helpers/nuxt-globals.ts +17 -1
  136. package/frontend-vue/tests/new-template-modal.test.ts +41 -6
  137. package/frontend-vue/tests/page-reads.test.ts +26 -6
  138. package/frontend-vue/tests/send-actions.test.ts +0 -1
  139. package/frontend-vue/tests/send-drawer.test.ts +2 -6
  140. package/frontend-vue/tests/send-modals.test.ts +8 -5
  141. package/frontend-vue/tests/sortable-list.test.ts +54 -62
  142. package/frontend-vue/tests/suppression.test.ts +1 -2
  143. package/frontend-vue/tests/template-drawer.test.ts +27 -18
  144. package/frontend-vue/tests/template-gallery.test.ts +7 -5
  145. package/frontend-vue/tests/template-preview-frame.test.ts +2 -5
  146. package/package.json +8 -13
  147. package/skills/dms-mailing/SKILL.md +11 -17
  148. package/skills/dms-mailing/cases.json +49 -0
  149. package/src/constants.ts +0 -2
  150. package/src/crons/jobs.ts +1 -1
  151. package/src/data/body.ts +2 -1
  152. package/src/data/templates-table.ts +15 -22
  153. package/src/db/models/index.ts +0 -1
  154. package/src/db/models/send-events.model.ts +2 -2
  155. package/src/db/models/sends.model.ts +7 -8
  156. package/src/db/models/template-versions.model.ts +5 -1
  157. package/src/db/models/templates.model.ts +9 -16
  158. package/src/db/tables/index.ts +0 -1
  159. package/src/db/tables/settings.table.ts +0 -8
  160. package/src/db/tables/templates.table.ts +2 -16
  161. package/src/engine/changes.ts +3 -2
  162. package/src/engine/conditions.ts +2 -4
  163. package/src/engine/fallback-html.ts +13 -13
  164. package/src/engine/formats.ts +6 -6
  165. package/src/engine/paths.ts +4 -3
  166. package/src/engine/system-variables.ts +4 -3
  167. package/src/engine/tokens.ts +1 -2
  168. package/src/hooks/index.ts +0 -1
  169. package/src/implementations/dms-mailing/index.ts +5 -18
  170. package/src/index.ts +1 -6
  171. package/src/pages/sends.ts +5 -3
  172. package/src/pages/settings/form.ts +16 -0
  173. package/src/pages/templates.ts +1 -1
  174. package/src/pages/toolbar.ts +4 -2
  175. package/src/routes/events.ts +3 -6
  176. package/src/routes/metrics.ts +7 -5
  177. package/src/routes/sends.ts +10 -18
  178. package/src/routes/settings.ts +8 -9
  179. package/src/routes/suppressions.ts +1 -1
  180. package/src/routes/templates.ts +16 -18
  181. package/src/services/attention.ts +4 -3
  182. package/src/services/categories.ts +6 -6
  183. package/src/services/checked-send.ts +17 -19
  184. package/src/services/declarations.ts +62 -318
  185. package/src/services/events.ts +16 -13
  186. package/src/services/localized-text.ts +4 -2
  187. package/src/services/metrics.ts +2 -2
  188. package/src/services/notify.ts +1 -1
  189. package/src/services/render.ts +5 -1
  190. package/src/services/send-import.ts +18 -13
  191. package/src/services/send.ts +7 -7
  192. package/src/services/settings.ts +3 -10
  193. package/src/services/starters.ts +6 -6
  194. package/src/services/template-stats.ts +11 -4
  195. package/src/services/templates.ts +69 -52
  196. package/src/types/settings.ts +20 -0
  197. package/src/validation/declarations.schema.ts +2 -2
  198. package/src/validation/guards.ts +25 -0
  199. package/src/validation/send-event-type.schema.ts +10 -0
  200. package/src/validation/settings.schema.ts +7 -2
  201. package/src/validation/templates.schema.ts +2 -1
  202. package/dist/db/models/template-slugs.model.d.ts +0 -27
  203. package/dist/db/models/template-slugs.model.js +0 -43
  204. package/dist/db/models/template-slugs.model.js.map +0 -1
  205. package/dist/db/tables/template-slugs.table.d.ts +0 -7
  206. package/dist/db/tables/template-slugs.table.js +0 -35
  207. package/dist/db/tables/template-slugs.table.js.map +0 -1
  208. package/dist/hooks/database-ready.d.ts +0 -7
  209. package/dist/hooks/database-ready.js +0 -26
  210. package/dist/hooks/database-ready.js.map +0 -1
  211. package/dist/services/fingerprint.d.ts +0 -1
  212. package/dist/services/fingerprint.js +0 -20
  213. package/dist/services/fingerprint.js.map +0 -1
  214. package/frontend-vue/tests/i18n-editor.test.ts +0 -50
  215. package/frontend-vue/tests/i18n.test.ts +0 -138
  216. package/src/db/models/template-slugs.model.ts +0 -61
  217. package/src/db/tables/template-slugs.table.ts +0 -29
  218. package/src/hooks/database-ready.ts +0 -47
  219. package/src/services/fingerprint.ts +0 -22
@@ -0,0 +1,122 @@
1
+ import { existsSync, readFileSync, realpathSync } from 'node:fs'
2
+ import { dirname, isAbsolute, join, relative, sep } from 'node:path'
3
+ import type { DmsVitePluginEntry } from '#dms/frontend-build'
4
+
5
+ type VitePlugin = Extract<DmsVitePluginEntry, { name: string }>
6
+
7
+ const BACKEND_PACKAGE = '@antelopejs/dms-mailing'
8
+ const BACKEND_SOURCE = 'src'
9
+ const QUERY_OR_HASH = /[?#].*$/
10
+
11
+ const backendRoots = new Map<string, string | null>()
12
+
13
+ /** Whether a parsed manifest names its package. */
14
+ function isNamedManifest(value: unknown): value is { name: string } {
15
+ return (
16
+ typeof value === 'object' &&
17
+ value !== null &&
18
+ 'name' in value &&
19
+ typeof value.name === 'string'
20
+ )
21
+ }
22
+
23
+ /** The package name a `package.json` declares, or `undefined`. */
24
+ function packageName(manifest: string): string | undefined {
25
+ try {
26
+ const parsed: unknown = JSON.parse(readFileSync(manifest, 'utf8'))
27
+ return isNamedManifest(parsed) ? parsed.name : undefined
28
+ } catch {
29
+ return undefined
30
+ }
31
+ }
32
+
33
+ /** The directory of the backend package that holds `directory`, or null. */
34
+ function backendRoot(directory: string): string | null {
35
+ const known = backendRoots.get(directory)
36
+ if (known !== undefined) {
37
+ return known
38
+ }
39
+ const manifest = join(directory, 'package.json')
40
+ const parent = dirname(directory)
41
+ let root: string | null = null
42
+ if (existsSync(manifest)) {
43
+ root = packageName(manifest) === BACKEND_PACKAGE ? directory : null
44
+ } else if (parent !== directory) {
45
+ root = backendRoot(parent)
46
+ }
47
+ backendRoots.set(directory, root)
48
+ return root
49
+ }
50
+
51
+ /**
52
+ * The real path of a resolved module id when it lies under the `src`
53
+ * directory of the backend package, or `undefined`. The package that owns the
54
+ * file decides, not a path, so the answer is the same in the repository and in
55
+ * the build workspace. Virtual ids and ids that are not files are ignored.
56
+ */
57
+ function backendSourceFile(id: string): string | undefined {
58
+ const path = id.replace(QUERY_OR_HASH, '')
59
+ if (!isAbsolute(path)) {
60
+ return undefined
61
+ }
62
+ let real: string
63
+ try {
64
+ real = realpathSync(path)
65
+ } catch {
66
+ return undefined
67
+ }
68
+ const root = backendRoot(dirname(real))
69
+ if (root === null) {
70
+ return undefined
71
+ }
72
+ return relative(root, real).split(sep)[0] === BACKEND_SOURCE
73
+ ? real
74
+ : undefined
75
+ }
76
+
77
+ /**
78
+ * Fails the build and the dev server when a module of the frontend resolves to
79
+ * a file under the `src` of the backend package: the browser reaches the
80
+ * backend only through its HTTP interface. It checks what the whole resolution
81
+ * chain returns, an id marked external included, so an alias is seen through
82
+ * and a symlink the resolver returns is followed to its real path, and it runs
83
+ * before the other plugins (`enforce: "pre"`). Vite builds workers with their
84
+ * own plugin list, so the plugin adds itself there too.
85
+ *
86
+ * antelopejs-sync writes this file from `@antelopejs/tooling-configs` and
87
+ * restores it on every run: change the plugin in the pack, not here.
88
+ */
89
+ export function backendBoundary(): VitePlugin {
90
+ return {
91
+ ...boundaryCheck(),
92
+ config: () => ({ worker: { plugins: () => [boundaryCheck()] } }),
93
+ }
94
+ }
95
+
96
+ /** The check alone, as a worker build runs it. */
97
+ function boundaryCheck(): VitePlugin {
98
+ return {
99
+ name: `${BACKEND_PACKAGE}:backend-boundary`,
100
+ enforce: 'pre',
101
+ async resolveId(source, importer, options) {
102
+ const resolved = await this.resolve(source, importer, {
103
+ ...options,
104
+ skipSelf: true,
105
+ })
106
+ if (resolved === null) {
107
+ return resolved
108
+ }
109
+ const file = backendSourceFile(resolved.id)
110
+ if (file === undefined) {
111
+ return resolved
112
+ }
113
+ const from =
114
+ importer === undefined
115
+ ? 'an entry point'
116
+ : importer.replace(QUERY_OR_HASH, '')
117
+ return this.error(
118
+ `Backend boundary: ${from} imports ${file}, which is under the src of ${BACKEND_PACKAGE}. The frontend reaches the backend only through its HTTP interface.`,
119
+ )
120
+ },
121
+ }
122
+ }
@@ -0,0 +1,7 @@
1
+ import { defineDmsFrontendBuild } from '#dms/frontend-build'
2
+ import { backendBoundary } from './build/backend-boundary.ts'
3
+
4
+ /** The build of the frontend module: the backend boundary in every build. */
5
+ export default defineDmsFrontendBuild((build) => {
6
+ build.registerVitePlugins(() => [backendBoundary()])
7
+ })
@@ -1,3 +1,5 @@
1
+ import antiSlop from '@antelopejs/tooling-configs/oxc/anti-slop'
2
+ import guardrails from '@antelopejs/tooling-configs/oxc/guardrails'
1
3
  import vue from 'eslint-plugin-vue'
2
4
  import ts from 'typescript-eslint'
3
5
 
@@ -10,4 +12,15 @@ export default [
10
12
  rules: { 'vue/multi-word-component-names': 'off' },
11
13
  },
12
14
  { files: ['**/*.ts'], languageOptions: { parser: ts.parser } },
15
+ {
16
+ files: ['tests/**/*.ts'],
17
+ plugins: { antelopejs: guardrails, 'anti-slop': antiSlop },
18
+ rules: {
19
+ 'antelopejs/no-fs-read-in-tests': 'error',
20
+ 'antelopejs/no-constant-value-assertion': 'error',
21
+ 'antelopejs/no-typeof-function-only-test': 'error',
22
+ 'antelopejs/no-self-import-in-tests': 'error',
23
+ 'anti-slop/no-module-mocking': 'error',
24
+ },
25
+ },
13
26
  ]
@@ -6,11 +6,11 @@
6
6
  "license": "Apache-2.0",
7
7
  "packageManager": "pnpm@10.2.0",
8
8
  "engines": {
9
- "@antelopejs/dms-frontend": ">=0.8.0 <0.9.0"
9
+ "@antelopejs/dms-frontend": ">=0.9.1 <0.10.0"
10
10
  },
11
11
  "scripts": {
12
12
  "format": "prettier --write .",
13
- "lint": "eslint .",
13
+ "lint": "eslint . && node --input-type=module -e \"import { assertApiErrorPresentation } from '@antelopejs/dms/checks/api-error-presentation'; assertApiErrorPresentation(['app']);\"",
14
14
  "lint:fix": "eslint . --fix",
15
15
  "test": "vitest run"
16
16
  },
@@ -21,12 +21,14 @@
21
21
  "vue": "^3.5.18"
22
22
  },
23
23
  "devDependencies": {
24
+ "@antelopejs/tooling-configs": "^0.2.12",
24
25
  "@nuxt/ui": "4.10.0",
25
26
  "@vitejs/plugin-vue": "^6.0.0",
26
27
  "@vitest/runner": "^4.1.5",
27
28
  "eslint": "^9.0.0",
28
29
  "eslint-plugin-vue": "^10.0.0",
29
30
  "typescript-eslint": "^8.0.0",
31
+ "vite": "^8.2.2",
30
32
  "jsdom": "^26",
31
33
  "prettier": "^3.5.3",
32
34
  "prettier-plugin-tailwindcss": "^0.6.11",