Tactical Media Broadcast Hub — initial release
Self-hosted multi-platform broadcast newsroom for activist collectives: publishing pipeline with group approval and DST-proof scheduling, TweetDeck-style column wall with hostile-content-safe rendering, live control room with Auto Director, bridged chat governance with polls and quorum, distributed sandboxed transcode workers, encrypted content-addressed archive, monthly analytics. MIT licensed. See README.md and docs/.
This commit is contained in:
commit
aa5e262f3a
880 changed files with 111042 additions and 0 deletions
27
packages/connector-example/src/contract.test.ts
Normal file
27
packages/connector-example/src/contract.test.ts
Normal file
|
|
@ -0,0 +1,27 @@
|
|||
import { describe, expect, it } from "vitest";
|
||||
import { createExampleConnector } from "./index.js";
|
||||
import { connectorContractTests } from "@tactical-media-broadcast-hub/connector-sdk/testing";
|
||||
import type { ConnectorConnection } from "@tactical-media-broadcast-hub/core";
|
||||
|
||||
const connection: ConnectorConnection = {
|
||||
id: "conn-1",
|
||||
workspaceId: "ws-1",
|
||||
provider: "example",
|
||||
channelId: "ch-1",
|
||||
credentialId: { kind: "credential-ref", id: "cred-1" },
|
||||
fields: {},
|
||||
createdAt: new Date(),
|
||||
};
|
||||
|
||||
connectorContractTests(createExampleConnector(), { connection });
|
||||
|
||||
describe("example connector specifics", () => {
|
||||
it("refuses authorize honestly", async () => {
|
||||
const connector = createExampleConnector();
|
||||
await expect(connector.authorize({
|
||||
redirectUri: "https://app.example/cb",
|
||||
workspaceId: "ws-1",
|
||||
state: "s",
|
||||
})).rejects.toThrow("does not implement");
|
||||
});
|
||||
});
|
||||
63
packages/connector-example/src/index.ts
Normal file
63
packages/connector-example/src/index.ts
Normal file
|
|
@ -0,0 +1,63 @@
|
|||
/**
|
||||
* Reference connector: the minimal honest implementation. Every real
|
||||
* connector copies this shape and fills in a provider API.
|
||||
*/
|
||||
import type {
|
||||
ConnectorCapabilities,
|
||||
ConnectorConnection,
|
||||
NormalizedIdentity,
|
||||
NormalizedPost,
|
||||
Publication,
|
||||
} from "@tactical-media-broadcast-hub/core";
|
||||
import {
|
||||
assertValidManifest,
|
||||
type ConnectorManifest,
|
||||
type PlatformConnector,
|
||||
} from "@tactical-media-broadcast-hub/connector-sdk";
|
||||
|
||||
const CAPABILITIES: ConnectorCapabilities = {
|
||||
publishText: true,
|
||||
};
|
||||
|
||||
export function createExampleConnector(): PlatformConnector {
|
||||
const manifest: ConnectorManifest = {
|
||||
id: "example",
|
||||
displayName: "Example (reference connector)",
|
||||
capabilities: CAPABILITIES,
|
||||
connectionFields: [
|
||||
{ name: "apiToken", label: "API token", required: true, secret: true },
|
||||
],
|
||||
};
|
||||
|
||||
return {
|
||||
manifest: () => {
|
||||
assertValidManifest(manifest);
|
||||
return manifest;
|
||||
},
|
||||
|
||||
async authorize() {
|
||||
throw new Error("example connector does not implement OAuth");
|
||||
},
|
||||
|
||||
async getIdentity(connection: ConnectorConnection): Promise<NormalizedIdentity> {
|
||||
return {
|
||||
provider: manifest.id,
|
||||
remoteId: connection.id,
|
||||
handle: "example@example",
|
||||
displayName: "Example Account",
|
||||
};
|
||||
},
|
||||
|
||||
async publish(connection: ConnectorConnection, post: NormalizedPost): Promise<Publication> {
|
||||
return {
|
||||
id: `pub-${post.text.length}`,
|
||||
workspaceId: connection.workspaceId,
|
||||
draftId: "direct",
|
||||
connectionId: connection.id,
|
||||
remoteId: `remote-${post.text.length}`,
|
||||
publishedAt: new Date(),
|
||||
providerMetadata: post.providerMetadata,
|
||||
};
|
||||
},
|
||||
};
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue