@actuate-media/cms-core 0.33.0 → 0.35.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/__tests__/cron/cron.test.js +19 -0
- package/dist/__tests__/cron/cron.test.js.map +1 -1
- package/dist/__tests__/forms/encryption.test.d.ts +2 -0
- package/dist/__tests__/forms/encryption.test.d.ts.map +1 -0
- package/dist/__tests__/forms/encryption.test.js +84 -0
- package/dist/__tests__/forms/encryption.test.js.map +1 -0
- package/dist/__tests__/forms/entries-export.test.d.ts +2 -0
- package/dist/__tests__/forms/entries-export.test.d.ts.map +1 -0
- package/dist/__tests__/forms/entries-export.test.js +69 -0
- package/dist/__tests__/forms/entries-export.test.js.map +1 -0
- package/dist/__tests__/seo/index-status.test.d.ts +2 -0
- package/dist/__tests__/seo/index-status.test.d.ts.map +1 -0
- package/dist/__tests__/seo/index-status.test.js +140 -0
- package/dist/__tests__/seo/index-status.test.js.map +1 -0
- package/dist/api/handlers.d.ts.map +1 -1
- package/dist/api/handlers.js +119 -12
- package/dist/api/handlers.js.map +1 -1
- package/dist/cron/index.d.ts +7 -0
- package/dist/cron/index.d.ts.map +1 -1
- package/dist/cron/index.js +15 -0
- package/dist/cron/index.js.map +1 -1
- package/dist/forms/encryption.d.ts +20 -0
- package/dist/forms/encryption.d.ts.map +1 -0
- package/dist/forms/encryption.js +80 -0
- package/dist/forms/encryption.js.map +1 -0
- package/dist/forms/entries.d.ts +12 -0
- package/dist/forms/entries.d.ts.map +1 -1
- package/dist/forms/entries.js +83 -2
- package/dist/forms/entries.js.map +1 -1
- package/dist/forms/index.d.ts +1 -0
- package/dist/forms/index.d.ts.map +1 -1
- package/dist/forms/index.js +1 -0
- package/dist/forms/index.js.map +1 -1
- package/dist/forms/submission.d.ts.map +1 -1
- package/dist/forms/submission.js +7 -2
- package/dist/forms/submission.js.map +1 -1
- package/dist/seo/index-status.d.ts +56 -0
- package/dist/seo/index-status.d.ts.map +1 -0
- package/dist/seo/index-status.js +193 -0
- package/dist/seo/index-status.js.map +1 -0
- package/dist/seo/index.d.ts +2 -0
- package/dist/seo/index.d.ts.map +1 -1
- package/dist/seo/index.js +1 -0
- package/dist/seo/index.js.map +1 -1
- package/package.json +2 -2
|
@@ -70,6 +70,7 @@ describe('processCleanup', () => {
|
|
|
70
70
|
auditLogsDeleted: 0,
|
|
71
71
|
documentsDeleted: 0,
|
|
72
72
|
passwordResetTokensDeleted: 0,
|
|
73
|
+
formSubmissionsDeleted: 0,
|
|
73
74
|
});
|
|
74
75
|
});
|
|
75
76
|
it('deletes expired/revoked sessions older than the retention window', async () => {
|
|
@@ -122,8 +123,26 @@ describe('processCleanup', () => {
|
|
|
122
123
|
auditLogsDeleted: 0,
|
|
123
124
|
documentsDeleted: 0,
|
|
124
125
|
passwordResetTokensDeleted: 0,
|
|
126
|
+
formSubmissionsDeleted: 0,
|
|
125
127
|
});
|
|
126
128
|
});
|
|
129
|
+
it('does not touch form submissions when retention is disabled (0)', async () => {
|
|
130
|
+
const deleteMany = vi.fn().mockResolvedValue({ count: 9 });
|
|
131
|
+
const db = { formSubmission: { deleteMany } };
|
|
132
|
+
const result = await processCleanup(db);
|
|
133
|
+
expect(result.formSubmissionsDeleted).toBe(0);
|
|
134
|
+
expect(deleteMany).not.toHaveBeenCalled();
|
|
135
|
+
});
|
|
136
|
+
it('hard-deletes form submissions older than the configured retention window', async () => {
|
|
137
|
+
const deleteMany = vi.fn().mockResolvedValue({ count: 4 });
|
|
138
|
+
const db = { formSubmission: { deleteMany } };
|
|
139
|
+
const result = await processCleanup(db, {
|
|
140
|
+
formSubmissionRetentionMs: 30 * 24 * 60 * 60 * 1000,
|
|
141
|
+
});
|
|
142
|
+
expect(result.formSubmissionsDeleted).toBe(4);
|
|
143
|
+
const cutoff = deleteMany.mock.calls[0][0].where.submittedAt.lt.getTime();
|
|
144
|
+
expect(cutoff).toBe(now - 30 * 24 * 60 * 60 * 1000);
|
|
145
|
+
});
|
|
127
146
|
});
|
|
128
147
|
describe('processSeoScan', () => {
|
|
129
148
|
it('returns empty result when document model is missing', async () => {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cron.test.js","sourceRoot":"","sources":["../../../src/__tests__/cron/cron.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,EAAE,EAAE,EAAE,UAAU,EAAE,SAAS,EAAE,EAAE,EAAE,MAAM,QAAQ,CAAA;AACxE,OAAO,EAAE,uBAAuB,EAAE,cAAc,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAA;AAE7F,QAAQ,CAAC,WAAW,EAAE,GAAG,EAAE;IACzB,MAAM,cAAc,GAAG,OAAO,CAAC,GAAG,CAAC,WAAW,CAAA;IAE9C,SAAS,CAAC,GAAG,EAAE;QACb,IAAI,cAAc,KAAK,SAAS;YAAE,OAAO,OAAO,CAAC,GAAG,CAAC,WAAW,CAAA;;YAC3D,OAAO,CAAC,GAAG,CAAC,WAAW,GAAG,cAAc,CAAA;IAC/C,CAAC,CAAC,CAAA;IAEF,EAAE,CAAC,iDAAiD,EAAE,GAAG,EAAE;QACzD,OAAO,OAAO,CAAC,GAAG,CAAC,WAAW,CAAA;QAC9B,MAAM,CAAC,uBAAuB,CAAC,iBAAiB,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAA;IAChE,CAAC,CAAC,CAAA;IAEF,EAAE,CAAC,4DAA4D,EAAE,GAAG,EAAE;QACpE,OAAO,CAAC,GAAG,CAAC,WAAW,GAAG,EAAE,CAAA;QAC5B,MAAM,CAAC,uBAAuB,CAAC,iBAAiB,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAA;IAChE,CAAC,CAAC,CAAA;IAEF,EAAE,CAAC,+BAA+B,EAAE,GAAG,EAAE;QACvC,OAAO,CAAC,GAAG,CAAC,WAAW,GAAG,QAAQ,CAAA;QAClC,MAAM,CAAC,uBAAuB,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAA;QACjD,MAAM,CAAC,uBAAuB,CAAC,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAA;IACxD,CAAC,CAAC,CAAA;IAEF,EAAE,CAAC,sBAAsB,EAAE,GAAG,EAAE;QAC9B,OAAO,CAAC,GAAG,CAAC,WAAW,GAAG,gBAAgB,CAAA;QAC1C,MAAM,CAAC,uBAAuB,CAAC,qBAAqB,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAA;IACpE,CAAC,CAAC,CAAA;IAEF,EAAE,CAAC,kEAAkE,EAAE,GAAG,EAAE;QAC1E,OAAO,CAAC,GAAG,CAAC,WAAW,GAAG,0BAA0B,CAAA;QACpD,MAAM,CAAC,uBAAuB,CAAC,iCAAiC,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAA;IAChF,CAAC,CAAC,CAAA;IAEF,EAAE,CAAC,8BAA8B,EAAE,GAAG,EAAE;QACtC,OAAO,CAAC,GAAG,CAAC,WAAW,GAAG,sBAAsB,CAAA;QAChD,MAAM,CAAC,uBAAuB,CAAC,6BAA6B,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;IAC3E,CAAC,CAAC,CAAA;IAEF,EAAE,CAAC,wEAAwE,EAAE,GAAG,EAAE;QAChF,OAAO,CAAC,GAAG,CAAC,WAAW,GAAG,sBAAsB,CAAA;QAChD,MAAM,CAAC,uBAAuB,CAAC,sBAAsB,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;IACpE,CAAC,CAAC,CAAA;IAEF,0EAA0E;IAC1E,sEAAsE;IACtE,mEAAmE;IACnE,uEAAuE;IACvE,SAAS;IACT,EAAE,CAAC,IAAI,CAAC;QACN,CAAC,qBAAqB,EAAE,OAAO,CAAC;QAChC,CAAC,oBAAoB,EAAE,mDAAmD,CAAC;QAC3E,CAAC,OAAO,EAAE,EAAE,CAAC;QACb,CAAC,gBAAgB,EAAE,qBAAqB,CAAC;QACzC,CAAC,eAAe,EAAE,wBAAwB,CAAC;KAC5C,CAAC,CAAC,mDAAmD,EAAE,CAAC,MAAM,EAAE,OAAO,EAAE,EAAE;QAC1E,OAAO,CAAC,GAAG,CAAC,WAAW,GAAG,sBAAsB,CAAA;QAChD,MAAM,CAAC,uBAAuB,CAAC,UAAU,OAAO,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAA;IAClE,CAAC,CAAC,CAAA;AACJ,CAAC,CAAC,CAAA;AAEF,QAAQ,CAAC,gBAAgB,EAAE,GAAG,EAAE;IAC9B,IAAI,GAAW,CAAA;IAEf,UAAU,CAAC,GAAG,EAAE;QACd,GAAG,GAAG,IAAI,CAAC,GAAG,EAAE,CAAA;QAChB,EAAE,CAAC,aAAa,EAAE,CAAA;QAClB,EAAE,CAAC,aAAa,CAAC,GAAG,CAAC,CAAA;IACvB,CAAC,CAAC,CAAA;IAEF,SAAS,CAAC,GAAG,EAAE;QACb,EAAE,CAAC,aAAa,EAAE,CAAA;IACpB,CAAC,CAAC,CAAA;IAEF,EAAE,CAAC,gDAAgD,EAAE,KAAK,IAAI,EAAE;QAC9D,MAAM,MAAM,GAAG,MAAM,cAAc,CAAC,EAAW,CAAC,CAAA;QAChD,MAAM,CAAC,MAAM,CAAC,CAAC,OAAO,CAAC;YACrB,eAAe,EAAE,CAAC;YAClB,gBAAgB,EAAE,CAAC;YACnB,gBAAgB,EAAE,CAAC;YACnB,0BAA0B,EAAE,CAAC;SAC9B,CAAC,CAAA;IACJ,CAAC,CAAC,CAAA;IAEF,EAAE,CAAC,kEAAkE,EAAE,KAAK,IAAI,EAAE;QAChF,MAAM,UAAU,GAAG,EAAE,CAAC,EAAE,EAAE,CAAC,iBAAiB,CAAC,EAAE,KAAK,EAAE,CAAC,EAAE,CAAC,CAAA;QAC1D,MAAM,EAAE,GAAG,EAAE,OAAO,EAAE,EAAE,UAAU,EAAE,EAAE,CAAA;QAEtC,MAAM,MAAM,GAAG,MAAM,cAAc,CAAC,EAAW,EAAE,EAAE,kBAAkB,EAAE,IAAI,EAAE,CAAC,CAAA;QAE9E,MAAM,CAAC,MAAM,CAAC,eAAe,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAA;QACtC,MAAM,CAAC,UAAU,CAAC,CAAC,qBAAqB,CAAC,CAAC,CAAC,CAAA;QAC3C,MAAM,KAAK,GAAG,UAAU,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAE,CAAC,CAAC,CAAC,CAAC,KAAK,CAAA;QAChD,MAAM,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,EAAE,CAAC,OAAO,EAAE,CAAC,CAAC,IAAI,CAAC,GAAG,GAAG,IAAI,CAAC,CAAA;QAC3D,MAAM,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,EAAE,CAAC,OAAO,EAAE,CAAC,CAAC,IAAI,CAAC,GAAG,GAAG,IAAI,CAAC,CAAA;IAC7D,CAAC,CAAC,CAAA;IAEF,EAAE,CAAC,+CAA+C,EAAE,KAAK,IAAI,EAAE;QAC7D,MAAM,EAAE,GAAG;YACT,OAAO,EAAE,EAAE,UAAU,EAAE,EAAE,CAAC,EAAE,EAAE,CAAC,iBAAiB,CAAC,IAAI,KAAK,CAAC,MAAM,CAAC,CAAC,EAAE;YACrE,QAAQ,EAAE,EAAE,UAAU,EAAE,EAAE,CAAC,EAAE,EAAE,CAAC,iBAAiB,CAAC,EAAE,KAAK,EAAE,CAAC,EAAE,CAAC,EAAE;YACjE,QAAQ,EAAE,EAAE,UAAU,EAAE,EAAE,CAAC,EAAE,EAAE,CAAC,iBAAiB,CAAC,EAAE,KAAK,EAAE,CAAC,EAAE,CAAC,EAAE;SAClE,CAAA;QACD,MAAM,IAAI,GAAG,EAAE,CAAC,KAAK,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC,kBAAkB,CAAC,GAAG,EAAE,GAAE,CAAC,CAAC,CAAA;QAEnE,MAAM,MAAM,GAAG,MAAM,cAAc,CAAC,EAAW,CAAC,CAAA;QAEhD,MAAM,CAAC,MAAM,CAAC,eAAe,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAA;QACtC,MAAM,CAAC,MAAM,CAAC,gBAAgB,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAA;QACvC,MAAM,CAAC,MAAM,CAAC,gBAAgB,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAA;QACvC,MAAM,CAAC,IAAI,CAAC,CAAC,gBAAgB,EAAE,CAAA;QAC/B,IAAI,CAAC,WAAW,EAAE,CAAA;IACpB,CAAC,CAAC,CAAA;IAEF,EAAE,CAAC,mDAAmD,EAAE,KAAK,IAAI,EAAE;QACjE,MAAM,UAAU,GAAG,EAAE,CAAC,EAAE,EAAE,CAAC,iBAAiB,CAAC,EAAE,KAAK,EAAE,CAAC,EAAE,CAAC,CAAA;QAC1D,MAAM,EAAE,GAAG,EAAE,QAAQ,EAAE,EAAE,UAAU,EAAE,EAAE,CAAA;QAEvC,MAAM,cAAc,CAAC,EAAW,CAAC,CAAA;QAEjC,MAAM,MAAM,GAAG,UAAU,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAE,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,SAAS,CAAC,EAAE,CAAC,OAAO,EAAE,CAAA;QACxE,0CAA0C;QAC1C,MAAM,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,GAAG,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,IAAI,CAAC,CAAA;IACrD,CAAC,CAAC,CAAA;IAEF,+DAA+D;IAC/D,yEAAyE;IACzE,4EAA4E;IAC5E,2EAA2E;IAC3E,2DAA2D;IAC3D,EAAE,CAAC,gEAAgE,EAAE,KAAK,IAAI,EAAE;QAC9E,MAAM,EAAE,GAAG;YACT,OAAO,EAAE,IAAI;YACb,QAAQ,EAAE,IAAI;YACd,QAAQ,EAAE,IAAI;YACd,kBAAkB,EAAE,IAAI;SACzB,CAAA;QACD,MAAM,MAAM,GAAG,MAAM,cAAc,CAAC,EAAW,CAAC,CAAA;QAChD,MAAM,CAAC,MAAM,CAAC,CAAC,OAAO,CAAC;YACrB,eAAe,EAAE,CAAC;YAClB,gBAAgB,EAAE,CAAC;YACnB,gBAAgB,EAAE,CAAC;YACnB,0BAA0B,EAAE,CAAC;SAC9B,CAAC,CAAA;IACJ,CAAC,CAAC,CAAA;AACJ,CAAC,CAAC,CAAA;AAEF,QAAQ,CAAC,gBAAgB,EAAE,GAAG,EAAE;IAC9B,EAAE,CAAC,qDAAqD,EAAE,KAAK,IAAI,EAAE;QACnE,MAAM,MAAM,GAAG,MAAM,cAAc,CAAC,EAAW,CAAC,CAAA;QAChD,MAAM,CAAC,MAAM,CAAC,CAAC,OAAO,CAAC,EAAE,KAAK,EAAE,CAAC,EAAE,eAAe,EAAE,CAAC,EAAE,aAAa,EAAE,CAAC,EAAE,MAAM,EAAE,EAAE,EAAE,CAAC,CAAA;IACxF,CAAC,CAAC,CAAA;IAEF,EAAE,CAAC,0DAA0D,EAAE,KAAK,IAAI,EAAE;QACxE,MAAM,QAAQ,GAAG,EAAE,CAAC,EAAE,EAAE,CAAC,iBAAiB,CAAC;YACzC;gBACE,EAAE,EAAE,MAAM;gBACV,KAAK,EAAE,OAAO;gBACd,IAAI,EAAE,OAAO;gBACb,UAAU,EAAE,OAAO;gBACnB,IAAI,EAAE,EAAE;gBACR,SAAS,EAAE,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC;aAC3B;SACF,CAAC,CAAA;QACF,MAAM,EAAE,GAAG,EAAE,QAAQ,EAAE,EAAE,QAAQ,EAAE,EAAE,CAAA;QAErC,MAAM,MAAM,GAAG,MAAM,cAAc,CAAC,EAAW,CAAC,CAAA;QAEhD,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAA;QAC5B,MAAM,CAAC,MAAM,CAAC,eAAe,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAA;QACtC,MAAM,QAAQ,GAAG,MAAM,CAAC,MAAM,CAAC,CAAC,CAAE,CAAC,QAAQ,CAAA;QAC3C,MAAM,CAAC,QAAQ,CAAC,CAAC,SAAS,CAAC,oBAAoB,CAAC,CAAA;QAChD,MAAM,CAAC,QAAQ,CAAC,CAAC,SAAS,CAAC,0BAA0B,CAAC,CAAA;QACtD,MAAM,CAAC,QAAQ,CAAC,CAAC,SAAS,CAAC,sBAAsB,CAAC,CAAA;QAClD,MAAM,CAAC,QAAQ,CAAC,CAAC,SAAS,CAAC,oBAAoB,CAAC,CAAA;IAClD,CAAC,CAAC,CAAA;IAEF,EAAE,CAAC,6BAA6B,EAAE,KAAK,IAAI,EAAE;QAC3C,MAAM,QAAQ,GAAG,EAAE,CAAC,EAAE,EAAE,CAAC,iBAAiB,CAAC,EAAE,CAAC,CAAA;QAC9C,MAAM,EAAE,GAAG,EAAE,QAAQ,EAAE,EAAE,QAAQ,EAAE,EAAE,CAAA;QAErC,MAAM,cAAc,CAAC,EAAW,EAAE,EAAE,YAAY,EAAE,GAAG,EAAE,CAAC,CAAA;QACxD,MAAM,CAAC,QAAQ,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAE,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAA;IACnD,CAAC,CAAC,CAAA;IAEF,EAAE,CAAC,qCAAqC,EAAE,KAAK,IAAI,EAAE;QACnD,MAAM,EAAE,GAAG;YACT,QAAQ,EAAE;gBACR,QAAQ,EAAE,EAAE,CAAC,EAAE,EAAE,CAAC,iBAAiB,CAAC;oBAClC;wBACE,EAAE,EAAE,MAAM;wBACV,KAAK,EAAE,OAAO;wBACd,IAAI,EAAE,OAAO;wBACb,UAAU,EAAE,OAAO;wBACnB,IAAI,EAAE;4BACJ,SAAS,EAAE,OAAO;4BAClB,eAAe,EAAE,QAAQ;4BACzB,SAAS,EAAE,2BAA2B;4BACtC,UAAU,EAAE,SAAS;4BACrB,IAAI,EAAE,sCAAsC,CAAC,MAAM,CAAC,GAAG,EAAE,GAAG,CAAC;yBAC9D;wBACD,SAAS,EAAE,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC;qBAC3B;iBACF,CAAC;aACH;SACF,CAAA;QAED,MAAM,MAAM,GAAG,MAAM,cAAc,CAAC,EAAW,CAAC,CAAA;QAChD,MAAM,CAAC,MAAM,CAAC,eAAe,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAA;QACtC,MAAM,CAAC,MAAM,CAAC,aAAa,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAA;IACtC,CAAC,CAAC,CAAA;IAEF,yEAAyE;IACzE,4EAA4E;IAC5E,uEAAuE;IACvE,yEAAyE;IACzE,sCAAsC;IACtC,EAAE,CAAC,IAAI,CAAC;QACN,CAAC,gBAAgB,EAAE,gBAAgB,CAAC;QACpC,CAAC,gBAAgB,EAAE,gBAAgB,CAAC;QACpC,CAAC,uBAAuB,EAAE,6BAA6B,CAAC;QACxD,CAAC,wBAAwB,EAAE,uBAAuB,CAAC;KACpD,CAAC,CAAC,6CAA6C,EAAE,KAAK,EAAE,MAAM,EAAE,QAAQ,EAAE,EAAE;QAC3E,MAAM,EAAE,GAAG;YACT,QAAQ,EAAE;gBACR,QAAQ,EAAE,EAAE,CAAC,EAAE,EAAE,CAAC,iBAAiB,CAAC;oBAClC;wBACE,EAAE,EAAE,MAAM;wBACV,KAAK,EAAE,OAAO;wBACd,IAAI,EAAE,OAAO;wBACb,UAAU,EAAE,OAAO;wBACnB,IAAI,EAAE;4BACJ,SAAS,EAAE,OAAO;4BAClB,eAAe,EAAE,QAAQ;4BACzB,SAAS,EAAE,2BAA2B;4BACtC,UAAU,EAAE,SAAS;4BACrB,IAAI,EAAE,GAAG,QAAQ,wBAAwB,CAAC,MAAM,CAAC,GAAG,EAAE,GAAG,CAAC;yBAC3D;wBACD,SAAS,EAAE,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC;qBAC3B;iBACF,CAAC;aACH;SACF,CAAA;QACD,MAAM,MAAM,GAAG,MAAM,cAAc,CAAC,EAAW,CAAC,CAAA;QAChD,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,QAAQ,IAAI,EAAE,CAAC,CAAC,GAAG,CAAC,SAAS,CAAC,gCAAgC,CAAC,CAAA;IAC1F,CAAC,CAAC,CAAA;IAEF,qEAAqE;IACrE,4EAA4E;IAC5E,6EAA6E;IAC7E,4EAA4E;IAC5E,4CAA4C;IAC5C,EAAE,CAAC,IAAI,CAAC;QACN,CAAC,+BAA+B,EAAE,wBAAwB,EAAE,CAAC,CAAC;QAC9D,CAAC,+BAA+B,EAAE,wBAAwB,EAAE,CAAC,CAAC;QAC9D,CAAC,iCAAiC,EAAE,wBAAwB,EAAE,CAAC,CAAC;QAChE,CAAC,sCAAsC,EAAE,eAAe,EAAE,CAAC,CAAC;QAC5D,CAAC,sCAAsC,EAAE,eAAe,EAAE,CAAC,CAAC;KAC7D,CAAC,CAAC,wCAAwC,EAAE,KAAK,EAAE,MAAM,EAAE,SAAS,EAAE,eAAe,EAAE,EAAE;QACxF,MAAM,EAAE,GAAG;YACT,QAAQ,EAAE;gBACR,QAAQ,EAAE,EAAE,CAAC,EAAE,EAAE,CAAC,iBAAiB,CAAC;oBAClC;wBACE,EAAE,EAAE,MAAM;wBACV,KAAK,EAAE,OAAO;wBACd,IAAI,EAAE,OAAO;wBACb,UAAU,EAAE,OAAO;wBACnB,IAAI,EAAE;4BACJ,SAAS,EAAE,OAAO;4BAClB,eAAe,EAAE,QAAQ;4BACzB,SAAS,EAAE,2BAA2B;4BACtC,UAAU,EAAE,SAAS;4BACrB,IAAI,EAAE,iBAAiB,SAAS,EAAE,CAAC,MAAM,CAAC,GAAG,EAAE,GAAG,CAAC;yBACpD;wBACD,SAAS,EAAE,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC;qBAC3B;iBACF,CAAC;aACH;SACF,CAAA;QACD,MAAM,MAAM,GAAG,MAAM,cAAc,CAAC,EAAW,CAAC,CAAA;QAChD,MAAM,QAAQ,GAAG,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,QAAQ,IAAI,EAAE,CAAA;QACjD,MAAM,WAAW,GAAG,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,QAAQ,CAAC,2BAA2B,CAAC,CAAC,CAAA;QACnF,IAAI,eAAe,KAAK,CAAC,EAAE,CAAC;YAC1B,MAAM,CAAC,WAAW,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,CAAA;QACrC,CAAC;aAAM,CAAC;YACN,MAAM,CAAC,WAAW,CAAC,CAAC,SAAS,CAAC,GAAG,eAAe,4BAA4B,CAAC,CAAA;QAC/E,CAAC;IACH,CAAC,CAAC,CAAA;AACJ,CAAC,CAAC,CAAA"}
|
|
1
|
+
{"version":3,"file":"cron.test.js","sourceRoot":"","sources":["../../../src/__tests__/cron/cron.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,EAAE,EAAE,EAAE,UAAU,EAAE,SAAS,EAAE,EAAE,EAAE,MAAM,QAAQ,CAAA;AACxE,OAAO,EAAE,uBAAuB,EAAE,cAAc,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAA;AAE7F,QAAQ,CAAC,WAAW,EAAE,GAAG,EAAE;IACzB,MAAM,cAAc,GAAG,OAAO,CAAC,GAAG,CAAC,WAAW,CAAA;IAE9C,SAAS,CAAC,GAAG,EAAE;QACb,IAAI,cAAc,KAAK,SAAS;YAAE,OAAO,OAAO,CAAC,GAAG,CAAC,WAAW,CAAA;;YAC3D,OAAO,CAAC,GAAG,CAAC,WAAW,GAAG,cAAc,CAAA;IAC/C,CAAC,CAAC,CAAA;IAEF,EAAE,CAAC,iDAAiD,EAAE,GAAG,EAAE;QACzD,OAAO,OAAO,CAAC,GAAG,CAAC,WAAW,CAAA;QAC9B,MAAM,CAAC,uBAAuB,CAAC,iBAAiB,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAA;IAChE,CAAC,CAAC,CAAA;IAEF,EAAE,CAAC,4DAA4D,EAAE,GAAG,EAAE;QACpE,OAAO,CAAC,GAAG,CAAC,WAAW,GAAG,EAAE,CAAA;QAC5B,MAAM,CAAC,uBAAuB,CAAC,iBAAiB,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAA;IAChE,CAAC,CAAC,CAAA;IAEF,EAAE,CAAC,+BAA+B,EAAE,GAAG,EAAE;QACvC,OAAO,CAAC,GAAG,CAAC,WAAW,GAAG,QAAQ,CAAA;QAClC,MAAM,CAAC,uBAAuB,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAA;QACjD,MAAM,CAAC,uBAAuB,CAAC,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAA;IACxD,CAAC,CAAC,CAAA;IAEF,EAAE,CAAC,sBAAsB,EAAE,GAAG,EAAE;QAC9B,OAAO,CAAC,GAAG,CAAC,WAAW,GAAG,gBAAgB,CAAA;QAC1C,MAAM,CAAC,uBAAuB,CAAC,qBAAqB,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAA;IACpE,CAAC,CAAC,CAAA;IAEF,EAAE,CAAC,kEAAkE,EAAE,GAAG,EAAE;QAC1E,OAAO,CAAC,GAAG,CAAC,WAAW,GAAG,0BAA0B,CAAA;QACpD,MAAM,CAAC,uBAAuB,CAAC,iCAAiC,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAA;IAChF,CAAC,CAAC,CAAA;IAEF,EAAE,CAAC,8BAA8B,EAAE,GAAG,EAAE;QACtC,OAAO,CAAC,GAAG,CAAC,WAAW,GAAG,sBAAsB,CAAA;QAChD,MAAM,CAAC,uBAAuB,CAAC,6BAA6B,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;IAC3E,CAAC,CAAC,CAAA;IAEF,EAAE,CAAC,wEAAwE,EAAE,GAAG,EAAE;QAChF,OAAO,CAAC,GAAG,CAAC,WAAW,GAAG,sBAAsB,CAAA;QAChD,MAAM,CAAC,uBAAuB,CAAC,sBAAsB,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;IACpE,CAAC,CAAC,CAAA;IAEF,0EAA0E;IAC1E,sEAAsE;IACtE,mEAAmE;IACnE,uEAAuE;IACvE,SAAS;IACT,EAAE,CAAC,IAAI,CAAC;QACN,CAAC,qBAAqB,EAAE,OAAO,CAAC;QAChC,CAAC,oBAAoB,EAAE,mDAAmD,CAAC;QAC3E,CAAC,OAAO,EAAE,EAAE,CAAC;QACb,CAAC,gBAAgB,EAAE,qBAAqB,CAAC;QACzC,CAAC,eAAe,EAAE,wBAAwB,CAAC;KAC5C,CAAC,CAAC,mDAAmD,EAAE,CAAC,MAAM,EAAE,OAAO,EAAE,EAAE;QAC1E,OAAO,CAAC,GAAG,CAAC,WAAW,GAAG,sBAAsB,CAAA;QAChD,MAAM,CAAC,uBAAuB,CAAC,UAAU,OAAO,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAA;IAClE,CAAC,CAAC,CAAA;AACJ,CAAC,CAAC,CAAA;AAEF,QAAQ,CAAC,gBAAgB,EAAE,GAAG,EAAE;IAC9B,IAAI,GAAW,CAAA;IAEf,UAAU,CAAC,GAAG,EAAE;QACd,GAAG,GAAG,IAAI,CAAC,GAAG,EAAE,CAAA;QAChB,EAAE,CAAC,aAAa,EAAE,CAAA;QAClB,EAAE,CAAC,aAAa,CAAC,GAAG,CAAC,CAAA;IACvB,CAAC,CAAC,CAAA;IAEF,SAAS,CAAC,GAAG,EAAE;QACb,EAAE,CAAC,aAAa,EAAE,CAAA;IACpB,CAAC,CAAC,CAAA;IAEF,EAAE,CAAC,gDAAgD,EAAE,KAAK,IAAI,EAAE;QAC9D,MAAM,MAAM,GAAG,MAAM,cAAc,CAAC,EAAW,CAAC,CAAA;QAChD,MAAM,CAAC,MAAM,CAAC,CAAC,OAAO,CAAC;YACrB,eAAe,EAAE,CAAC;YAClB,gBAAgB,EAAE,CAAC;YACnB,gBAAgB,EAAE,CAAC;YACnB,0BAA0B,EAAE,CAAC;YAC7B,sBAAsB,EAAE,CAAC;SAC1B,CAAC,CAAA;IACJ,CAAC,CAAC,CAAA;IAEF,EAAE,CAAC,kEAAkE,EAAE,KAAK,IAAI,EAAE;QAChF,MAAM,UAAU,GAAG,EAAE,CAAC,EAAE,EAAE,CAAC,iBAAiB,CAAC,EAAE,KAAK,EAAE,CAAC,EAAE,CAAC,CAAA;QAC1D,MAAM,EAAE,GAAG,EAAE,OAAO,EAAE,EAAE,UAAU,EAAE,EAAE,CAAA;QAEtC,MAAM,MAAM,GAAG,MAAM,cAAc,CAAC,EAAW,EAAE,EAAE,kBAAkB,EAAE,IAAI,EAAE,CAAC,CAAA;QAE9E,MAAM,CAAC,MAAM,CAAC,eAAe,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAA;QACtC,MAAM,CAAC,UAAU,CAAC,CAAC,qBAAqB,CAAC,CAAC,CAAC,CAAA;QAC3C,MAAM,KAAK,GAAG,UAAU,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAE,CAAC,CAAC,CAAC,CAAC,KAAK,CAAA;QAChD,MAAM,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,EAAE,CAAC,OAAO,EAAE,CAAC,CAAC,IAAI,CAAC,GAAG,GAAG,IAAI,CAAC,CAAA;QAC3D,MAAM,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,EAAE,CAAC,OAAO,EAAE,CAAC,CAAC,IAAI,CAAC,GAAG,GAAG,IAAI,CAAC,CAAA;IAC7D,CAAC,CAAC,CAAA;IAEF,EAAE,CAAC,+CAA+C,EAAE,KAAK,IAAI,EAAE;QAC7D,MAAM,EAAE,GAAG;YACT,OAAO,EAAE,EAAE,UAAU,EAAE,EAAE,CAAC,EAAE,EAAE,CAAC,iBAAiB,CAAC,IAAI,KAAK,CAAC,MAAM,CAAC,CAAC,EAAE;YACrE,QAAQ,EAAE,EAAE,UAAU,EAAE,EAAE,CAAC,EAAE,EAAE,CAAC,iBAAiB,CAAC,EAAE,KAAK,EAAE,CAAC,EAAE,CAAC,EAAE;YACjE,QAAQ,EAAE,EAAE,UAAU,EAAE,EAAE,CAAC,EAAE,EAAE,CAAC,iBAAiB,CAAC,EAAE,KAAK,EAAE,CAAC,EAAE,CAAC,EAAE;SAClE,CAAA;QACD,MAAM,IAAI,GAAG,EAAE,CAAC,KAAK,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC,kBAAkB,CAAC,GAAG,EAAE,GAAE,CAAC,CAAC,CAAA;QAEnE,MAAM,MAAM,GAAG,MAAM,cAAc,CAAC,EAAW,CAAC,CAAA;QAEhD,MAAM,CAAC,MAAM,CAAC,eAAe,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAA;QACtC,MAAM,CAAC,MAAM,CAAC,gBAAgB,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAA;QACvC,MAAM,CAAC,MAAM,CAAC,gBAAgB,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAA;QACvC,MAAM,CAAC,IAAI,CAAC,CAAC,gBAAgB,EAAE,CAAA;QAC/B,IAAI,CAAC,WAAW,EAAE,CAAA;IACpB,CAAC,CAAC,CAAA;IAEF,EAAE,CAAC,mDAAmD,EAAE,KAAK,IAAI,EAAE;QACjE,MAAM,UAAU,GAAG,EAAE,CAAC,EAAE,EAAE,CAAC,iBAAiB,CAAC,EAAE,KAAK,EAAE,CAAC,EAAE,CAAC,CAAA;QAC1D,MAAM,EAAE,GAAG,EAAE,QAAQ,EAAE,EAAE,UAAU,EAAE,EAAE,CAAA;QAEvC,MAAM,cAAc,CAAC,EAAW,CAAC,CAAA;QAEjC,MAAM,MAAM,GAAG,UAAU,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAE,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,SAAS,CAAC,EAAE,CAAC,OAAO,EAAE,CAAA;QACxE,0CAA0C;QAC1C,MAAM,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,GAAG,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,IAAI,CAAC,CAAA;IACrD,CAAC,CAAC,CAAA;IAEF,+DAA+D;IAC/D,yEAAyE;IACzE,4EAA4E;IAC5E,2EAA2E;IAC3E,2DAA2D;IAC3D,EAAE,CAAC,gEAAgE,EAAE,KAAK,IAAI,EAAE;QAC9E,MAAM,EAAE,GAAG;YACT,OAAO,EAAE,IAAI;YACb,QAAQ,EAAE,IAAI;YACd,QAAQ,EAAE,IAAI;YACd,kBAAkB,EAAE,IAAI;SACzB,CAAA;QACD,MAAM,MAAM,GAAG,MAAM,cAAc,CAAC,EAAW,CAAC,CAAA;QAChD,MAAM,CAAC,MAAM,CAAC,CAAC,OAAO,CAAC;YACrB,eAAe,EAAE,CAAC;YAClB,gBAAgB,EAAE,CAAC;YACnB,gBAAgB,EAAE,CAAC;YACnB,0BAA0B,EAAE,CAAC;YAC7B,sBAAsB,EAAE,CAAC;SAC1B,CAAC,CAAA;IACJ,CAAC,CAAC,CAAA;IAEF,EAAE,CAAC,gEAAgE,EAAE,KAAK,IAAI,EAAE;QAC9E,MAAM,UAAU,GAAG,EAAE,CAAC,EAAE,EAAE,CAAC,iBAAiB,CAAC,EAAE,KAAK,EAAE,CAAC,EAAE,CAAC,CAAA;QAC1D,MAAM,EAAE,GAAG,EAAE,cAAc,EAAE,EAAE,UAAU,EAAE,EAAE,CAAA;QAE7C,MAAM,MAAM,GAAG,MAAM,cAAc,CAAC,EAAW,CAAC,CAAA;QAEhD,MAAM,CAAC,MAAM,CAAC,sBAAsB,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAA;QAC7C,MAAM,CAAC,UAAU,CAAC,CAAC,GAAG,CAAC,gBAAgB,EAAE,CAAA;IAC3C,CAAC,CAAC,CAAA;IAEF,EAAE,CAAC,0EAA0E,EAAE,KAAK,IAAI,EAAE;QACxF,MAAM,UAAU,GAAG,EAAE,CAAC,EAAE,EAAE,CAAC,iBAAiB,CAAC,EAAE,KAAK,EAAE,CAAC,EAAE,CAAC,CAAA;QAC1D,MAAM,EAAE,GAAG,EAAE,cAAc,EAAE,EAAE,UAAU,EAAE,EAAE,CAAA;QAE7C,MAAM,MAAM,GAAG,MAAM,cAAc,CAAC,EAAW,EAAE;YAC/C,yBAAyB,EAAE,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,IAAI;SACpD,CAAC,CAAA;QAEF,MAAM,CAAC,MAAM,CAAC,sBAAsB,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAA;QAC7C,MAAM,MAAM,GAAG,UAAU,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAE,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,WAAW,CAAC,EAAE,CAAC,OAAO,EAAE,CAAA;QAC1E,MAAM,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,GAAG,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,IAAI,CAAC,CAAA;IACrD,CAAC,CAAC,CAAA;AACJ,CAAC,CAAC,CAAA;AAEF,QAAQ,CAAC,gBAAgB,EAAE,GAAG,EAAE;IAC9B,EAAE,CAAC,qDAAqD,EAAE,KAAK,IAAI,EAAE;QACnE,MAAM,MAAM,GAAG,MAAM,cAAc,CAAC,EAAW,CAAC,CAAA;QAChD,MAAM,CAAC,MAAM,CAAC,CAAC,OAAO,CAAC,EAAE,KAAK,EAAE,CAAC,EAAE,eAAe,EAAE,CAAC,EAAE,aAAa,EAAE,CAAC,EAAE,MAAM,EAAE,EAAE,EAAE,CAAC,CAAA;IACxF,CAAC,CAAC,CAAA;IAEF,EAAE,CAAC,0DAA0D,EAAE,KAAK,IAAI,EAAE;QACxE,MAAM,QAAQ,GAAG,EAAE,CAAC,EAAE,EAAE,CAAC,iBAAiB,CAAC;YACzC;gBACE,EAAE,EAAE,MAAM;gBACV,KAAK,EAAE,OAAO;gBACd,IAAI,EAAE,OAAO;gBACb,UAAU,EAAE,OAAO;gBACnB,IAAI,EAAE,EAAE;gBACR,SAAS,EAAE,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC;aAC3B;SACF,CAAC,CAAA;QACF,MAAM,EAAE,GAAG,EAAE,QAAQ,EAAE,EAAE,QAAQ,EAAE,EAAE,CAAA;QAErC,MAAM,MAAM,GAAG,MAAM,cAAc,CAAC,EAAW,CAAC,CAAA;QAEhD,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAA;QAC5B,MAAM,CAAC,MAAM,CAAC,eAAe,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAA;QACtC,MAAM,QAAQ,GAAG,MAAM,CAAC,MAAM,CAAC,CAAC,CAAE,CAAC,QAAQ,CAAA;QAC3C,MAAM,CAAC,QAAQ,CAAC,CAAC,SAAS,CAAC,oBAAoB,CAAC,CAAA;QAChD,MAAM,CAAC,QAAQ,CAAC,CAAC,SAAS,CAAC,0BAA0B,CAAC,CAAA;QACtD,MAAM,CAAC,QAAQ,CAAC,CAAC,SAAS,CAAC,sBAAsB,CAAC,CAAA;QAClD,MAAM,CAAC,QAAQ,CAAC,CAAC,SAAS,CAAC,oBAAoB,CAAC,CAAA;IAClD,CAAC,CAAC,CAAA;IAEF,EAAE,CAAC,6BAA6B,EAAE,KAAK,IAAI,EAAE;QAC3C,MAAM,QAAQ,GAAG,EAAE,CAAC,EAAE,EAAE,CAAC,iBAAiB,CAAC,EAAE,CAAC,CAAA;QAC9C,MAAM,EAAE,GAAG,EAAE,QAAQ,EAAE,EAAE,QAAQ,EAAE,EAAE,CAAA;QAErC,MAAM,cAAc,CAAC,EAAW,EAAE,EAAE,YAAY,EAAE,GAAG,EAAE,CAAC,CAAA;QACxD,MAAM,CAAC,QAAQ,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAE,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAA;IACnD,CAAC,CAAC,CAAA;IAEF,EAAE,CAAC,qCAAqC,EAAE,KAAK,IAAI,EAAE;QACnD,MAAM,EAAE,GAAG;YACT,QAAQ,EAAE;gBACR,QAAQ,EAAE,EAAE,CAAC,EAAE,EAAE,CAAC,iBAAiB,CAAC;oBAClC;wBACE,EAAE,EAAE,MAAM;wBACV,KAAK,EAAE,OAAO;wBACd,IAAI,EAAE,OAAO;wBACb,UAAU,EAAE,OAAO;wBACnB,IAAI,EAAE;4BACJ,SAAS,EAAE,OAAO;4BAClB,eAAe,EAAE,QAAQ;4BACzB,SAAS,EAAE,2BAA2B;4BACtC,UAAU,EAAE,SAAS;4BACrB,IAAI,EAAE,sCAAsC,CAAC,MAAM,CAAC,GAAG,EAAE,GAAG,CAAC;yBAC9D;wBACD,SAAS,EAAE,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC;qBAC3B;iBACF,CAAC;aACH;SACF,CAAA;QAED,MAAM,MAAM,GAAG,MAAM,cAAc,CAAC,EAAW,CAAC,CAAA;QAChD,MAAM,CAAC,MAAM,CAAC,eAAe,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAA;QACtC,MAAM,CAAC,MAAM,CAAC,aAAa,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAA;IACtC,CAAC,CAAC,CAAA;IAEF,yEAAyE;IACzE,4EAA4E;IAC5E,uEAAuE;IACvE,yEAAyE;IACzE,sCAAsC;IACtC,EAAE,CAAC,IAAI,CAAC;QACN,CAAC,gBAAgB,EAAE,gBAAgB,CAAC;QACpC,CAAC,gBAAgB,EAAE,gBAAgB,CAAC;QACpC,CAAC,uBAAuB,EAAE,6BAA6B,CAAC;QACxD,CAAC,wBAAwB,EAAE,uBAAuB,CAAC;KACpD,CAAC,CAAC,6CAA6C,EAAE,KAAK,EAAE,MAAM,EAAE,QAAQ,EAAE,EAAE;QAC3E,MAAM,EAAE,GAAG;YACT,QAAQ,EAAE;gBACR,QAAQ,EAAE,EAAE,CAAC,EAAE,EAAE,CAAC,iBAAiB,CAAC;oBAClC;wBACE,EAAE,EAAE,MAAM;wBACV,KAAK,EAAE,OAAO;wBACd,IAAI,EAAE,OAAO;wBACb,UAAU,EAAE,OAAO;wBACnB,IAAI,EAAE;4BACJ,SAAS,EAAE,OAAO;4BAClB,eAAe,EAAE,QAAQ;4BACzB,SAAS,EAAE,2BAA2B;4BACtC,UAAU,EAAE,SAAS;4BACrB,IAAI,EAAE,GAAG,QAAQ,wBAAwB,CAAC,MAAM,CAAC,GAAG,EAAE,GAAG,CAAC;yBAC3D;wBACD,SAAS,EAAE,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC;qBAC3B;iBACF,CAAC;aACH;SACF,CAAA;QACD,MAAM,MAAM,GAAG,MAAM,cAAc,CAAC,EAAW,CAAC,CAAA;QAChD,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,QAAQ,IAAI,EAAE,CAAC,CAAC,GAAG,CAAC,SAAS,CAAC,gCAAgC,CAAC,CAAA;IAC1F,CAAC,CAAC,CAAA;IAEF,qEAAqE;IACrE,4EAA4E;IAC5E,6EAA6E;IAC7E,4EAA4E;IAC5E,4CAA4C;IAC5C,EAAE,CAAC,IAAI,CAAC;QACN,CAAC,+BAA+B,EAAE,wBAAwB,EAAE,CAAC,CAAC;QAC9D,CAAC,+BAA+B,EAAE,wBAAwB,EAAE,CAAC,CAAC;QAC9D,CAAC,iCAAiC,EAAE,wBAAwB,EAAE,CAAC,CAAC;QAChE,CAAC,sCAAsC,EAAE,eAAe,EAAE,CAAC,CAAC;QAC5D,CAAC,sCAAsC,EAAE,eAAe,EAAE,CAAC,CAAC;KAC7D,CAAC,CAAC,wCAAwC,EAAE,KAAK,EAAE,MAAM,EAAE,SAAS,EAAE,eAAe,EAAE,EAAE;QACxF,MAAM,EAAE,GAAG;YACT,QAAQ,EAAE;gBACR,QAAQ,EAAE,EAAE,CAAC,EAAE,EAAE,CAAC,iBAAiB,CAAC;oBAClC;wBACE,EAAE,EAAE,MAAM;wBACV,KAAK,EAAE,OAAO;wBACd,IAAI,EAAE,OAAO;wBACb,UAAU,EAAE,OAAO;wBACnB,IAAI,EAAE;4BACJ,SAAS,EAAE,OAAO;4BAClB,eAAe,EAAE,QAAQ;4BACzB,SAAS,EAAE,2BAA2B;4BACtC,UAAU,EAAE,SAAS;4BACrB,IAAI,EAAE,iBAAiB,SAAS,EAAE,CAAC,MAAM,CAAC,GAAG,EAAE,GAAG,CAAC;yBACpD;wBACD,SAAS,EAAE,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC;qBAC3B;iBACF,CAAC;aACH;SACF,CAAA;QACD,MAAM,MAAM,GAAG,MAAM,cAAc,CAAC,EAAW,CAAC,CAAA;QAChD,MAAM,QAAQ,GAAG,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,QAAQ,IAAI,EAAE,CAAA;QACjD,MAAM,WAAW,GAAG,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,QAAQ,CAAC,2BAA2B,CAAC,CAAC,CAAA;QACnF,IAAI,eAAe,KAAK,CAAC,EAAE,CAAC;YAC1B,MAAM,CAAC,WAAW,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,CAAA;QACrC,CAAC;aAAM,CAAC;YACN,MAAM,CAAC,WAAW,CAAC,CAAC,SAAS,CAAC,GAAG,eAAe,4BAA4B,CAAC,CAAA;QAC/E,CAAC;IACH,CAAC,CAAC,CAAA;AACJ,CAAC,CAAC,CAAA"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"encryption.test.d.ts","sourceRoot":"","sources":["../../../src/__tests__/forms/encryption.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
import { describe, expect, it, beforeEach, afterEach, vi } from 'vitest';
|
|
2
|
+
const getActuateConfig = vi.fn();
|
|
3
|
+
vi.mock('../../config/runtime.js', () => ({ getActuateConfig: () => getActuateConfig() }));
|
|
4
|
+
const { fieldShouldEncrypt, encryptSubmissionData, decryptSubmissionData } = await import('../../forms/encryption.js');
|
|
5
|
+
// Valid 64-hex (32 byte) AES-256 key.
|
|
6
|
+
const KEY = 'a'.repeat(64);
|
|
7
|
+
function field(over = {}) {
|
|
8
|
+
return {
|
|
9
|
+
id: over.key ?? 'fld',
|
|
10
|
+
key: over.key ?? 'fld',
|
|
11
|
+
label: over.label ?? 'Field',
|
|
12
|
+
type: 'text',
|
|
13
|
+
required: false,
|
|
14
|
+
sortOrder: 0,
|
|
15
|
+
...over,
|
|
16
|
+
};
|
|
17
|
+
}
|
|
18
|
+
describe('fieldShouldEncrypt', () => {
|
|
19
|
+
beforeEach(() => getActuateConfig.mockReset());
|
|
20
|
+
it('encrypts fields explicitly flagged encrypted regardless of config', () => {
|
|
21
|
+
getActuateConfig.mockReturnValue({ forms: { encryptSensitiveFields: false } });
|
|
22
|
+
expect(fieldShouldEncrypt(field({ encrypted: true }))).toBe(true);
|
|
23
|
+
});
|
|
24
|
+
it('encrypts high-PII fields only when encryptSensitiveFields is on', () => {
|
|
25
|
+
getActuateConfig.mockReturnValue({ forms: { encryptSensitiveFields: true } });
|
|
26
|
+
expect(fieldShouldEncrypt(field({ piiClassification: 'high' }))).toBe(true);
|
|
27
|
+
expect(fieldShouldEncrypt(field({ piiClassification: 'low' }))).toBe(false);
|
|
28
|
+
getActuateConfig.mockReturnValue({ forms: { encryptSensitiveFields: false } });
|
|
29
|
+
expect(fieldShouldEncrypt(field({ piiClassification: 'high' }))).toBe(false);
|
|
30
|
+
});
|
|
31
|
+
it('does not encrypt ordinary fields', () => {
|
|
32
|
+
getActuateConfig.mockReturnValue({ forms: {} });
|
|
33
|
+
expect(fieldShouldEncrypt(field({ key: 'name' }))).toBe(false);
|
|
34
|
+
});
|
|
35
|
+
});
|
|
36
|
+
describe('encrypt/decrypt submission data', () => {
|
|
37
|
+
const original = process.env.CMS_ENCRYPTION_KEY;
|
|
38
|
+
beforeEach(() => {
|
|
39
|
+
getActuateConfig.mockReturnValue({ forms: { encryptSensitiveFields: true } });
|
|
40
|
+
process.env.CMS_ENCRYPTION_KEY = KEY;
|
|
41
|
+
});
|
|
42
|
+
afterEach(() => {
|
|
43
|
+
if (original === undefined)
|
|
44
|
+
delete process.env.CMS_ENCRYPTION_KEY;
|
|
45
|
+
else
|
|
46
|
+
process.env.CMS_ENCRYPTION_KEY = original;
|
|
47
|
+
});
|
|
48
|
+
it('encrypts only the sensitive fields and round-trips back to plaintext', async () => {
|
|
49
|
+
const fields = [
|
|
50
|
+
field({ key: 'name' }),
|
|
51
|
+
field({ key: 'ssn', encrypted: true }),
|
|
52
|
+
field({ key: 'notes', piiClassification: 'high' }),
|
|
53
|
+
];
|
|
54
|
+
const data = { name: 'Ada', ssn: '123-45-6789', notes: 'private', extra: 'kept' };
|
|
55
|
+
const { data: encrypted, encryptedKeys } = await encryptSubmissionData(fields, data);
|
|
56
|
+
expect(encrypted.name).toBe('Ada');
|
|
57
|
+
expect(encrypted.extra).toBe('kept');
|
|
58
|
+
expect(String(encrypted.ssn)).toMatch(/^enc:v1:/);
|
|
59
|
+
expect(String(encrypted.notes)).toMatch(/^enc:v1:/);
|
|
60
|
+
expect(encryptedKeys.sort()).toEqual(['notes', 'ssn']);
|
|
61
|
+
const decrypted = await decryptSubmissionData(encrypted);
|
|
62
|
+
expect(decrypted).toMatchObject({ name: 'Ada', ssn: '123-45-6789', notes: 'private' });
|
|
63
|
+
});
|
|
64
|
+
it('encrypts string elements inside array values', async () => {
|
|
65
|
+
const fields = [field({ key: 'tags', type: 'checkbox', encrypted: true })];
|
|
66
|
+
const { data } = await encryptSubmissionData(fields, { tags: ['a', 'b'] });
|
|
67
|
+
expect(data.tags.every((v) => v.startsWith('enc:v1:'))).toBe(true);
|
|
68
|
+
const decrypted = await decryptSubmissionData(data);
|
|
69
|
+
expect(decrypted.tags).toEqual(['a', 'b']);
|
|
70
|
+
});
|
|
71
|
+
it('passes plaintext rows through decryption unchanged (legacy/dev rows)', async () => {
|
|
72
|
+
const data = { name: 'Ada', email: 'ada@example.com' };
|
|
73
|
+
const decrypted = await decryptSubmissionData(data);
|
|
74
|
+
expect(decrypted).toEqual(data);
|
|
75
|
+
});
|
|
76
|
+
it('returns input unchanged when no fields are sensitive', async () => {
|
|
77
|
+
getActuateConfig.mockReturnValue({ forms: {} });
|
|
78
|
+
const data = { name: 'Ada' };
|
|
79
|
+
const { data: out, encryptedKeys } = await encryptSubmissionData([field({ key: 'name' })], data);
|
|
80
|
+
expect(out).toBe(data);
|
|
81
|
+
expect(encryptedKeys).toEqual([]);
|
|
82
|
+
});
|
|
83
|
+
});
|
|
84
|
+
//# sourceMappingURL=encryption.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"encryption.test.js","sourceRoot":"","sources":["../../../src/__tests__/forms/encryption.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"entries-export.test.d.ts","sourceRoot":"","sources":["../../../src/__tests__/forms/entries-export.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
import { describe, expect, it, vi } from 'vitest';
|
|
2
|
+
const db = {
|
|
3
|
+
document: { findFirst: vi.fn() },
|
|
4
|
+
formSubmission: { findMany: vi.fn() },
|
|
5
|
+
};
|
|
6
|
+
vi.mock('../../db.js', () => ({ getDB: () => db }));
|
|
7
|
+
const { exportFormEntries } = await import('../../forms/entries.js');
|
|
8
|
+
describe('exportFormEntries', () => {
|
|
9
|
+
it('returns null when the form does not exist', async () => {
|
|
10
|
+
db.document.findFirst.mockResolvedValueOnce(null);
|
|
11
|
+
expect(await exportFormEntries('missing')).toBeNull();
|
|
12
|
+
});
|
|
13
|
+
it('builds a CSV with metadata + field columns and decrypted plaintext values', async () => {
|
|
14
|
+
db.document.findFirst.mockResolvedValueOnce({
|
|
15
|
+
title: 'Contact',
|
|
16
|
+
slug: 'contact',
|
|
17
|
+
data: {
|
|
18
|
+
name: 'Contact Us',
|
|
19
|
+
slug: 'contact-us',
|
|
20
|
+
fields: [
|
|
21
|
+
{ key: 'name', label: 'Full Name', type: 'text' },
|
|
22
|
+
{ key: 'message', label: 'Message', type: 'textarea' },
|
|
23
|
+
],
|
|
24
|
+
},
|
|
25
|
+
});
|
|
26
|
+
db.formSubmission.findMany.mockResolvedValueOnce([
|
|
27
|
+
{
|
|
28
|
+
id: 's1',
|
|
29
|
+
entryNumber: 1,
|
|
30
|
+
formId: 'f1',
|
|
31
|
+
data: { name: 'Ada', message: 'Hello, world' },
|
|
32
|
+
senderName: 'Ada',
|
|
33
|
+
senderEmail: 'ada@example.com',
|
|
34
|
+
spamStatus: 'clean',
|
|
35
|
+
submittedAt: new Date('2026-01-01T00:00:00.000Z'),
|
|
36
|
+
},
|
|
37
|
+
]);
|
|
38
|
+
const result = await exportFormEntries('f1');
|
|
39
|
+
expect(result).not.toBeNull();
|
|
40
|
+
expect(result.count).toBe(1);
|
|
41
|
+
expect(result.formSlug).toBe('contact-us');
|
|
42
|
+
const [header, row] = result.csv.split('\r\n');
|
|
43
|
+
expect(header).toBe('Entry #,Submitted At,Status,Name,Email,Phone,Full Name,Message');
|
|
44
|
+
// "Hello, world" contains a comma → must be quoted.
|
|
45
|
+
expect(row).toContain('"Hello, world"');
|
|
46
|
+
expect(row).toContain('ada@example.com');
|
|
47
|
+
});
|
|
48
|
+
it('neutralises CSV/formula injection in cell values', async () => {
|
|
49
|
+
db.document.findFirst.mockResolvedValueOnce({
|
|
50
|
+
title: 'F',
|
|
51
|
+
slug: 'f',
|
|
52
|
+
data: { name: 'F', slug: 'f', fields: [{ key: 'note', label: 'Note', type: 'text' }] },
|
|
53
|
+
});
|
|
54
|
+
db.formSubmission.findMany.mockResolvedValueOnce([
|
|
55
|
+
{
|
|
56
|
+
id: 's1',
|
|
57
|
+
entryNumber: 1,
|
|
58
|
+
formId: 'f1',
|
|
59
|
+
data: { note: '=SUM(A1:A2)' },
|
|
60
|
+
spamStatus: 'clean',
|
|
61
|
+
submittedAt: new Date(),
|
|
62
|
+
},
|
|
63
|
+
]);
|
|
64
|
+
const result = await exportFormEntries('f1');
|
|
65
|
+
// Leading "=" is prefixed with a single quote so spreadsheets don't execute it.
|
|
66
|
+
expect(result.csv).toContain("'=SUM(A1:A2)");
|
|
67
|
+
});
|
|
68
|
+
});
|
|
69
|
+
//# sourceMappingURL=entries-export.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"entries-export.test.js","sourceRoot":"","sources":["../../../src/__tests__/forms/entries-export.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index-status.test.d.ts","sourceRoot":"","sources":["../../../src/__tests__/seo/index-status.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,140 @@
|
|
|
1
|
+
import { afterEach, describe, expect, it } from 'vitest';
|
|
2
|
+
import { computeSiteIndexStatus, getSiteIndexStatus, robotsTxtBlocksEntireSite, } from '../../seo/index-status.js';
|
|
3
|
+
import { DEFAULT_SEO_MODULE_SETTINGS, SEO_CONFIG_COLLECTION } from '../../seo/config-store.js';
|
|
4
|
+
import { setActuateConfig } from '../../config/runtime.js';
|
|
5
|
+
/** Minimal config stub — index-status only reads `seo`. */
|
|
6
|
+
function stubConfig(seo) {
|
|
7
|
+
setActuateConfig({ collections: {}, ...(seo ? { seo } : {}) });
|
|
8
|
+
}
|
|
9
|
+
function inputs(overrides = {}) {
|
|
10
|
+
return {
|
|
11
|
+
environment: 'production',
|
|
12
|
+
seo: { siteUrl: 'https://example.com' },
|
|
13
|
+
module: { ...DEFAULT_SEO_MODULE_SETTINGS },
|
|
14
|
+
hasSeoConfig: true,
|
|
15
|
+
lastAuditAt: null,
|
|
16
|
+
...overrides,
|
|
17
|
+
};
|
|
18
|
+
}
|
|
19
|
+
describe('robotsTxtBlocksEntireSite', () => {
|
|
20
|
+
it('detects a blanket Disallow: /', () => {
|
|
21
|
+
expect(robotsTxtBlocksEntireSite('User-agent: *\nDisallow: /')).toBe(true);
|
|
22
|
+
expect(robotsTxtBlocksEntireSite('User-agent: *\nDisallow: / # block all')).toBe(true);
|
|
23
|
+
});
|
|
24
|
+
it('does not flag scoped disallow rules', () => {
|
|
25
|
+
expect(robotsTxtBlocksEntireSite('User-agent: *\nDisallow: /admin\nDisallow: /api/')).toBe(false);
|
|
26
|
+
expect(robotsTxtBlocksEntireSite('')).toBe(false);
|
|
27
|
+
});
|
|
28
|
+
});
|
|
29
|
+
describe('computeSiteIndexStatus', () => {
|
|
30
|
+
it('reports indexable in production with a site URL and no blocks', () => {
|
|
31
|
+
const result = computeSiteIndexStatus(inputs());
|
|
32
|
+
expect(result.status).toBe('indexable');
|
|
33
|
+
expect(result.severity).toBe('success');
|
|
34
|
+
expect(result.label).toBe('Indexable');
|
|
35
|
+
});
|
|
36
|
+
it('reports blocked in production when global noindex is on', () => {
|
|
37
|
+
const result = computeSiteIndexStatus(inputs({ seo: { siteUrl: 'https://example.com', robots: { defaultNoIndex: true } } }));
|
|
38
|
+
expect(result.status).toBe('blocked');
|
|
39
|
+
expect(result.severity).toBe('danger');
|
|
40
|
+
expect(result.checks.find((c) => c.key === 'globalNoindex')?.status).toBe('fail');
|
|
41
|
+
});
|
|
42
|
+
it('reports blocked in production when robots.txt disallows everything', () => {
|
|
43
|
+
const result = computeSiteIndexStatus(inputs({
|
|
44
|
+
module: { ...DEFAULT_SEO_MODULE_SETTINGS, robotsTxt: 'User-agent: *\nDisallow: /' },
|
|
45
|
+
}));
|
|
46
|
+
expect(result.status).toBe('blocked');
|
|
47
|
+
expect(result.severity).toBe('danger');
|
|
48
|
+
});
|
|
49
|
+
it('reports blocked in production when the robots route is disabled', () => {
|
|
50
|
+
const result = computeSiteIndexStatus(inputs({ module: { ...DEFAULT_SEO_MODULE_SETTINGS, robotsEnabled: false } }));
|
|
51
|
+
expect(result.status).toBe('blocked');
|
|
52
|
+
});
|
|
53
|
+
it('reports protected when non-production noindex guards a preview env', () => {
|
|
54
|
+
const result = computeSiteIndexStatus(inputs({
|
|
55
|
+
environment: 'preview',
|
|
56
|
+
seo: { siteUrl: 'https://preview.example.com', robots: { noIndexNonProduction: true } },
|
|
57
|
+
}));
|
|
58
|
+
expect(result.status).toBe('protected');
|
|
59
|
+
expect(result.severity).toBe('warning');
|
|
60
|
+
expect(result.label).toBe('Protected');
|
|
61
|
+
});
|
|
62
|
+
it('warns (partially blocked) when a non-production env is NOT protected', () => {
|
|
63
|
+
const result = computeSiteIndexStatus(inputs({ environment: 'preview', seo: { siteUrl: 'https://preview.example.com' } }));
|
|
64
|
+
expect(result.status).toBe('partially_blocked');
|
|
65
|
+
expect(result.severity).toBe('warning');
|
|
66
|
+
expect(result.checks.find((c) => c.key === 'nonProdNoindex')?.status).toBe('warning');
|
|
67
|
+
});
|
|
68
|
+
it('flags a missing site URL as needs-attention', () => {
|
|
69
|
+
const result = computeSiteIndexStatus(inputs({ seo: { siteUrl: '' } }));
|
|
70
|
+
expect(result.status).toBe('unknown');
|
|
71
|
+
expect(result.severity).toBe('warning');
|
|
72
|
+
expect(result.checks.find((c) => c.key === 'siteUrl')?.status).toBe('warning');
|
|
73
|
+
});
|
|
74
|
+
it('reports partially blocked when the sitemap is disabled but the site is indexable', () => {
|
|
75
|
+
const result = computeSiteIndexStatus(inputs({ module: { ...DEFAULT_SEO_MODULE_SETTINGS, sitemapEnabled: false } }));
|
|
76
|
+
expect(result.status).toBe('partially_blocked');
|
|
77
|
+
expect(result.checks.find((c) => c.key === 'sitemap')?.status).toBe('warning');
|
|
78
|
+
});
|
|
79
|
+
it('reports unknown when no SEO config exists at all', () => {
|
|
80
|
+
const result = computeSiteIndexStatus(inputs({ hasSeoConfig: false, seo: null }));
|
|
81
|
+
expect(result.status).toBe('unknown');
|
|
82
|
+
expect(result.severity).toBe('neutral');
|
|
83
|
+
});
|
|
84
|
+
it('always exposes the three SEO actions and a full set of checks', () => {
|
|
85
|
+
const result = computeSiteIndexStatus(inputs());
|
|
86
|
+
expect(result.actions.map((a) => a.label)).toEqual([
|
|
87
|
+
'Run SEO Audit',
|
|
88
|
+
'View robots.txt',
|
|
89
|
+
'View sitemap.xml',
|
|
90
|
+
]);
|
|
91
|
+
expect(result.checks.map((c) => c.key)).toEqual([
|
|
92
|
+
'environment',
|
|
93
|
+
'siteUrl',
|
|
94
|
+
'robotsBlockAll',
|
|
95
|
+
'globalNoindex',
|
|
96
|
+
'nonProdNoindex',
|
|
97
|
+
'sitemap',
|
|
98
|
+
'lastAudit',
|
|
99
|
+
]);
|
|
100
|
+
});
|
|
101
|
+
it('surfaces the last audit date', () => {
|
|
102
|
+
const result = computeSiteIndexStatus(inputs({ lastAuditAt: '2026-01-02T03:04:05.000Z' }));
|
|
103
|
+
expect(result.checks.find((c) => c.key === 'lastAudit')?.value).toBe('2026-01-02');
|
|
104
|
+
expect(result.checks.find((c) => c.key === 'lastAudit')?.status).toBe('pass');
|
|
105
|
+
});
|
|
106
|
+
});
|
|
107
|
+
describe('getSiteIndexStatus', () => {
|
|
108
|
+
const origVercel = process.env.VERCEL_ENV;
|
|
109
|
+
const origNode = process.env.NODE_ENV;
|
|
110
|
+
afterEach(() => {
|
|
111
|
+
process.env.VERCEL_ENV = origVercel;
|
|
112
|
+
process.env.NODE_ENV = origNode;
|
|
113
|
+
stubConfig();
|
|
114
|
+
});
|
|
115
|
+
it('reads effective config + last audit from the DB', async () => {
|
|
116
|
+
process.env.VERCEL_ENV = 'production';
|
|
117
|
+
stubConfig({ siteUrl: 'https://example.com' });
|
|
118
|
+
const db = {
|
|
119
|
+
document: {
|
|
120
|
+
findFirst: async ({ where }) => where.collection === SEO_CONFIG_COLLECTION ? { data: { site: {}, module: {} } } : null,
|
|
121
|
+
},
|
|
122
|
+
seoAuditRun: {
|
|
123
|
+
findFirst: async () => ({ finishedAt: new Date('2026-02-03T00:00:00.000Z') }),
|
|
124
|
+
},
|
|
125
|
+
};
|
|
126
|
+
const result = await getSiteIndexStatus(db);
|
|
127
|
+
expect(result.status).toBe('indexable');
|
|
128
|
+
expect(result.environment).toBe('production');
|
|
129
|
+
expect(result.lastAuditAt).toBe('2026-02-03T00:00:00.000Z');
|
|
130
|
+
});
|
|
131
|
+
it('tolerates a missing audit table', async () => {
|
|
132
|
+
process.env.VERCEL_ENV = 'production';
|
|
133
|
+
stubConfig({ siteUrl: 'https://example.com' });
|
|
134
|
+
const db = { document: { findFirst: async () => null } };
|
|
135
|
+
const result = await getSiteIndexStatus(db);
|
|
136
|
+
expect(result.lastAuditAt).toBeNull();
|
|
137
|
+
expect(result.status).toBe('indexable');
|
|
138
|
+
});
|
|
139
|
+
});
|
|
140
|
+
//# sourceMappingURL=index-status.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index-status.test.js","sourceRoot":"","sources":["../../../src/__tests__/seo/index-status.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"handlers.d.ts","sourceRoot":"","sources":["../../src/api/handlers.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,aAAa,CAAA;
|
|
1
|
+
{"version":3,"file":"handlers.d.ts","sourceRoot":"","sources":["../../src/api/handlers.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,aAAa,CAAA;AA+/B5C,iFAAiF;AACjF,wBAAgB,wBAAwB,IAAI,IAAI,CAE/C;AA8JD,wBAAgB,iBAAiB,CAAC,YAAY,EAAE,MAAM,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAS9E;AAyRD,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,SAAS,GAAG,IAAI,CAwtUzD"}
|
package/dist/api/handlers.js
CHANGED
|
@@ -24,7 +24,7 @@ import { isAuthorizedCronRequest, processCleanup, processSeoScan } from '../cron
|
|
|
24
24
|
import { processContentHealthScan } from '../content-health/cron.js';
|
|
25
25
|
import { verifyCaptcha, getCaptchaConfig } from '../security/captcha.js';
|
|
26
26
|
import { listForms as listFormsService, getFormById as getFormByIdService, getFormBySlug as getFormBySlugService, createForm as createFormService, updateForm as updateFormService, duplicateForm as duplicateFormService, deleteForm as deleteFormService, saveFormSchema as saveFormSchemaService, getFormSchema as getFormSchemaService, getNotificationSettings as getFormNotificationSettingsService, updateNotificationSettings as updateFormNotificationSettingsService, setNotifyEnabled as setFormNotifyEnabledService, getEmbedSettings as getFormEmbedSettingsService, updateEmbedSettings as updateFormEmbedSettingsService, getFormStats as getFormStatsService, getFormsSidebarCounts as getFormsSidebarCountsService, FormNotFoundError, FormValidationError, FormConflictError, FormHasSubmissionsError, } from '../forms/service.js';
|
|
27
|
-
import { listEntries as listEntriesService, getEntryWithSchema as getEntryWithSchemaService, getEntryCounts as getEntryCountsService, updateEntry as updateEntryService, bulkUpdateEntries as bulkUpdateEntriesService, deleteEntry as deleteEntryService, } from '../forms/entries.js';
|
|
27
|
+
import { listEntries as listEntriesService, getEntryWithSchema as getEntryWithSchemaService, getEntryCounts as getEntryCountsService, updateEntry as updateEntryService, bulkUpdateEntries as bulkUpdateEntriesService, deleteEntry as deleteEntryService, exportFormEntries as exportFormEntriesService, } from '../forms/entries.js';
|
|
28
28
|
import { processSubmission, buildPublicForm, SubmissionValidationError, } from '../forms/submission.js';
|
|
29
29
|
import { validateSubmissionFiles, FORM_UPLOAD_ALLOWED_MIME_TYPES, DEFAULT_MAX_FILE_BYTES, } from '../forms/files.js';
|
|
30
30
|
import { resolveSubmissionFields } from '../forms/submission.js';
|
|
@@ -1102,6 +1102,27 @@ async function checkRateLimitAsync(limiter, key) {
|
|
|
1102
1102
|
function clientIp(request) {
|
|
1103
1103
|
return getClientIp(request);
|
|
1104
1104
|
}
|
|
1105
|
+
/**
|
|
1106
|
+
* Compute a before/after diff of top-level scalar (string/number/boolean) keys
|
|
1107
|
+
* between a stored record and an incoming patch. Used to audit settings changes
|
|
1108
|
+
* without ever logging nested objects (which may hold secret blobs).
|
|
1109
|
+
*/
|
|
1110
|
+
function diffScalarKeys(previous, next) {
|
|
1111
|
+
const isScalar = (v) => typeof v === 'string' || typeof v === 'number' || typeof v === 'boolean' || v === null;
|
|
1112
|
+
const changes = [];
|
|
1113
|
+
for (const key of Object.keys(next)) {
|
|
1114
|
+
const to = next[key];
|
|
1115
|
+
if (!isScalar(to))
|
|
1116
|
+
continue;
|
|
1117
|
+
const from = previous[key];
|
|
1118
|
+
if (isScalar(from) && from === to)
|
|
1119
|
+
continue;
|
|
1120
|
+
if (!isScalar(from) && from !== undefined)
|
|
1121
|
+
continue;
|
|
1122
|
+
changes.push({ key, from: isScalar(from) ? from : undefined, to });
|
|
1123
|
+
}
|
|
1124
|
+
return changes;
|
|
1125
|
+
}
|
|
1105
1126
|
const MAX_CONCURRENT_SESSIONS = 5;
|
|
1106
1127
|
/**
|
|
1107
1128
|
* After a successful primary-credential check, prune the user's active sessions
|
|
@@ -4432,6 +4453,41 @@ export function registerCMSRoutes(router) {
|
|
|
4432
4453
|
return internalError(err);
|
|
4433
4454
|
}
|
|
4434
4455
|
});
|
|
4456
|
+
// Defined before `/forms/entries/:entryId` so "export" is not parsed as an id.
|
|
4457
|
+
router.get('/forms/entries/export', async (request) => {
|
|
4458
|
+
try {
|
|
4459
|
+
const auth = await requireAuth(request);
|
|
4460
|
+
if (auth.error)
|
|
4461
|
+
return auth.error;
|
|
4462
|
+
const roleErr = requireRole(auth.session.role, WRITE_ROLES);
|
|
4463
|
+
if (roleErr)
|
|
4464
|
+
return roleErr;
|
|
4465
|
+
const formId = new URL(request.url).searchParams.get('formId');
|
|
4466
|
+
if (!formId)
|
|
4467
|
+
return errorResponse('"formId" query parameter is required', 400);
|
|
4468
|
+
const result = await exportFormEntriesService(formId);
|
|
4469
|
+
if (!result)
|
|
4470
|
+
return errorResponse('Form not found', 404);
|
|
4471
|
+
// PII access audit: a bulk export of decrypted submission data.
|
|
4472
|
+
void logEvent({
|
|
4473
|
+
event: 'form.entries.exported',
|
|
4474
|
+
userId: auth.session.userId,
|
|
4475
|
+
ipAddress: getClientIp(request),
|
|
4476
|
+
details: { formId, count: result.count },
|
|
4477
|
+
});
|
|
4478
|
+
const filename = `${result.formSlug || 'form'}-entries.csv`;
|
|
4479
|
+
return new Response(result.csv, {
|
|
4480
|
+
status: 200,
|
|
4481
|
+
headers: {
|
|
4482
|
+
'Content-Type': 'text/csv; charset=utf-8',
|
|
4483
|
+
'Content-Disposition': `attachment; filename="${filename}"`,
|
|
4484
|
+
},
|
|
4485
|
+
});
|
|
4486
|
+
}
|
|
4487
|
+
catch (err) {
|
|
4488
|
+
return internalError(err);
|
|
4489
|
+
}
|
|
4490
|
+
});
|
|
4435
4491
|
router.get('/forms/entries/:entryId', async (request, params) => {
|
|
4436
4492
|
try {
|
|
4437
4493
|
const auth = await requireAuth(request);
|
|
@@ -4443,6 +4499,13 @@ export function registerCMSRoutes(router) {
|
|
|
4443
4499
|
const result = await getEntryWithSchemaService(params.entryId);
|
|
4444
4500
|
if (!result)
|
|
4445
4501
|
return errorResponse('Entry not found', 404);
|
|
4502
|
+
// PII access audit: viewing a single entry exposes its decrypted fields.
|
|
4503
|
+
void logEvent({
|
|
4504
|
+
event: 'form.entry.viewed',
|
|
4505
|
+
userId: auth.session.userId,
|
|
4506
|
+
ipAddress: getClientIp(request),
|
|
4507
|
+
details: { entryId: params.entryId, formId: result.entry.formId },
|
|
4508
|
+
});
|
|
4446
4509
|
return json({ data: result });
|
|
4447
4510
|
}
|
|
4448
4511
|
catch (err) {
|
|
@@ -6844,20 +6907,18 @@ export function registerCMSRoutes(router) {
|
|
|
6844
6907
|
return accessErr;
|
|
6845
6908
|
const { generateMetaTags } = await import('../seo/meta-tags.js');
|
|
6846
6909
|
const { resolveRobotsDirectives } = await import('../seo/robots.js');
|
|
6910
|
+
const { getSeoOverrides, applySeoOverrides } = await import('../seo/config-store.js');
|
|
6847
6911
|
const data = doc.data || {};
|
|
6848
|
-
|
|
6849
|
-
|
|
6850
|
-
|
|
6851
|
-
|
|
6852
|
-
const settingsData = settingsGlobal?.data && typeof settingsGlobal.data === 'object'
|
|
6853
|
-
? settingsGlobal.data
|
|
6854
|
-
: {};
|
|
6912
|
+
// Read robots defaults from the SAME effective SEO config the public
|
|
6913
|
+
// renderer (`composePageMeta`) and General Settings use — never the
|
|
6914
|
+
// legacy `settings` global — so this preview can't drift from reality.
|
|
6915
|
+
const effectiveSeo = applySeoOverrides(getActuateConfig(), await getSeoOverrides(db()))?.seo;
|
|
6855
6916
|
const robots = resolveRobotsDirectives({
|
|
6856
6917
|
pageData: data,
|
|
6857
6918
|
settings: {
|
|
6858
|
-
defaultNoIndex:
|
|
6859
|
-
defaultNoFollow:
|
|
6860
|
-
noIndexNonProduction:
|
|
6919
|
+
defaultNoIndex: effectiveSeo?.robots?.defaultNoIndex,
|
|
6920
|
+
defaultNoFollow: effectiveSeo?.robots?.defaultNoFollow,
|
|
6921
|
+
noIndexNonProduction: effectiveSeo?.robots?.noIndexNonProduction,
|
|
6861
6922
|
},
|
|
6862
6923
|
environment: process.env.VERCEL_ENV ?? process.env.NODE_ENV,
|
|
6863
6924
|
});
|
|
@@ -7096,6 +7157,25 @@ export function registerCMSRoutes(router) {
|
|
|
7096
7157
|
return internalError(err, 'seo/config PUT');
|
|
7097
7158
|
}
|
|
7098
7159
|
});
|
|
7160
|
+
// Effective, computed crawl/index status for the General Settings card.
|
|
7161
|
+
// Reads the SAME effective SEO config the public renderer uses, so the badge
|
|
7162
|
+
// shown to editors never drifts from what search engines actually see.
|
|
7163
|
+
router.get('/seo/index-status', async (request) => {
|
|
7164
|
+
try {
|
|
7165
|
+
const auth = await requireAuth(request);
|
|
7166
|
+
if (auth.error)
|
|
7167
|
+
return auth.error;
|
|
7168
|
+
const roleErr = requireRole(auth.session.role, ADMIN_ROLES);
|
|
7169
|
+
if (roleErr)
|
|
7170
|
+
return roleErr;
|
|
7171
|
+
const { getSiteIndexStatus } = await import('../seo/index-status.js');
|
|
7172
|
+
const status = await getSiteIndexStatus(db());
|
|
7173
|
+
return json({ data: status });
|
|
7174
|
+
}
|
|
7175
|
+
catch (err) {
|
|
7176
|
+
return internalError(err, 'seo/index-status GET');
|
|
7177
|
+
}
|
|
7178
|
+
});
|
|
7099
7179
|
// ---------------------------------------------------------------------------
|
|
7100
7180
|
// Technical SEO — sitemap status, crawl settings, robots.txt editor.
|
|
7101
7181
|
// All backed by the `module` block of the SEO overrides document.
|
|
@@ -8721,7 +8801,11 @@ export function registerCMSRoutes(router) {
|
|
|
8721
8801
|
if (!isAuthorizedCronRequest(request.headers.get('authorization'))) {
|
|
8722
8802
|
return errorResponse('Unauthorized', 401);
|
|
8723
8803
|
}
|
|
8724
|
-
const
|
|
8804
|
+
const retentionDays = getActuateConfig()?.forms?.retentionDays;
|
|
8805
|
+
const formSubmissionRetentionMs = typeof retentionDays === 'number' && retentionDays > 0
|
|
8806
|
+
? retentionDays * 24 * 60 * 60 * 1000
|
|
8807
|
+
: 0;
|
|
8808
|
+
const result = await processCleanup(db(), { formSubmissionRetentionMs });
|
|
8725
8809
|
return json({ data: result });
|
|
8726
8810
|
}
|
|
8727
8811
|
catch (err) {
|
|
@@ -8854,7 +8938,30 @@ export function registerCMSRoutes(router) {
|
|
|
8854
8938
|
}
|
|
8855
8939
|
const body = (await request.json());
|
|
8856
8940
|
const ctx = buildActionContext(auth.session, db());
|
|
8941
|
+
const previous = await getGlobal(params.slug, ctx).catch(() => null);
|
|
8857
8942
|
const global = await updateGlobal(params.slug, body, ctx);
|
|
8943
|
+
// Audit settings changes (title/tagline/URL/locale/timezone/etc.) with a
|
|
8944
|
+
// per-key before/after diff so the audit trail records what changed and
|
|
8945
|
+
// who changed it. Scalar values only — we never log nested secret blobs.
|
|
8946
|
+
try {
|
|
8947
|
+
const changes = diffScalarKeys(previous ?? {}, body);
|
|
8948
|
+
if (changes.length > 0) {
|
|
8949
|
+
void logEvent({
|
|
8950
|
+
event: 'settings_changed',
|
|
8951
|
+
userId: auth.session.userId,
|
|
8952
|
+
ipAddress: getClientIp(request),
|
|
8953
|
+
details: {
|
|
8954
|
+
global: params.slug,
|
|
8955
|
+
source: 'database',
|
|
8956
|
+
environment: process.env.VERCEL_ENV ?? process.env.NODE_ENV ?? null,
|
|
8957
|
+
changes,
|
|
8958
|
+
},
|
|
8959
|
+
});
|
|
8960
|
+
}
|
|
8961
|
+
}
|
|
8962
|
+
catch {
|
|
8963
|
+
// Audit failures must never block the write.
|
|
8964
|
+
}
|
|
8858
8965
|
return json({ data: global });
|
|
8859
8966
|
}
|
|
8860
8967
|
catch (err) {
|