@forumone/throughline-publishing 0.0.1 → 0.2.1
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 +13 -0
- package/LICENSE +21 -0
- package/README.md +2 -42
- package/dist/checks/alt-text.d.ts +11 -0
- package/dist/checks/alt-text.d.ts.map +1 -0
- package/dist/checks/alt-text.js +53 -0
- package/dist/checks/alt-text.js.map +1 -0
- package/dist/checks/heading-hierarchy.d.ts +11 -0
- package/dist/checks/heading-hierarchy.d.ts.map +1 -0
- package/dist/checks/heading-hierarchy.js +32 -0
- package/dist/checks/heading-hierarchy.js.map +1 -0
- package/dist/checks/index.d.ts +6 -0
- package/dist/checks/index.d.ts.map +1 -0
- package/dist/checks/index.js +13 -0
- package/dist/checks/index.js.map +1 -0
- package/dist/checks/link-labels.d.ts +9 -0
- package/dist/checks/link-labels.d.ts.map +1 -0
- package/dist/checks/link-labels.js +44 -0
- package/dist/checks/link-labels.js.map +1 -0
- package/dist/hooks/block-status-writes.d.ts +12 -0
- package/dist/hooks/block-status-writes.d.ts.map +1 -0
- package/dist/hooks/block-status-writes.js +36 -0
- package/dist/hooks/block-status-writes.js.map +1 -0
- package/dist/index.d.ts +4 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +2 -0
- package/dist/index.js.map +1 -0
- package/dist/options.d.ts +65 -0
- package/dist/options.d.ts.map +1 -0
- package/dist/options.js +57 -0
- package/dist/options.js.map +1 -0
- package/dist/pipeline/index.d.ts +15 -0
- package/dist/pipeline/index.d.ts.map +1 -0
- package/dist/pipeline/index.js +62 -0
- package/dist/pipeline/index.js.map +1 -0
- package/dist/pipeline/steps/accessibility.d.ts +9 -0
- package/dist/pipeline/steps/accessibility.d.ts.map +1 -0
- package/dist/pipeline/steps/accessibility.js +32 -0
- package/dist/pipeline/steps/accessibility.js.map +1 -0
- package/dist/pipeline/steps/approval.d.ts +21 -0
- package/dist/pipeline/steps/approval.d.ts.map +1 -0
- package/dist/pipeline/steps/approval.js +48 -0
- package/dist/pipeline/steps/approval.js.map +1 -0
- package/dist/pipeline/steps/composition.d.ts +14 -0
- package/dist/pipeline/steps/composition.d.ts.map +1 -0
- package/dist/pipeline/steps/composition.js +63 -0
- package/dist/pipeline/steps/composition.js.map +1 -0
- package/dist/pipeline/steps/embargo.d.ts +12 -0
- package/dist/pipeline/steps/embargo.d.ts.map +1 -0
- package/dist/pipeline/steps/embargo.js +41 -0
- package/dist/pipeline/steps/embargo.js.map +1 -0
- package/dist/pipeline/steps/execute.d.ts +12 -0
- package/dist/pipeline/steps/execute.d.ts.map +1 -0
- package/dist/pipeline/steps/execute.js +38 -0
- package/dist/pipeline/steps/execute.js.map +1 -0
- package/dist/pipeline/steps/exist.d.ts +9 -0
- package/dist/pipeline/steps/exist.d.ts.map +1 -0
- package/dist/pipeline/steps/exist.js +31 -0
- package/dist/pipeline/steps/exist.js.map +1 -0
- package/dist/pipeline/steps/required-fields.d.ts +9 -0
- package/dist/pipeline/steps/required-fields.d.ts.map +1 -0
- package/dist/pipeline/steps/required-fields.js +63 -0
- package/dist/pipeline/steps/required-fields.js.map +1 -0
- package/dist/pipeline/types.d.ts +45 -0
- package/dist/pipeline/types.d.ts.map +1 -0
- package/dist/pipeline/types.js +2 -0
- package/dist/pipeline/types.js.map +1 -0
- package/dist/plugin.d.ts +4 -0
- package/dist/plugin.d.ts.map +1 -0
- package/dist/plugin.js +87 -0
- package/dist/plugin.js.map +1 -0
- package/dist/tools/get-publish-status.d.ts +9 -0
- package/dist/tools/get-publish-status.d.ts.map +1 -0
- package/dist/tools/get-publish-status.js +55 -0
- package/dist/tools/get-publish-status.js.map +1 -0
- package/dist/tools/index.d.ts +6 -0
- package/dist/tools/index.d.ts.map +1 -0
- package/dist/tools/index.js +6 -0
- package/dist/tools/index.js.map +1 -0
- package/dist/tools/publish.d.ts +11 -0
- package/dist/tools/publish.d.ts.map +1 -0
- package/dist/tools/publish.js +71 -0
- package/dist/tools/publish.js.map +1 -0
- package/dist/tools/rollback.d.ts +11 -0
- package/dist/tools/rollback.d.ts.map +1 -0
- package/dist/tools/rollback.js +78 -0
- package/dist/tools/rollback.js.map +1 -0
- package/dist/tools/schedule-publish.d.ts +11 -0
- package/dist/tools/schedule-publish.d.ts.map +1 -0
- package/dist/tools/schedule-publish.js +94 -0
- package/dist/tools/schedule-publish.js.map +1 -0
- package/dist/tools/unpublish.d.ts +11 -0
- package/dist/tools/unpublish.d.ts.map +1 -0
- package/dist/tools/unpublish.js +61 -0
- package/dist/tools/unpublish.js.map +1 -0
- package/package.json +66 -7
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { Payload } from 'payload';
|
|
2
|
+
import type { McpToolDefinition } from '@forumone/throughline-plugin-contract';
|
|
3
|
+
import { type PublishingPluginOptions } from '../options.js';
|
|
4
|
+
export interface GetPublishStatusToolDeps {
|
|
5
|
+
payload: Payload;
|
|
6
|
+
options: PublishingPluginOptions;
|
|
7
|
+
}
|
|
8
|
+
export declare function createGetPublishStatusTool(deps: GetPublishStatusToolDeps): McpToolDefinition;
|
|
9
|
+
//# sourceMappingURL=get-publish-status.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"get-publish-status.d.ts","sourceRoot":"","sources":["../../src/tools/get-publish-status.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,SAAS,CAAA;AAEtC,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,uCAAuC,CAAA;AAC9E,OAAO,EAAE,KAAK,uBAAuB,EAAqB,MAAM,eAAe,CAAA;AAG/E,MAAM,WAAW,wBAAwB;IACvC,OAAO,EAAE,OAAO,CAAA;IAChB,OAAO,EAAE,uBAAuB,CAAA;CACjC;AAED,wBAAgB,0BAA0B,CAAC,IAAI,EAAE,wBAAwB,GAAG,iBAAiB,CAuD5F"}
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
import { withMeta } from '@forumone/throughline-core';
|
|
3
|
+
import { resolveCollection } from '../options.js';
|
|
4
|
+
import { runPreflightPipeline } from '../pipeline/index.js';
|
|
5
|
+
export function createGetPublishStatusTool(deps) {
|
|
6
|
+
const inputSchema = withMeta({
|
|
7
|
+
collection: z.string(),
|
|
8
|
+
id: z.string(),
|
|
9
|
+
});
|
|
10
|
+
return {
|
|
11
|
+
name: 'get_publish_status',
|
|
12
|
+
description: "Returns the current publishability of a document without actually publishing. Reports current status, whether unpublished changes exist, the last publish timestamp, and a preflight result indicating whether `publish` would currently succeed. Read-only; no audit record is written.",
|
|
13
|
+
inputSchema,
|
|
14
|
+
handler: async (input, ctx) => {
|
|
15
|
+
const collection = resolveCollection(deps.options, input.collection);
|
|
16
|
+
const document = (await deps.payload.findByID({
|
|
17
|
+
collection: collection.slug,
|
|
18
|
+
id: input.id,
|
|
19
|
+
draft: true,
|
|
20
|
+
}));
|
|
21
|
+
const preflight = await runPreflightPipeline({
|
|
22
|
+
payload: deps.payload,
|
|
23
|
+
inngest: deps.options.inngest,
|
|
24
|
+
options: deps.options,
|
|
25
|
+
collection,
|
|
26
|
+
document,
|
|
27
|
+
documentId: input.id,
|
|
28
|
+
actor: { user: ctx.user, apiKeyName: ctx.apiKeyName },
|
|
29
|
+
});
|
|
30
|
+
const updatedAt = document['updatedAt'];
|
|
31
|
+
const publishedAt = document[collection.publishedAtField];
|
|
32
|
+
const hasUnpublishedChanges = typeof updatedAt === 'string' &&
|
|
33
|
+
typeof publishedAt === 'string' &&
|
|
34
|
+
Date.parse(updatedAt) > Date.parse(publishedAt);
|
|
35
|
+
return {
|
|
36
|
+
currentStatus: document['_status'] ?? 'draft',
|
|
37
|
+
hasUnpublishedChanges,
|
|
38
|
+
lastPublished: typeof publishedAt === 'string' ? publishedAt : null,
|
|
39
|
+
wouldPublish: {
|
|
40
|
+
canPublish: preflight.success,
|
|
41
|
+
...(preflight.success
|
|
42
|
+
? {}
|
|
43
|
+
: {
|
|
44
|
+
blockedAt: preflight.failedAt,
|
|
45
|
+
code: preflight.code,
|
|
46
|
+
reason: preflight.reason,
|
|
47
|
+
suggestion: preflight.suggestion,
|
|
48
|
+
issues: preflight.issues ?? [],
|
|
49
|
+
}),
|
|
50
|
+
},
|
|
51
|
+
};
|
|
52
|
+
},
|
|
53
|
+
};
|
|
54
|
+
}
|
|
55
|
+
//# sourceMappingURL=get-publish-status.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"get-publish-status.js","sourceRoot":"","sources":["../../src/tools/get-publish-status.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAA;AAEvB,OAAO,EAAE,QAAQ,EAAE,MAAM,4BAA4B,CAAA;AAErD,OAAO,EAAgC,iBAAiB,EAAE,MAAM,eAAe,CAAA;AAC/E,OAAO,EAAE,oBAAoB,EAAE,MAAM,sBAAsB,CAAA;AAO3D,MAAM,UAAU,0BAA0B,CAAC,IAA8B;IACvE,MAAM,WAAW,GAAG,QAAQ,CAAC;QAC3B,UAAU,EAAE,CAAC,CAAC,MAAM,EAAE;QACtB,EAAE,EAAE,CAAC,CAAC,MAAM,EAAE;KACf,CAAC,CAAA;IAEF,OAAO;QACL,IAAI,EAAE,oBAAoB;QAC1B,WAAW,EACT,0RAA0R;QAC5R,WAAW;QACX,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,GAAG,EAAE,EAAE;YAC5B,MAAM,UAAU,GAAG,iBAAiB,CAAC,IAAI,CAAC,OAAO,EAAE,KAAK,CAAC,UAAU,CAAC,CAAA;YACpE,MAAM,QAAQ,GAAG,CAAC,MAAM,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC;gBAC5C,UAAU,EAAE,UAAU,CAAC,IAAI;gBAC3B,EAAE,EAAE,KAAK,CAAC,EAAE;gBACZ,KAAK,EAAE,IAAI;aACZ,CAAC,CAA4B,CAAA;YAE9B,MAAM,SAAS,GAAG,MAAM,oBAAoB,CAAC;gBAC3C,OAAO,EAAE,IAAI,CAAC,OAAO;gBACrB,OAAO,EAAE,IAAI,CAAC,OAAO,CAAC,OAAO;gBAC7B,OAAO,EAAE,IAAI,CAAC,OAAO;gBACrB,UAAU;gBACV,QAAQ;gBACR,UAAU,EAAE,KAAK,CAAC,EAAE;gBACpB,KAAK,EAAE,EAAE,IAAI,EAAE,GAAG,CAAC,IAAI,EAAE,UAAU,EAAE,GAAG,CAAC,UAAU,EAAE;aACtD,CAAC,CAAA;YAEF,MAAM,SAAS,GAAG,QAAQ,CAAC,WAAW,CAAC,CAAA;YACvC,MAAM,WAAW,GAAG,QAAQ,CAAC,UAAU,CAAC,gBAAgB,CAAC,CAAA;YACzD,MAAM,qBAAqB,GACzB,OAAO,SAAS,KAAK,QAAQ;gBAC7B,OAAO,WAAW,KAAK,QAAQ;gBAC/B,IAAI,CAAC,KAAK,CAAC,SAAS,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC,WAAW,CAAC,CAAA;YAEjD,OAAO;gBACL,aAAa,EAAE,QAAQ,CAAC,SAAS,CAAC,IAAI,OAAO;gBAC7C,qBAAqB;gBACrB,aAAa,EAAE,OAAO,WAAW,KAAK,QAAQ,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,IAAI;gBACnE,YAAY,EAAE;oBACZ,UAAU,EAAE,SAAS,CAAC,OAAO;oBAC7B,GAAG,CAAC,SAAS,CAAC,OAAO;wBACnB,CAAC,CAAC,EAAE;wBACJ,CAAC,CAAC;4BACE,SAAS,EAAE,SAAS,CAAC,QAAQ;4BAC7B,IAAI,EAAE,SAAS,CAAC,IAAI;4BACpB,MAAM,EAAE,SAAS,CAAC,MAAM;4BACxB,UAAU,EAAE,SAAS,CAAC,UAAU;4BAChC,MAAM,EAAE,SAAS,CAAC,MAAM,IAAI,EAAE;yBAC/B,CAAC;iBACP;aACF,CAAA;QACH,CAAC;KACF,CAAA;AACH,CAAC"}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
export { createPublishTool, type PublishToolDeps } from './publish.js';
|
|
2
|
+
export { createUnpublishTool, type UnpublishToolDeps } from './unpublish.js';
|
|
3
|
+
export { createSchedulePublishTool, type SchedulePublishToolDeps, } from './schedule-publish.js';
|
|
4
|
+
export { createGetPublishStatusTool, type GetPublishStatusToolDeps, } from './get-publish-status.js';
|
|
5
|
+
export { createRollbackTool, type RollbackToolDeps } from './rollback.js';
|
|
6
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/tools/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAE,KAAK,eAAe,EAAE,MAAM,cAAc,CAAA;AACtE,OAAO,EAAE,mBAAmB,EAAE,KAAK,iBAAiB,EAAE,MAAM,gBAAgB,CAAA;AAC5E,OAAO,EACL,yBAAyB,EACzB,KAAK,uBAAuB,GAC7B,MAAM,uBAAuB,CAAA;AAC9B,OAAO,EACL,0BAA0B,EAC1B,KAAK,wBAAwB,GAC9B,MAAM,yBAAyB,CAAA;AAChC,OAAO,EAAE,kBAAkB,EAAE,KAAK,gBAAgB,EAAE,MAAM,eAAe,CAAA"}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
export { createPublishTool } from './publish.js';
|
|
2
|
+
export { createUnpublishTool } from './unpublish.js';
|
|
3
|
+
export { createSchedulePublishTool, } from './schedule-publish.js';
|
|
4
|
+
export { createGetPublishStatusTool, } from './get-publish-status.js';
|
|
5
|
+
export { createRollbackTool } from './rollback.js';
|
|
6
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/tools/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAwB,MAAM,cAAc,CAAA;AACtE,OAAO,EAAE,mBAAmB,EAA0B,MAAM,gBAAgB,CAAA;AAC5E,OAAO,EACL,yBAAyB,GAE1B,MAAM,uBAAuB,CAAA;AAC9B,OAAO,EACL,0BAA0B,GAE3B,MAAM,yBAAyB,CAAA;AAChC,OAAO,EAAE,kBAAkB,EAAyB,MAAM,eAAe,CAAA"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { Payload } from 'payload';
|
|
2
|
+
import { type AuditWriter } from '@forumone/throughline-core';
|
|
3
|
+
import type { McpToolDefinition } from '@forumone/throughline-plugin-contract';
|
|
4
|
+
import { type PublishingPluginOptions } from '../options.js';
|
|
5
|
+
export interface PublishToolDeps {
|
|
6
|
+
payload: Payload;
|
|
7
|
+
options: PublishingPluginOptions;
|
|
8
|
+
auditWriter: AuditWriter;
|
|
9
|
+
}
|
|
10
|
+
export declare function createPublishTool(deps: PublishToolDeps): McpToolDefinition;
|
|
11
|
+
//# sourceMappingURL=publish.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"publish.d.ts","sourceRoot":"","sources":["../../src/tools/publish.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,SAAS,CAAA;AACtC,OAAO,EAAE,KAAK,WAAW,EAAY,MAAM,4BAA4B,CAAA;AACvE,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,uCAAuC,CAAA;AAC9E,OAAO,EAAE,KAAK,uBAAuB,EAAqB,MAAM,eAAe,CAAA;AAG/E,MAAM,WAAW,eAAe;IAC9B,OAAO,EAAE,OAAO,CAAA;IAChB,OAAO,EAAE,uBAAuB,CAAA;IAChC,WAAW,EAAE,WAAW,CAAA;CACzB;AAED,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,eAAe,GAAG,iBAAiB,CAkE1E"}
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
import { withMeta } from '@forumone/throughline-core';
|
|
3
|
+
import { resolveCollection } from '../options.js';
|
|
4
|
+
import { runPublishPipeline } from '../pipeline/index.js';
|
|
5
|
+
export function createPublishTool(deps) {
|
|
6
|
+
const inputSchema = withMeta({
|
|
7
|
+
collection: z.string().describe('The collection slug (e.g. "pages")'),
|
|
8
|
+
id: z.string().describe('The document ID'),
|
|
9
|
+
});
|
|
10
|
+
return {
|
|
11
|
+
name: 'publish',
|
|
12
|
+
description: "Publishes a draft document. Runs the full publish pipeline: composition, accessibility, required-field, embargo, and approval checks. Returns success with the publish timestamp, or a specific failedAt step with reason / suggestion when something blocks the publish.",
|
|
13
|
+
inputSchema,
|
|
14
|
+
handler: async (input, ctx) => {
|
|
15
|
+
const collection = resolveCollection(deps.options, input.collection);
|
|
16
|
+
const document = (await deps.payload.findByID({
|
|
17
|
+
collection: collection.slug,
|
|
18
|
+
id: input.id,
|
|
19
|
+
draft: true,
|
|
20
|
+
}));
|
|
21
|
+
const result = await runPublishPipeline({
|
|
22
|
+
payload: deps.payload,
|
|
23
|
+
inngest: deps.options.inngest,
|
|
24
|
+
options: deps.options,
|
|
25
|
+
collection,
|
|
26
|
+
document,
|
|
27
|
+
documentId: input.id,
|
|
28
|
+
actor: { user: ctx.user, apiKeyName: ctx.apiKeyName },
|
|
29
|
+
...(input._meta ? { meta: input._meta } : {}),
|
|
30
|
+
});
|
|
31
|
+
await deps.auditWriter({
|
|
32
|
+
actor: {
|
|
33
|
+
type: ctx.user ? 'user' : 'system',
|
|
34
|
+
userId: ctx.user?.id,
|
|
35
|
+
userName: ctx.user?.name,
|
|
36
|
+
apiKeyName: ctx.apiKeyName,
|
|
37
|
+
},
|
|
38
|
+
action: 'publishing.publish',
|
|
39
|
+
mcpServer: 'publishing',
|
|
40
|
+
mcpTool: 'publish',
|
|
41
|
+
targetCollection: input.collection,
|
|
42
|
+
targetId: input.id,
|
|
43
|
+
targetTitle: stringField(document, 'title') ?? input.id,
|
|
44
|
+
prompt: input._meta?.userPrompt,
|
|
45
|
+
reasoning: input._meta?.reasoning,
|
|
46
|
+
changesSummary: input._meta?.changesSummary,
|
|
47
|
+
success: result.success,
|
|
48
|
+
errorMessage: result.success ? undefined : result.reason,
|
|
49
|
+
});
|
|
50
|
+
if (result.success) {
|
|
51
|
+
return {
|
|
52
|
+
published: true,
|
|
53
|
+
publishedAt: result.publishedAt,
|
|
54
|
+
};
|
|
55
|
+
}
|
|
56
|
+
return {
|
|
57
|
+
published: false,
|
|
58
|
+
failedAt: result.failedAt,
|
|
59
|
+
reason: result.reason,
|
|
60
|
+
code: result.code,
|
|
61
|
+
issues: result.issues,
|
|
62
|
+
suggestion: result.suggestion,
|
|
63
|
+
};
|
|
64
|
+
},
|
|
65
|
+
};
|
|
66
|
+
}
|
|
67
|
+
function stringField(doc, name) {
|
|
68
|
+
const value = doc[name];
|
|
69
|
+
return typeof value === 'string' ? value : undefined;
|
|
70
|
+
}
|
|
71
|
+
//# sourceMappingURL=publish.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"publish.js","sourceRoot":"","sources":["../../src/tools/publish.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { Payload } from 'payload';
|
|
2
|
+
import { type AuditWriter } from '@forumone/throughline-core';
|
|
3
|
+
import type { McpToolDefinition } from '@forumone/throughline-plugin-contract';
|
|
4
|
+
import { type PublishingPluginOptions } from '../options.js';
|
|
5
|
+
export interface RollbackToolDeps {
|
|
6
|
+
payload: Payload;
|
|
7
|
+
options: PublishingPluginOptions;
|
|
8
|
+
auditWriter: AuditWriter;
|
|
9
|
+
}
|
|
10
|
+
export declare function createRollbackTool(deps: RollbackToolDeps): McpToolDefinition;
|
|
11
|
+
//# sourceMappingURL=rollback.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"rollback.d.ts","sourceRoot":"","sources":["../../src/tools/rollback.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,SAAS,CAAA;AACtC,OAAO,EAAE,KAAK,WAAW,EAAY,MAAM,4BAA4B,CAAA;AACvE,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,uCAAuC,CAAA;AAC9E,OAAO,EAAE,KAAK,uBAAuB,EAAqB,MAAM,eAAe,CAAA;AAE/E,MAAM,WAAW,gBAAgB;IAC/B,OAAO,EAAE,OAAO,CAAA;IAChB,OAAO,EAAE,uBAAuB,CAAA;IAChC,WAAW,EAAE,WAAW,CAAA;CACzB;AAED,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,gBAAgB,GAAG,iBAAiB,CAiF5E"}
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
import { withMeta } from '@forumone/throughline-core';
|
|
3
|
+
import { resolveCollection } from '../options.js';
|
|
4
|
+
export function createRollbackTool(deps) {
|
|
5
|
+
const inputSchema = withMeta({
|
|
6
|
+
collection: z.string(),
|
|
7
|
+
id: z.string().describe('The document ID'),
|
|
8
|
+
versionId: z.string().describe('The version ID to roll the document back to'),
|
|
9
|
+
});
|
|
10
|
+
return {
|
|
11
|
+
name: 'rollback',
|
|
12
|
+
description: "Rolls a document back to a prior version from Payload's version history. The restored content lands as a fresh draft; call `publish` afterwards if you want it live again. Audits the rollback under publishing.rollback.",
|
|
13
|
+
inputSchema,
|
|
14
|
+
handler: async (input, ctx) => {
|
|
15
|
+
const collection = resolveCollection(deps.options, input.collection);
|
|
16
|
+
// Confirm the version belongs to this document before restoring.
|
|
17
|
+
const versions = await deps.payload.findVersions({
|
|
18
|
+
collection: collection.slug,
|
|
19
|
+
where: {
|
|
20
|
+
and: [{ id: { equals: input.versionId } }, { parent: { equals: input.id } }],
|
|
21
|
+
},
|
|
22
|
+
limit: 1,
|
|
23
|
+
});
|
|
24
|
+
if (!versions.docs[0]) {
|
|
25
|
+
await deps.auditWriter({
|
|
26
|
+
actor: { type: ctx.user ? 'user' : 'system', userId: ctx.user?.id, apiKeyName: ctx.apiKeyName },
|
|
27
|
+
action: 'publishing.rollback',
|
|
28
|
+
mcpServer: 'publishing',
|
|
29
|
+
mcpTool: 'rollback',
|
|
30
|
+
targetCollection: input.collection,
|
|
31
|
+
targetId: input.id,
|
|
32
|
+
success: false,
|
|
33
|
+
errorMessage: 'Version not found for the supplied document',
|
|
34
|
+
});
|
|
35
|
+
return {
|
|
36
|
+
restored: false,
|
|
37
|
+
reason: `Version "${input.versionId}" not found for document "${input.id}" in "${input.collection}"`,
|
|
38
|
+
};
|
|
39
|
+
}
|
|
40
|
+
await deps.payload.restoreVersion({
|
|
41
|
+
collection: collection.slug,
|
|
42
|
+
id: input.versionId,
|
|
43
|
+
});
|
|
44
|
+
await deps.options.inngest.send({
|
|
45
|
+
name: 'content/page.rolled_back',
|
|
46
|
+
data: {
|
|
47
|
+
collection: collection.slug,
|
|
48
|
+
id: input.id,
|
|
49
|
+
rolledBackBy: ctx.user?.id ?? 'system',
|
|
50
|
+
toVersionId: input.versionId,
|
|
51
|
+
},
|
|
52
|
+
});
|
|
53
|
+
await deps.auditWriter({
|
|
54
|
+
actor: {
|
|
55
|
+
type: ctx.user ? 'user' : 'system',
|
|
56
|
+
userId: ctx.user?.id,
|
|
57
|
+
userName: ctx.user?.name,
|
|
58
|
+
apiKeyName: ctx.apiKeyName,
|
|
59
|
+
},
|
|
60
|
+
action: 'publishing.rollback',
|
|
61
|
+
mcpServer: 'publishing',
|
|
62
|
+
mcpTool: 'rollback',
|
|
63
|
+
targetCollection: input.collection,
|
|
64
|
+
targetId: input.id,
|
|
65
|
+
prompt: input._meta?.userPrompt,
|
|
66
|
+
reasoning: input._meta?.reasoning,
|
|
67
|
+
changesSummary: `Rolled back to version ${input.versionId}`,
|
|
68
|
+
success: true,
|
|
69
|
+
});
|
|
70
|
+
return {
|
|
71
|
+
restored: true,
|
|
72
|
+
toVersionId: input.versionId,
|
|
73
|
+
note: 'The restored content is a draft. Call `publish` to make it live.',
|
|
74
|
+
};
|
|
75
|
+
},
|
|
76
|
+
};
|
|
77
|
+
}
|
|
78
|
+
//# sourceMappingURL=rollback.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"rollback.js","sourceRoot":"","sources":["../../src/tools/rollback.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAA;AAEvB,OAAO,EAAoB,QAAQ,EAAE,MAAM,4BAA4B,CAAA;AAEvE,OAAO,EAAgC,iBAAiB,EAAE,MAAM,eAAe,CAAA;AAQ/E,MAAM,UAAU,kBAAkB,CAAC,IAAsB;IACvD,MAAM,WAAW,GAAG,QAAQ,CAAC;QAC3B,UAAU,EAAE,CAAC,CAAC,MAAM,EAAE;QACtB,EAAE,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,iBAAiB,CAAC;QAC1C,SAAS,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,6CAA6C,CAAC;KAC9E,CAAC,CAAA;IAEF,OAAO;QACL,IAAI,EAAE,UAAU;QAChB,WAAW,EACT,2NAA2N;QAC7N,WAAW;QACX,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,GAAG,EAAE,EAAE;YAC5B,MAAM,UAAU,GAAG,iBAAiB,CAAC,IAAI,CAAC,OAAO,EAAE,KAAK,CAAC,UAAU,CAAC,CAAA;YAEpE,iEAAiE;YACjE,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,OAAO,CAAC,YAAY,CAAC;gBAC/C,UAAU,EAAE,UAAU,CAAC,IAAI;gBAC3B,KAAK,EAAE;oBACL,GAAG,EAAE,CAAC,EAAE,EAAE,EAAE,EAAE,MAAM,EAAE,KAAK,CAAC,SAAS,EAAE,EAAE,EAAE,EAAE,MAAM,EAAE,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,EAAE,EAAE,CAAC;iBAC7E;gBACD,KAAK,EAAE,CAAC;aACT,CAAC,CAAA;YAEF,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC;gBACtB,MAAM,IAAI,CAAC,WAAW,CAAC;oBACrB,KAAK,EAAE,EAAE,IAAI,EAAE,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,QAAQ,EAAE,MAAM,EAAE,GAAG,CAAC,IAAI,EAAE,EAAE,EAAE,UAAU,EAAE,GAAG,CAAC,UAAU,EAAE;oBAC/F,MAAM,EAAE,qBAAqB;oBAC7B,SAAS,EAAE,YAAY;oBACvB,OAAO,EAAE,UAAU;oBACnB,gBAAgB,EAAE,KAAK,CAAC,UAAU;oBAClC,QAAQ,EAAE,KAAK,CAAC,EAAE;oBAClB,OAAO,EAAE,KAAK;oBACd,YAAY,EAAE,6CAA6C;iBAC5D,CAAC,CAAA;gBACF,OAAO;oBACL,QAAQ,EAAE,KAAK;oBACf,MAAM,EAAE,YAAY,KAAK,CAAC,SAAS,6BAA6B,KAAK,CAAC,EAAE,SAAS,KAAK,CAAC,UAAU,GAAG;iBACrG,CAAA;YACH,CAAC;YAED,MAAM,IAAI,CAAC,OAAO,CAAC,cAAc,CAAC;gBAChC,UAAU,EAAE,UAAU,CAAC,IAAI;gBAC3B,EAAE,EAAE,KAAK,CAAC,SAAS;aACpB,CAAC,CAAA;YAEF,MAAM,IAAI,CAAC,OAAO,CAAC,OAAO,CAAC,IAAI,CAAC;gBAC9B,IAAI,EAAE,0BAA0B;gBAChC,IAAI,EAAE;oBACJ,UAAU,EAAE,UAAU,CAAC,IAAI;oBAC3B,EAAE,EAAE,KAAK,CAAC,EAAE;oBACZ,YAAY,EAAE,GAAG,CAAC,IAAI,EAAE,EAAE,IAAI,QAAQ;oBACtC,WAAW,EAAE,KAAK,CAAC,SAAS;iBAC7B;aACF,CAAC,CAAA;YAEF,MAAM,IAAI,CAAC,WAAW,CAAC;gBACrB,KAAK,EAAE;oBACL,IAAI,EAAE,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,QAAQ;oBAClC,MAAM,EAAE,GAAG,CAAC,IAAI,EAAE,EAAE;oBACpB,QAAQ,EAAE,GAAG,CAAC,IAAI,EAAE,IAAI;oBACxB,UAAU,EAAE,GAAG,CAAC,UAAU;iBAC3B;gBACD,MAAM,EAAE,qBAAqB;gBAC7B,SAAS,EAAE,YAAY;gBACvB,OAAO,EAAE,UAAU;gBACnB,gBAAgB,EAAE,KAAK,CAAC,UAAU;gBAClC,QAAQ,EAAE,KAAK,CAAC,EAAE;gBAClB,MAAM,EAAE,KAAK,CAAC,KAAK,EAAE,UAAU;gBAC/B,SAAS,EAAE,KAAK,CAAC,KAAK,EAAE,SAAS;gBACjC,cAAc,EAAE,0BAA0B,KAAK,CAAC,SAAS,EAAE;gBAC3D,OAAO,EAAE,IAAI;aACd,CAAC,CAAA;YAEF,OAAO;gBACL,QAAQ,EAAE,IAAI;gBACd,WAAW,EAAE,KAAK,CAAC,SAAS;gBAC5B,IAAI,EAAE,kEAAkE;aACzE,CAAA;QACH,CAAC;KACF,CAAA;AACH,CAAC"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { Payload } from 'payload';
|
|
2
|
+
import { type AuditWriter } from '@forumone/throughline-core';
|
|
3
|
+
import type { McpToolDefinition } from '@forumone/throughline-plugin-contract';
|
|
4
|
+
import { type PublishingPluginOptions } from '../options.js';
|
|
5
|
+
export interface SchedulePublishToolDeps {
|
|
6
|
+
payload: Payload;
|
|
7
|
+
options: PublishingPluginOptions;
|
|
8
|
+
auditWriter: AuditWriter;
|
|
9
|
+
}
|
|
10
|
+
export declare function createSchedulePublishTool(deps: SchedulePublishToolDeps): McpToolDefinition;
|
|
11
|
+
//# sourceMappingURL=schedule-publish.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"schedule-publish.d.ts","sourceRoot":"","sources":["../../src/tools/schedule-publish.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,SAAS,CAAA;AACtC,OAAO,EAAE,KAAK,WAAW,EAAY,MAAM,4BAA4B,CAAA;AACvE,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,uCAAuC,CAAA;AAC9E,OAAO,EAAE,KAAK,uBAAuB,EAAqB,MAAM,eAAe,CAAA;AAG/E,MAAM,WAAW,uBAAuB;IACtC,OAAO,EAAE,OAAO,CAAA;IAChB,OAAO,EAAE,uBAAuB,CAAA;IAChC,WAAW,EAAE,WAAW,CAAA;CACzB;AAED,wBAAgB,yBAAyB,CAAC,IAAI,EAAE,uBAAuB,GAAG,iBAAiB,CAiG1F"}
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
import { withMeta } from '@forumone/throughline-core';
|
|
3
|
+
import { resolveCollection } from '../options.js';
|
|
4
|
+
import { runPreflightPipeline } from '../pipeline/index.js';
|
|
5
|
+
export function createSchedulePublishTool(deps) {
|
|
6
|
+
const inputSchema = withMeta({
|
|
7
|
+
collection: z.string(),
|
|
8
|
+
id: z.string(),
|
|
9
|
+
publishAt: z
|
|
10
|
+
.string()
|
|
11
|
+
.datetime()
|
|
12
|
+
.describe('ISO 8601 timestamp at which the document should be published'),
|
|
13
|
+
});
|
|
14
|
+
return {
|
|
15
|
+
name: 'schedule_publish',
|
|
16
|
+
description: "Schedules a future publish. Validates the document would currently pass the preflight pipeline (composition, accessibility, required fields, embargo, approval), then stores `scheduledPublishAt` on the document. The framework's workflow runner picks up the schedule and executes the full publish pipeline at that time.",
|
|
17
|
+
inputSchema,
|
|
18
|
+
handler: async (input, ctx) => {
|
|
19
|
+
const collection = resolveCollection(deps.options, input.collection);
|
|
20
|
+
const publishAtMs = Date.parse(input.publishAt);
|
|
21
|
+
if (publishAtMs <= Date.now()) {
|
|
22
|
+
return {
|
|
23
|
+
scheduled: false,
|
|
24
|
+
reason: 'publishAt must be in the future',
|
|
25
|
+
};
|
|
26
|
+
}
|
|
27
|
+
const document = (await deps.payload.findByID({
|
|
28
|
+
collection: collection.slug,
|
|
29
|
+
id: input.id,
|
|
30
|
+
draft: true,
|
|
31
|
+
}));
|
|
32
|
+
const preflight = await runPreflightPipeline({
|
|
33
|
+
payload: deps.payload,
|
|
34
|
+
inngest: deps.options.inngest,
|
|
35
|
+
options: deps.options,
|
|
36
|
+
collection,
|
|
37
|
+
document,
|
|
38
|
+
documentId: input.id,
|
|
39
|
+
actor: { user: ctx.user, apiKeyName: ctx.apiKeyName },
|
|
40
|
+
...(input._meta ? { meta: input._meta } : {}),
|
|
41
|
+
});
|
|
42
|
+
if (!preflight.success) {
|
|
43
|
+
await deps.auditWriter({
|
|
44
|
+
actor: { type: ctx.user ? 'user' : 'system', userId: ctx.user?.id, apiKeyName: ctx.apiKeyName },
|
|
45
|
+
action: 'publishing.schedule',
|
|
46
|
+
mcpServer: 'publishing',
|
|
47
|
+
mcpTool: 'schedule_publish',
|
|
48
|
+
targetCollection: input.collection,
|
|
49
|
+
targetId: input.id,
|
|
50
|
+
prompt: input._meta?.userPrompt,
|
|
51
|
+
success: false,
|
|
52
|
+
errorMessage: preflight.reason,
|
|
53
|
+
});
|
|
54
|
+
return {
|
|
55
|
+
scheduled: false,
|
|
56
|
+
failedAt: preflight.failedAt,
|
|
57
|
+
reason: preflight.reason,
|
|
58
|
+
code: preflight.code,
|
|
59
|
+
issues: preflight.issues,
|
|
60
|
+
suggestion: preflight.suggestion,
|
|
61
|
+
};
|
|
62
|
+
}
|
|
63
|
+
await deps.payload.update({
|
|
64
|
+
collection: collection.slug,
|
|
65
|
+
id: input.id,
|
|
66
|
+
data: { [collection.scheduledPublishField]: input.publishAt },
|
|
67
|
+
context: { bypassPublishingServer: false },
|
|
68
|
+
});
|
|
69
|
+
await deps.options.inngest.send({
|
|
70
|
+
name: 'content/page.scheduled',
|
|
71
|
+
data: {
|
|
72
|
+
collection: collection.slug,
|
|
73
|
+
id: input.id,
|
|
74
|
+
scheduledFor: input.publishAt,
|
|
75
|
+
},
|
|
76
|
+
});
|
|
77
|
+
await deps.auditWriter({
|
|
78
|
+
actor: { type: ctx.user ? 'user' : 'system', userId: ctx.user?.id, apiKeyName: ctx.apiKeyName },
|
|
79
|
+
action: 'publishing.schedule',
|
|
80
|
+
mcpServer: 'publishing',
|
|
81
|
+
mcpTool: 'schedule_publish',
|
|
82
|
+
targetCollection: input.collection,
|
|
83
|
+
targetId: input.id,
|
|
84
|
+
targetTitle: typeof document['title'] === 'string' ? document['title'] : input.id,
|
|
85
|
+
prompt: input._meta?.userPrompt,
|
|
86
|
+
reasoning: input._meta?.reasoning,
|
|
87
|
+
changesSummary: `Scheduled publish for ${input.publishAt}`,
|
|
88
|
+
success: true,
|
|
89
|
+
});
|
|
90
|
+
return { scheduled: true, scheduledFor: input.publishAt };
|
|
91
|
+
},
|
|
92
|
+
};
|
|
93
|
+
}
|
|
94
|
+
//# sourceMappingURL=schedule-publish.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"schedule-publish.js","sourceRoot":"","sources":["../../src/tools/schedule-publish.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { Payload } from 'payload';
|
|
2
|
+
import { type AuditWriter } from '@forumone/throughline-core';
|
|
3
|
+
import type { McpToolDefinition } from '@forumone/throughline-plugin-contract';
|
|
4
|
+
import { type PublishingPluginOptions } from '../options.js';
|
|
5
|
+
export interface UnpublishToolDeps {
|
|
6
|
+
payload: Payload;
|
|
7
|
+
options: PublishingPluginOptions;
|
|
8
|
+
auditWriter: AuditWriter;
|
|
9
|
+
}
|
|
10
|
+
export declare function createUnpublishTool(deps: UnpublishToolDeps): McpToolDefinition;
|
|
11
|
+
//# sourceMappingURL=unpublish.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"unpublish.d.ts","sourceRoot":"","sources":["../../src/tools/unpublish.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,SAAS,CAAA;AACtC,OAAO,EAAE,KAAK,WAAW,EAAY,MAAM,4BAA4B,CAAA;AACvE,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,uCAAuC,CAAA;AAC9E,OAAO,EAAE,KAAK,uBAAuB,EAAqB,MAAM,eAAe,CAAA;AAE/E,MAAM,WAAW,iBAAiB;IAChC,OAAO,EAAE,OAAO,CAAA;IAChB,OAAO,EAAE,uBAAuB,CAAA;IAChC,WAAW,EAAE,WAAW,CAAA;CACzB;AAED,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,iBAAiB,GAAG,iBAAiB,CA+D9E"}
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
import { withMeta } from '@forumone/throughline-core';
|
|
3
|
+
import { resolveCollection } from '../options.js';
|
|
4
|
+
export function createUnpublishTool(deps) {
|
|
5
|
+
const inputSchema = withMeta({
|
|
6
|
+
collection: z.string(),
|
|
7
|
+
id: z.string(),
|
|
8
|
+
});
|
|
9
|
+
return {
|
|
10
|
+
name: 'unpublish',
|
|
11
|
+
description: 'Unpublishes a published document by reverting it to draft. Use when content needs to be removed from the public site without deleting it. Fires content/page.unpublished so revalidation and integrations can react.',
|
|
12
|
+
inputSchema,
|
|
13
|
+
handler: async (input, ctx) => {
|
|
14
|
+
const collection = resolveCollection(deps.options, input.collection);
|
|
15
|
+
const document = (await deps.payload.findByID({
|
|
16
|
+
collection: collection.slug,
|
|
17
|
+
id: input.id,
|
|
18
|
+
draft: true,
|
|
19
|
+
}));
|
|
20
|
+
if (document['_status'] !== 'published') {
|
|
21
|
+
return { unpublished: false, reason: 'Document is not currently published' };
|
|
22
|
+
}
|
|
23
|
+
await deps.payload.update({
|
|
24
|
+
collection: collection.slug,
|
|
25
|
+
id: input.id,
|
|
26
|
+
data: { _status: 'draft' },
|
|
27
|
+
context: { bypassPublishingServer: true },
|
|
28
|
+
});
|
|
29
|
+
const slug = document[collection.slugField];
|
|
30
|
+
await deps.options.inngest.send({
|
|
31
|
+
name: 'content/page.unpublished',
|
|
32
|
+
data: {
|
|
33
|
+
collection: collection.slug,
|
|
34
|
+
id: input.id,
|
|
35
|
+
slug: typeof slug === 'string' ? slug : input.id,
|
|
36
|
+
unpublishedBy: ctx.user?.id ?? 'system',
|
|
37
|
+
},
|
|
38
|
+
});
|
|
39
|
+
await deps.auditWriter({
|
|
40
|
+
actor: {
|
|
41
|
+
type: ctx.user ? 'user' : 'system',
|
|
42
|
+
userId: ctx.user?.id,
|
|
43
|
+
userName: ctx.user?.name,
|
|
44
|
+
apiKeyName: ctx.apiKeyName,
|
|
45
|
+
},
|
|
46
|
+
action: 'publishing.unpublish',
|
|
47
|
+
mcpServer: 'publishing',
|
|
48
|
+
mcpTool: 'unpublish',
|
|
49
|
+
targetCollection: input.collection,
|
|
50
|
+
targetId: input.id,
|
|
51
|
+
targetTitle: typeof document['title'] === 'string' ? document['title'] : input.id,
|
|
52
|
+
prompt: input._meta?.userPrompt,
|
|
53
|
+
reasoning: input._meta?.reasoning,
|
|
54
|
+
changesSummary: input._meta?.changesSummary,
|
|
55
|
+
success: true,
|
|
56
|
+
});
|
|
57
|
+
return { unpublished: true };
|
|
58
|
+
},
|
|
59
|
+
};
|
|
60
|
+
}
|
|
61
|
+
//# sourceMappingURL=unpublish.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"unpublish.js","sourceRoot":"","sources":["../../src/tools/unpublish.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,10 +1,69 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@forumone/throughline-publishing",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"description": "
|
|
3
|
+
"version": "0.2.1",
|
|
4
|
+
"description": "Policy-gated publishing server for Throughline. Wraps Payload's update operation with composition, accessibility, required-field, embargo, and approval gating.",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "./dist/index.js",
|
|
7
|
+
"types": "./dist/index.d.ts",
|
|
8
|
+
"exports": {
|
|
9
|
+
".": {
|
|
10
|
+
"types": "./dist/index.d.ts",
|
|
11
|
+
"default": "./dist/index.js"
|
|
12
|
+
},
|
|
13
|
+
"./checks": {
|
|
14
|
+
"types": "./dist/checks/index.d.ts",
|
|
15
|
+
"default": "./dist/checks/index.js"
|
|
16
|
+
}
|
|
17
|
+
},
|
|
18
|
+
"files": [
|
|
19
|
+
"dist",
|
|
20
|
+
"README.md",
|
|
21
|
+
"CHANGELOG.md"
|
|
22
|
+
],
|
|
5
23
|
"keywords": [
|
|
6
|
-
"
|
|
7
|
-
"
|
|
8
|
-
"
|
|
9
|
-
|
|
10
|
-
|
|
24
|
+
"throughline",
|
|
25
|
+
"payload",
|
|
26
|
+
"mcp",
|
|
27
|
+
"publishing"
|
|
28
|
+
],
|
|
29
|
+
"license": "MIT",
|
|
30
|
+
"repository": {
|
|
31
|
+
"type": "git",
|
|
32
|
+
"url": "git+https://github.com/forumone/throughline.git",
|
|
33
|
+
"directory": "packages/publishing"
|
|
34
|
+
},
|
|
35
|
+
"homepage": "https://github.com/forumone/throughline/tree/main/packages/publishing#readme",
|
|
36
|
+
"bugs": {
|
|
37
|
+
"url": "https://github.com/forumone/throughline/issues"
|
|
38
|
+
},
|
|
39
|
+
"publishConfig": {
|
|
40
|
+
"access": "public"
|
|
41
|
+
},
|
|
42
|
+
"peerDependencies": {
|
|
43
|
+
"payload": "^3.0.0",
|
|
44
|
+
"inngest": "^4.0.0"
|
|
45
|
+
},
|
|
46
|
+
"dependencies": {
|
|
47
|
+
"zod": "^3.23.0",
|
|
48
|
+
"@forumone/throughline-core": "0.2.0",
|
|
49
|
+
"@forumone/throughline-plugin-contract": "0.0.0"
|
|
50
|
+
},
|
|
51
|
+
"devDependencies": {
|
|
52
|
+
"@types/node": "^20.17.0",
|
|
53
|
+
"eslint": "^9.15.0",
|
|
54
|
+
"inngest": "^4.2.0",
|
|
55
|
+
"payload": "^3.83.0",
|
|
56
|
+
"typescript": "^5.6.0",
|
|
57
|
+
"vitest": "^2.1.0",
|
|
58
|
+
"@forumone/throughline-eslint-config": "0.0.0",
|
|
59
|
+
"@forumone/throughline-tsconfig": "0.0.0"
|
|
60
|
+
},
|
|
61
|
+
"scripts": {
|
|
62
|
+
"build": "tsc -b",
|
|
63
|
+
"dev": "tsc -b -w",
|
|
64
|
+
"clean": "rm -rf dist .turbo *.tsbuildinfo",
|
|
65
|
+
"typecheck": "tsc --noEmit",
|
|
66
|
+
"lint": "eslint src",
|
|
67
|
+
"test": "vitest run"
|
|
68
|
+
}
|
|
69
|
+
}
|