@contractspec/example.video-api-showcase 2.1.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/.turbo/turbo-build.log +35 -0
- package/.turbo/turbo-prebuild.log +1 -0
- package/CHANGELOG.md +14 -0
- package/dist/browser/build-api-video.js +41 -0
- package/dist/browser/docs/index.js +66 -0
- package/dist/browser/docs/video-api-showcase.docblock.js +66 -0
- package/dist/browser/example.js +33 -0
- package/dist/browser/index.js +241 -0
- package/dist/browser/sample-specs.js +103 -0
- package/dist/build-api-video.d.ts +53 -0
- package/dist/build-api-video.js +42 -0
- package/dist/docs/index.d.ts +1 -0
- package/dist/docs/index.js +67 -0
- package/dist/docs/video-api-showcase.docblock.d.ts +1 -0
- package/dist/docs/video-api-showcase.docblock.js +67 -0
- package/dist/example.d.ts +2 -0
- package/dist/example.js +34 -0
- package/dist/index.d.ts +4 -0
- package/dist/index.js +242 -0
- package/dist/node/build-api-video.js +41 -0
- package/dist/node/docs/index.js +66 -0
- package/dist/node/docs/video-api-showcase.docblock.js +66 -0
- package/dist/node/example.js +33 -0
- package/dist/node/index.js +241 -0
- package/dist/node/sample-specs.js +103 -0
- package/dist/sample-specs.d.ts +28 -0
- package/dist/sample-specs.js +104 -0
- package/package.json +145 -0
- package/src/build-api-video.ts +104 -0
- package/src/docs/index.ts +1 -0
- package/src/docs/video-api-showcase.docblock.ts +70 -0
- package/src/example.ts +32 -0
- package/src/index.ts +6 -0
- package/src/sample-specs.ts +129 -0
- package/tsconfig.json +9 -0
- package/tsdown.config.js +3 -0
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
// ---------------------------------------------------------------------------
|
|
2
|
+
// Build API Video -- Construct a VideoProject from contract spec metadata
|
|
3
|
+
// ---------------------------------------------------------------------------
|
|
4
|
+
|
|
5
|
+
import type { VideoProject } from '@contractspec/lib.contracts-integrations/integrations/providers/video';
|
|
6
|
+
import { VIDEO_FORMATS } from '@contractspec/lib.video-gen/design/layouts';
|
|
7
|
+
import { resolveRenderConfig } from '@contractspec/lib.video-gen/renderers/config';
|
|
8
|
+
import type { QualityPreset } from '@contractspec/lib.video-gen/renderers/config';
|
|
9
|
+
import type { RenderConfig } from '@contractspec/lib.contracts-integrations/integrations/providers/video';
|
|
10
|
+
import type { ApiSpecDefinition } from './sample-specs';
|
|
11
|
+
|
|
12
|
+
const DEFAULT_FPS = 30;
|
|
13
|
+
const DEFAULT_DURATION_FRAMES = 450; // 15 seconds
|
|
14
|
+
|
|
15
|
+
/** Options for building an API showcase video. */
|
|
16
|
+
export interface BuildApiVideoOptions {
|
|
17
|
+
/** Duration in frames. Default: 450 (15s at 30fps). */
|
|
18
|
+
durationInFrames?: number;
|
|
19
|
+
/** Tagline shown at the end. */
|
|
20
|
+
tagline?: string;
|
|
21
|
+
/** FPS. Default: 30. */
|
|
22
|
+
fps?: number;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* Build a VideoProject from a contract spec definition.
|
|
27
|
+
*
|
|
28
|
+
* This demonstrates manual project construction using the ApiOverview
|
|
29
|
+
* composition -- useful when you know the exact video structure.
|
|
30
|
+
*
|
|
31
|
+
* @example
|
|
32
|
+
* ```ts
|
|
33
|
+
* import { buildApiVideo } from "@contractspec/example.video-api-showcase/build-api-video";
|
|
34
|
+
* import { createUserSpec } from "@contractspec/example.video-api-showcase/sample-specs";
|
|
35
|
+
*
|
|
36
|
+
* const project = buildApiVideo(createUserSpec);
|
|
37
|
+
* // project.scenes[0].compositionId === "ApiOverview"
|
|
38
|
+
* ```
|
|
39
|
+
*/
|
|
40
|
+
export function buildApiVideo(
|
|
41
|
+
spec: ApiSpecDefinition,
|
|
42
|
+
options?: BuildApiVideoOptions
|
|
43
|
+
): VideoProject {
|
|
44
|
+
const fps = options?.fps ?? DEFAULT_FPS;
|
|
45
|
+
const durationInFrames = options?.durationInFrames ?? DEFAULT_DURATION_FRAMES;
|
|
46
|
+
|
|
47
|
+
return {
|
|
48
|
+
id: `api-video-${spec.specName.toLowerCase()}-${Date.now().toString(36)}`,
|
|
49
|
+
scenes: [
|
|
50
|
+
{
|
|
51
|
+
id: 'scene-api-overview',
|
|
52
|
+
compositionId: 'ApiOverview',
|
|
53
|
+
props: {
|
|
54
|
+
specName: spec.specName,
|
|
55
|
+
method: spec.method,
|
|
56
|
+
endpoint: spec.endpoint,
|
|
57
|
+
specCode: spec.specCode,
|
|
58
|
+
generatedOutputs: spec.generatedOutputs,
|
|
59
|
+
tagline: options?.tagline ?? 'One spec. Every surface.',
|
|
60
|
+
},
|
|
61
|
+
durationInFrames,
|
|
62
|
+
},
|
|
63
|
+
],
|
|
64
|
+
totalDurationInFrames: durationInFrames,
|
|
65
|
+
fps,
|
|
66
|
+
format: VIDEO_FORMATS.landscape,
|
|
67
|
+
};
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
/**
|
|
71
|
+
* Build a render configuration for the API video.
|
|
72
|
+
*
|
|
73
|
+
* Demonstrates using quality presets to configure rendering.
|
|
74
|
+
*
|
|
75
|
+
* @example
|
|
76
|
+
* ```ts
|
|
77
|
+
* const config = buildRenderConfig("out/api-overview.mp4", "high");
|
|
78
|
+
* // config.crf === 12, config.codec === "h264"
|
|
79
|
+
* ```
|
|
80
|
+
*/
|
|
81
|
+
export function buildRenderConfig(
|
|
82
|
+
outputPath: string,
|
|
83
|
+
preset: QualityPreset = 'standard'
|
|
84
|
+
): RenderConfig {
|
|
85
|
+
return resolveRenderConfig({ outputPath }, preset);
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
/**
|
|
89
|
+
* Build video projects for multiple specs at once.
|
|
90
|
+
*
|
|
91
|
+
* @example
|
|
92
|
+
* ```ts
|
|
93
|
+
* import { createUserSpec, listTransactionsSpec } from "./sample-specs";
|
|
94
|
+
*
|
|
95
|
+
* const projects = buildApiVideoSuite([createUserSpec, listTransactionsSpec]);
|
|
96
|
+
* // projects.length === 2
|
|
97
|
+
* ```
|
|
98
|
+
*/
|
|
99
|
+
export function buildApiVideoSuite(
|
|
100
|
+
specs: ApiSpecDefinition[],
|
|
101
|
+
options?: BuildApiVideoOptions
|
|
102
|
+
): VideoProject[] {
|
|
103
|
+
return specs.map((spec) => buildApiVideo(spec, options));
|
|
104
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import './video-api-showcase.docblock';
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
import type { DocBlock } from '@contractspec/lib.contracts-spec/docs';
|
|
2
|
+
import { registerDocBlocks } from '@contractspec/lib.contracts-spec/docs';
|
|
3
|
+
|
|
4
|
+
const blocks: DocBlock[] = [
|
|
5
|
+
{
|
|
6
|
+
id: 'docs.examples.video-api-showcase',
|
|
7
|
+
title: 'Video API Showcase (example)',
|
|
8
|
+
summary:
|
|
9
|
+
'Spec-driven example: build API overview videos directly from contract spec metadata using manual VideoProject construction.',
|
|
10
|
+
kind: 'reference',
|
|
11
|
+
visibility: 'public',
|
|
12
|
+
route: '/docs/examples/video-api-showcase',
|
|
13
|
+
tags: ['video', 'api', 'spec-driven', 'example'],
|
|
14
|
+
body: `## What this example shows
|
|
15
|
+
|
|
16
|
+
- Manually constructing a \`VideoProject\` from contract spec metadata (name, method, endpoint, code, outputs).
|
|
17
|
+
- Using the \`ApiOverview\` composition to visualize how a spec generates multiple API surfaces.
|
|
18
|
+
- Configuring render settings with quality presets (\`draft\`, \`standard\`, \`high\`).
|
|
19
|
+
- Building video scenes with explicit composition IDs and props.
|
|
20
|
+
|
|
21
|
+
## Key concepts
|
|
22
|
+
|
|
23
|
+
- **Spec-to-Video**: Contract spec metadata (name, method, endpoint, code snippet) becomes the input props for the \`ApiOverview\` composition.
|
|
24
|
+
- **Manual project construction**: Instead of using \`VideoGenerator\`, this example builds the \`VideoProject\` directly -- useful when you know exactly which composition and props to use.
|
|
25
|
+
- **Render configuration**: Shows how to use \`resolveRenderConfig()\` with quality presets for different output needs.
|
|
26
|
+
|
|
27
|
+
## Notes
|
|
28
|
+
|
|
29
|
+
- This approach is ideal when the video structure is known ahead of time (e.g., always an API overview).
|
|
30
|
+
- For dynamic scene planning from content briefs, use \`VideoGenerator\` instead (see the video-marketing-clip example).
|
|
31
|
+
`,
|
|
32
|
+
},
|
|
33
|
+
{
|
|
34
|
+
id: 'docs.examples.video-api-showcase.usage',
|
|
35
|
+
title: 'Video API Showcase -- Usage',
|
|
36
|
+
summary:
|
|
37
|
+
'How to generate API overview videos from contract spec definitions.',
|
|
38
|
+
kind: 'usage',
|
|
39
|
+
visibility: 'public',
|
|
40
|
+
route: '/docs/examples/video-api-showcase/usage',
|
|
41
|
+
tags: ['video', 'api', 'usage'],
|
|
42
|
+
body: `## Usage
|
|
43
|
+
|
|
44
|
+
\`\`\`ts
|
|
45
|
+
import { buildApiVideo } from "@contractspec/example.video-api-showcase/build-api-video";
|
|
46
|
+
import { createUserSpec, listTransactionsSpec } from "@contractspec/example.video-api-showcase/sample-specs";
|
|
47
|
+
|
|
48
|
+
// Build a video project for a single API spec
|
|
49
|
+
const project = buildApiVideo(createUserSpec);
|
|
50
|
+
|
|
51
|
+
console.log(project.scenes[0].compositionId); // "ApiOverview"
|
|
52
|
+
console.log(project.format); // { type: "landscape", width: 1920, height: 1080 }
|
|
53
|
+
|
|
54
|
+
// Build with custom duration and tagline
|
|
55
|
+
const custom = buildApiVideo(listTransactionsSpec, {
|
|
56
|
+
durationInFrames: 600,
|
|
57
|
+
tagline: "From spec to production in seconds.",
|
|
58
|
+
});
|
|
59
|
+
\`\`\`
|
|
60
|
+
|
|
61
|
+
## Guardrails
|
|
62
|
+
|
|
63
|
+
- The \`specCode\` field should be a concise snippet (10-20 lines) for readability in the video.
|
|
64
|
+
- Generated outputs list should contain 3-8 items for optimal visual layout.
|
|
65
|
+
- Tagline should be short (under 40 characters) to fit within the composition frame.
|
|
66
|
+
`,
|
|
67
|
+
},
|
|
68
|
+
];
|
|
69
|
+
|
|
70
|
+
registerDocBlocks(blocks);
|
package/src/example.ts
ADDED
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { defineExample } from '@contractspec/lib.contracts-spec';
|
|
2
|
+
|
|
3
|
+
const example = defineExample({
|
|
4
|
+
meta: {
|
|
5
|
+
key: 'video-api-showcase',
|
|
6
|
+
version: '1.0.0',
|
|
7
|
+
title: 'Video API Showcase',
|
|
8
|
+
description:
|
|
9
|
+
'Generate API documentation videos from contract spec definitions using the ApiOverview composition.',
|
|
10
|
+
kind: 'script',
|
|
11
|
+
visibility: 'public',
|
|
12
|
+
stability: 'experimental',
|
|
13
|
+
owners: ['@platform.core'],
|
|
14
|
+
tags: ['video', 'api', 'documentation', 'spec-driven'],
|
|
15
|
+
},
|
|
16
|
+
docs: {
|
|
17
|
+
rootDocId: 'docs.examples.video-api-showcase',
|
|
18
|
+
usageDocId: 'docs.examples.video-api-showcase.usage',
|
|
19
|
+
},
|
|
20
|
+
entrypoints: {
|
|
21
|
+
packageName: '@contractspec/example.video-api-showcase',
|
|
22
|
+
docs: './docs',
|
|
23
|
+
},
|
|
24
|
+
surfaces: {
|
|
25
|
+
templates: true,
|
|
26
|
+
sandbox: { enabled: true, modes: ['markdown'] },
|
|
27
|
+
studio: { enabled: true, installable: true },
|
|
28
|
+
mcp: { enabled: true },
|
|
29
|
+
},
|
|
30
|
+
});
|
|
31
|
+
|
|
32
|
+
export default example;
|
package/src/index.ts
ADDED
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
// ---------------------------------------------------------------------------
|
|
2
|
+
// Sample Contract Spec Definitions for API Video Generation
|
|
3
|
+
// ---------------------------------------------------------------------------
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Spec metadata used to build API overview videos.
|
|
7
|
+
* Maps directly to ApiOverviewProps.
|
|
8
|
+
*/
|
|
9
|
+
export interface ApiSpecDefinition {
|
|
10
|
+
/** Contract spec name (e.g., "CreateUser") */
|
|
11
|
+
specName: string;
|
|
12
|
+
/** HTTP method */
|
|
13
|
+
method: string;
|
|
14
|
+
/** Endpoint path */
|
|
15
|
+
endpoint: string;
|
|
16
|
+
/** Contract spec code snippet */
|
|
17
|
+
specCode: string;
|
|
18
|
+
/** Generated output surfaces */
|
|
19
|
+
generatedOutputs: string[];
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* CreateUser -- user registration endpoint.
|
|
24
|
+
*/
|
|
25
|
+
export const createUserSpec: ApiSpecDefinition = {
|
|
26
|
+
specName: 'CreateUser',
|
|
27
|
+
method: 'POST',
|
|
28
|
+
endpoint: '/api/users',
|
|
29
|
+
specCode: `export const createUser = defineCommand({
|
|
30
|
+
meta: {
|
|
31
|
+
name: "CreateUser",
|
|
32
|
+
version: "1.0.0",
|
|
33
|
+
stability: "Stable",
|
|
34
|
+
},
|
|
35
|
+
io: {
|
|
36
|
+
input: z.object({
|
|
37
|
+
email: z.string().email(),
|
|
38
|
+
name: z.string(),
|
|
39
|
+
role: z.enum(["admin", "user"]),
|
|
40
|
+
}),
|
|
41
|
+
output: z.object({
|
|
42
|
+
id: z.string().uuid(),
|
|
43
|
+
email: z.string(),
|
|
44
|
+
createdAt: z.date(),
|
|
45
|
+
}),
|
|
46
|
+
},
|
|
47
|
+
});`,
|
|
48
|
+
generatedOutputs: [
|
|
49
|
+
'REST Endpoint',
|
|
50
|
+
'GraphQL Mutation',
|
|
51
|
+
'Prisma Model',
|
|
52
|
+
'TypeScript SDK',
|
|
53
|
+
'MCP Tool',
|
|
54
|
+
'OpenAPI Spec',
|
|
55
|
+
],
|
|
56
|
+
};
|
|
57
|
+
|
|
58
|
+
/**
|
|
59
|
+
* ListTransactions -- financial transaction listing.
|
|
60
|
+
*/
|
|
61
|
+
export const listTransactionsSpec: ApiSpecDefinition = {
|
|
62
|
+
specName: 'ListTransactions',
|
|
63
|
+
method: 'GET',
|
|
64
|
+
endpoint: '/api/transactions',
|
|
65
|
+
specCode: `export const listTransactions = defineQuery({
|
|
66
|
+
meta: {
|
|
67
|
+
name: "ListTransactions",
|
|
68
|
+
version: "1.0.0",
|
|
69
|
+
stability: "Stable",
|
|
70
|
+
},
|
|
71
|
+
io: {
|
|
72
|
+
input: z.object({
|
|
73
|
+
accountId: z.string().uuid(),
|
|
74
|
+
from: z.date().optional(),
|
|
75
|
+
to: z.date().optional(),
|
|
76
|
+
limit: z.number().default(50),
|
|
77
|
+
}),
|
|
78
|
+
output: z.object({
|
|
79
|
+
transactions: z.array(transactionSchema),
|
|
80
|
+
total: z.number(),
|
|
81
|
+
hasMore: z.boolean(),
|
|
82
|
+
}),
|
|
83
|
+
},
|
|
84
|
+
});`,
|
|
85
|
+
generatedOutputs: [
|
|
86
|
+
'REST Endpoint',
|
|
87
|
+
'GraphQL Query',
|
|
88
|
+
'Prisma Query',
|
|
89
|
+
'TypeScript SDK',
|
|
90
|
+
'OpenAPI Spec',
|
|
91
|
+
],
|
|
92
|
+
};
|
|
93
|
+
|
|
94
|
+
/**
|
|
95
|
+
* SendNotification -- push notification dispatch.
|
|
96
|
+
*/
|
|
97
|
+
export const sendNotificationSpec: ApiSpecDefinition = {
|
|
98
|
+
specName: 'SendNotification',
|
|
99
|
+
method: 'POST',
|
|
100
|
+
endpoint: '/api/notifications',
|
|
101
|
+
specCode: `export const sendNotification = defineCommand({
|
|
102
|
+
meta: {
|
|
103
|
+
name: "SendNotification",
|
|
104
|
+
version: "1.0.0",
|
|
105
|
+
stability: "Beta",
|
|
106
|
+
},
|
|
107
|
+
io: {
|
|
108
|
+
input: z.object({
|
|
109
|
+
userId: z.string().uuid(),
|
|
110
|
+
channel: z.enum(["push", "email", "sms"]),
|
|
111
|
+
title: z.string(),
|
|
112
|
+
body: z.string(),
|
|
113
|
+
}),
|
|
114
|
+
output: z.object({
|
|
115
|
+
notificationId: z.string().uuid(),
|
|
116
|
+
deliveredAt: z.date().nullable(),
|
|
117
|
+
status: z.enum(["sent", "failed", "queued"]),
|
|
118
|
+
}),
|
|
119
|
+
},
|
|
120
|
+
});`,
|
|
121
|
+
generatedOutputs: [
|
|
122
|
+
'REST Endpoint',
|
|
123
|
+
'GraphQL Mutation',
|
|
124
|
+
'TypeScript SDK',
|
|
125
|
+
'MCP Tool',
|
|
126
|
+
'OpenAPI Spec',
|
|
127
|
+
'Event Schema',
|
|
128
|
+
],
|
|
129
|
+
};
|
package/tsconfig.json
ADDED
package/tsdown.config.js
ADDED