payload-plugin-newsletter 0.4.5 → 0.6.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/CHANGELOG.md CHANGED
@@ -1,6 +1,8 @@
1
- ## [0.4.5] - 2025-06-19
1
+ ## [0.6.0] - 2025-06-20
2
2
 
3
- - fix: add tsup build system for proper ESM/CJS dual package support
3
+ - fix: resolve ESLint error for unused variable in test mock
4
+ - fix: update tests to support newsletter settings as global
5
+ - feat: convert newsletter settings from collection to global
4
6
 
5
7
 
6
8
  All notable changes to this project will be documented in this file.
@@ -8,6 +10,28 @@ All notable changes to this project will be documented in this file.
8
10
  The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
9
11
  and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
10
12
 
13
+ ## [0.5.0] - 2025-06-20
14
+
15
+ ### Changed
16
+ - **BREAKING**: Changed newsletter settings from a collection back to a global configuration
17
+ - Settings are now accessed as a single global config instead of multiple documents
18
+ - Removed the "name" and "active" fields as they're no longer needed for globals
19
+ - Settings now appear as a single page in the admin UI instead of a list view
20
+ - Updated all code to use `payload.findGlobal()` instead of `payload.find()`
21
+
22
+ ### Migration Required
23
+ - Users with existing newsletter-settings collections will need to manually copy their active configuration to the new global settings
24
+ - After migration, the old newsletter-settings collection can be removed from the database
25
+
26
+ ### Fixed
27
+ - Resolved user confusion around having multiple settings documents when only one could be active
28
+ - Settings now follow the standard Payload pattern for configuration globals
29
+
30
+ ## [0.4.5] - 2025-06-19
31
+
32
+ ### Fixed
33
+ - Added tsup build system for proper ESM/CJS dual package support
34
+
11
35
  ## [0.4.4] - 2025-06-16
12
36
 
13
37
  ### Fixed
@@ -0,0 +1,74 @@
1
+ # ESM/CJS Module Resolution Fix Summary
2
+
3
+ ## Changes Made
4
+
5
+ ### 1. **Added tsup Build Tool**
6
+ - Added `tsup` v8.3.5 to devDependencies for proper ESM/CJS dual package support
7
+ - Created `tsup.config.ts` with configuration for building both ESM and CJS outputs
8
+
9
+ ### 2. **Updated package.json**
10
+ - Changed entry points from source files (`./src/`) to built files (`./dist/`)
11
+ - Added proper exports configuration with both ESM and CJS support:
12
+ - ESM files: `.js` extension with `.d.ts` types
13
+ - CJS files: `.cjs` extension with `.d.cts` types
14
+ - Updated build scripts to use tsup
15
+ - Added `module` field pointing to ESM entry
16
+
17
+ ### 3. **Updated tsconfig.json**
18
+ - Changed `moduleResolution` from "bundler" to "node" for better compatibility
19
+
20
+ ### 4. **Created Build Script**
21
+ - Added `build-and-commit.sh` for easy building and verification
22
+
23
+ ## File Structure After Build
24
+
25
+ ```
26
+ dist/
27
+ ├── index.js # ESM main entry
28
+ ├── index.cjs # CJS main entry
29
+ ├── index.d.ts # TypeScript definitions
30
+ ├── index.d.cts # CJS TypeScript definitions
31
+ ├── client.js # ESM client export
32
+ ├── client.cjs # CJS client export
33
+ ├── client.d.ts # Client TypeScript definitions
34
+ ├── client.d.cts # CJS Client TypeScript definitions
35
+ ├── types.js # ESM types export
36
+ ├── types.cjs # CJS types export
37
+ ├── types.d.ts # Types TypeScript definitions
38
+ ├── types.d.cts # CJS Types TypeScript definitions
39
+ ├── components.js # ESM components export
40
+ ├── components.cjs # CJS components export
41
+ ├── components.d.ts # Components TypeScript definitions
42
+ └── components.d.cts # CJS Components TypeScript definitions
43
+ ```
44
+
45
+ ## How to Build and Publish
46
+
47
+ 1. **Install dependencies**: `bun install`
48
+ 2. **Build the package**: `bun run build`
49
+ 3. **Test locally**: Link the package to test in your project
50
+ 4. **Publish**: `npm publish` (dist files will be included automatically)
51
+
52
+ ## Benefits
53
+
54
+ 1. **Proper ESM Support**: Next.js apps using `"type": "module"` can now import the package without issues
55
+ 2. **CJS Compatibility**: Still works with CommonJS projects
56
+ 3. **TypeScript Support**: Proper type definitions for both module systems
57
+ 4. **Clean Exports**: Clear separation of server/client code with proper exports
58
+ 5. **Future Proof**: Ready for the ESM-first ecosystem
59
+
60
+ ## Testing the Fix
61
+
62
+ To test in your ContentQuant project:
63
+ 1. Build the plugin: `bun run build`
64
+ 2. Link locally: `npm link` in plugin directory
65
+ 3. Link in project: `npm link payload-plugin-newsletter` in ContentQuant
66
+ 4. Import and use normally
67
+
68
+ ## Next Steps
69
+
70
+ 1. Run `./build-and-commit.sh` to build the package
71
+ 2. Test the built package locally
72
+ 3. Commit changes with message: "fix: add tsup build system for proper ESM/CJS dual package support"
73
+ 4. Push to repository
74
+ 5. Publish new version to npm
package/dist/index.cjs CHANGED
@@ -357,40 +357,17 @@ var createSubscribersCollection = (pluginConfig) => {
357
357
  return subscribersCollection;
358
358
  };
359
359
 
360
- // src/collections/NewsletterSettings.ts
361
- var createNewsletterSettingsCollection = (pluginConfig) => {
360
+ // src/globals/NewsletterSettings.ts
361
+ var createNewsletterSettingsGlobal = (pluginConfig) => {
362
362
  const slug = pluginConfig.settingsSlug || "newsletter-settings";
363
363
  return {
364
364
  slug,
365
- labels: {
366
- singular: "Newsletter Setting",
367
- plural: "Newsletter Settings"
368
- },
365
+ label: "Newsletter Settings",
369
366
  admin: {
370
- useAsTitle: "name",
371
- defaultColumns: ["name", "provider", "active", "updatedAt"],
372
367
  group: "Newsletter",
373
368
  description: "Configure email provider settings and templates"
374
369
  },
375
370
  fields: [
376
- {
377
- name: "name",
378
- type: "text",
379
- label: "Configuration Name",
380
- required: true,
381
- admin: {
382
- description: 'A descriptive name for this configuration (e.g., "Production", "Development", "Marketing Emails")'
383
- }
384
- },
385
- {
386
- name: "active",
387
- type: "checkbox",
388
- label: "Active",
389
- defaultValue: false,
390
- admin: {
391
- description: "Only one configuration can be active at a time"
392
- }
393
- },
394
371
  {
395
372
  type: "tabs",
396
373
  tabs: [
@@ -650,53 +627,16 @@ var createNewsletterSettingsCollection = (pluginConfig) => {
650
627
  ],
651
628
  hooks: {
652
629
  beforeChange: [
653
- async ({ data, req, operation }) => {
630
+ async ({ data, req }) => {
654
631
  if (!req.user || req.user.collection !== "users") {
655
632
  throw new Error("Only administrators can modify newsletter settings");
656
633
  }
657
- if (data?.active && operation !== "create") {
658
- await req.payload.update({
659
- collection: slug,
660
- where: {
661
- id: {
662
- not_equals: data.id
663
- }
664
- },
665
- data: {
666
- active: false
667
- }
668
- // Keep overrideAccess: true for admin operations after verification
669
- });
670
- }
671
- if (operation === "create" && data?.active) {
672
- const existingActive = await req.payload.find({
673
- collection: slug,
674
- where: {
675
- active: {
676
- equals: true
677
- }
678
- }
679
- // Keep overrideAccess: true for admin operations
680
- });
681
- if (existingActive.docs.length > 0) {
682
- for (const doc of existingActive.docs) {
683
- await req.payload.update({
684
- collection: slug,
685
- id: doc.id,
686
- data: {
687
- active: false
688
- }
689
- // Keep overrideAccess: true for admin operations
690
- });
691
- }
692
- }
693
- }
694
634
  return data;
695
635
  }
696
636
  ],
697
637
  afterChange: [
698
638
  async ({ doc, req }) => {
699
- if (req.payload.newsletterEmailService && doc.active) {
639
+ if (req.payload.newsletterEmailService) {
700
640
  try {
701
641
  console.warn("Newsletter settings updated, reinitializing service...");
702
642
  } catch {
@@ -709,11 +649,8 @@ var createNewsletterSettingsCollection = (pluginConfig) => {
709
649
  access: {
710
650
  read: () => true,
711
651
  // Settings can be read publicly for validation
712
- create: adminOnly(pluginConfig),
713
- update: adminOnly(pluginConfig),
714
- delete: adminOnly(pluginConfig)
715
- },
716
- timestamps: true
652
+ update: adminOnly(pluginConfig)
653
+ }
717
654
  };
718
655
  };
719
656
 
@@ -1193,18 +1130,11 @@ var createSubscribeEndpoint = (config) => {
1193
1130
  errors: validation.errors
1194
1131
  });
1195
1132
  }
1196
- const settingsResult = await req.payload.find({
1197
- collection: config.settingsSlug || "newsletter-settings",
1198
- where: {
1199
- active: {
1200
- equals: true
1201
- }
1202
- },
1203
- limit: 1,
1133
+ const settings = await req.payload.findGlobal({
1134
+ slug: config.settingsSlug || "newsletter-settings",
1204
1135
  overrideAccess: false
1205
1136
  // No user context for public endpoint
1206
1137
  });
1207
- const settings = settingsResult.docs[0];
1208
1138
  const allowedDomains = settings?.subscriptionSettings?.allowedDomains?.map((d) => d.domain) || [];
1209
1139
  if (!isDomainAllowed(trimmedEmail, allowedDomains)) {
1210
1140
  return res.status(400).json({
@@ -1909,8 +1839,8 @@ var newsletterPlugin = (pluginConfig) => (incomingConfig) => {
1909
1839
  return incomingConfig;
1910
1840
  }
1911
1841
  const subscribersCollection = createSubscribersCollection(config);
1912
- const settingsCollection = createNewsletterSettingsCollection(config);
1913
- let collections = [...incomingConfig.collections || [], subscribersCollection, settingsCollection];
1842
+ const settingsGlobal = createNewsletterSettingsGlobal(config);
1843
+ let collections = [...incomingConfig.collections || [], subscribersCollection];
1914
1844
  if (config.features?.newsletterScheduling?.enabled) {
1915
1845
  const targetCollections = config.features.newsletterScheduling.collections || "articles";
1916
1846
  const collectionsToExtend = Array.isArray(targetCollections) ? targetCollections : [targetCollections];
@@ -1933,7 +1863,8 @@ var newsletterPlugin = (pluginConfig) => (incomingConfig) => {
1933
1863
  ...incomingConfig,
1934
1864
  collections,
1935
1865
  globals: [
1936
- ...incomingConfig.globals || []
1866
+ ...incomingConfig.globals || [],
1867
+ settingsGlobal
1937
1868
  ],
1938
1869
  endpoints: [
1939
1870
  ...incomingConfig.endpoints || [],
@@ -1941,16 +1872,9 @@ var newsletterPlugin = (pluginConfig) => (incomingConfig) => {
1941
1872
  ],
1942
1873
  onInit: async (payload) => {
1943
1874
  try {
1944
- const settingsResult = await payload.find({
1945
- collection: config.settingsSlug || "newsletter-settings",
1946
- where: {
1947
- active: {
1948
- equals: true
1949
- }
1950
- },
1951
- limit: 1
1875
+ const settings = await payload.findGlobal({
1876
+ slug: config.settingsSlug || "newsletter-settings"
1952
1877
  });
1953
- const settings = settingsResult.docs[0];
1954
1878
  let emailServiceConfig;
1955
1879
  if (settings) {
1956
1880
  emailServiceConfig = {