@contractspec/example.learning-journey-platform-tour 0.0.0-canary-20260113162409

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.
Files changed (56) hide show
  1. package/.turbo/turbo-build$colon$bundle.log +45 -0
  2. package/.turbo/turbo-build.log +46 -0
  3. package/CHANGELOG.md +330 -0
  4. package/LICENSE +21 -0
  5. package/README.md +43 -0
  6. package/dist/docs/index.d.ts +1 -0
  7. package/dist/docs/index.js +1 -0
  8. package/dist/docs/platform-tour.docblock.d.ts +1 -0
  9. package/dist/docs/platform-tour.docblock.js +42 -0
  10. package/dist/docs/platform-tour.docblock.js.map +1 -0
  11. package/dist/example.d.ts +7 -0
  12. package/dist/example.d.ts.map +1 -0
  13. package/dist/example.js +46 -0
  14. package/dist/example.js.map +1 -0
  15. package/dist/handlers/demo.handlers.d.ts +25 -0
  16. package/dist/handlers/demo.handlers.d.ts.map +1 -0
  17. package/dist/handlers/demo.handlers.js +27 -0
  18. package/dist/handlers/demo.handlers.js.map +1 -0
  19. package/dist/index.d.ts +7 -0
  20. package/dist/index.js +9 -0
  21. package/dist/learning-journey-platform-tour.feature.d.ts +12 -0
  22. package/dist/learning-journey-platform-tour.feature.d.ts.map +1 -0
  23. package/dist/learning-journey-platform-tour.feature.js +75 -0
  24. package/dist/learning-journey-platform-tour.feature.js.map +1 -0
  25. package/dist/operations/index.d.ts +271 -0
  26. package/dist/operations/index.d.ts.map +1 -0
  27. package/dist/operations/index.js +176 -0
  28. package/dist/operations/index.js.map +1 -0
  29. package/dist/presentations/index.d.ts +9 -0
  30. package/dist/presentations/index.d.ts.map +1 -0
  31. package/dist/presentations/index.js +55 -0
  32. package/dist/presentations/index.js.map +1 -0
  33. package/dist/tests/operations.test-spec.d.ts +7 -0
  34. package/dist/tests/operations.test-spec.d.ts.map +1 -0
  35. package/dist/tests/operations.test-spec.js +36 -0
  36. package/dist/tests/operations.test-spec.js.map +1 -0
  37. package/dist/track.d.ts +8 -0
  38. package/dist/track.d.ts.map +1 -0
  39. package/dist/track.js +106 -0
  40. package/dist/track.js.map +1 -0
  41. package/example.ts +1 -0
  42. package/package.json +66 -0
  43. package/src/docs/index.ts +1 -0
  44. package/src/docs/platform-tour.docblock.ts +40 -0
  45. package/src/example.ts +33 -0
  46. package/src/handlers/demo.handlers.ts +50 -0
  47. package/src/index.ts +7 -0
  48. package/src/learning-journey-platform-tour.feature.ts +66 -0
  49. package/src/operations/index.test.ts +49 -0
  50. package/src/operations/index.ts +122 -0
  51. package/src/presentations/index.ts +51 -0
  52. package/src/tests/operations.test-spec.ts +31 -0
  53. package/src/track.ts +106 -0
  54. package/tsconfig.json +9 -0
  55. package/tsconfig.tsbuildinfo +1 -0
  56. package/tsdown.config.js +17 -0
@@ -0,0 +1 @@
1
+ {"version":3,"file":"operations.test-spec.d.ts","names":[],"sources":["../../src/tests/operations.test-spec.ts"],"sourcesContent":[],"mappings":";;;cAEa,cA4BX,4BAAA,CA5BuB"}
@@ -0,0 +1,36 @@
1
+ import { defineTestSpec } from "@contractspec/lib.contracts";
2
+
3
+ //#region src/tests/operations.test-spec.ts
4
+ const GetTrackTest = defineTestSpec({
5
+ meta: {
6
+ key: "learningJourney.platformTour.getTrack.test",
7
+ version: "1.0.0",
8
+ stability: "experimental",
9
+ owners: ["@example.learning-journey-platform-tour"],
10
+ description: "Test for getting platform tour track",
11
+ tags: ["test"]
12
+ },
13
+ target: {
14
+ type: "operation",
15
+ operation: {
16
+ key: "learningJourney.platformTour.getTrack",
17
+ version: "1.0.0"
18
+ }
19
+ },
20
+ scenarios: [{
21
+ key: "success",
22
+ when: { operation: { key: "learningJourney.platformTour.getTrack" } },
23
+ then: [{
24
+ type: "expectOutput",
25
+ match: {}
26
+ }]
27
+ }, {
28
+ key: "error",
29
+ when: { operation: { key: "learningJourney.platformTour.getTrack" } },
30
+ then: [{ type: "expectError" }]
31
+ }]
32
+ });
33
+
34
+ //#endregion
35
+ export { GetTrackTest };
36
+ //# sourceMappingURL=operations.test-spec.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"operations.test-spec.js","names":[],"sources":["../../src/tests/operations.test-spec.ts"],"sourcesContent":["import { defineTestSpec } from '@contractspec/lib.contracts';\n\nexport const GetTrackTest = defineTestSpec({\n meta: {\n key: 'learningJourney.platformTour.getTrack.test',\n version: '1.0.0',\n stability: 'experimental',\n owners: ['@example.learning-journey-platform-tour'],\n description: 'Test for getting platform tour track',\n tags: ['test'],\n },\n target: {\n type: 'operation',\n operation: {\n key: 'learningJourney.platformTour.getTrack',\n version: '1.0.0',\n },\n },\n scenarios: [\n {\n key: 'success',\n when: { operation: { key: 'learningJourney.platformTour.getTrack' } },\n then: [{ type: 'expectOutput', match: {} }],\n },\n {\n key: 'error',\n when: { operation: { key: 'learningJourney.platformTour.getTrack' } },\n then: [{ type: 'expectError' }],\n },\n ],\n});\n"],"mappings":";;;AAEA,MAAa,eAAe,eAAe;CACzC,MAAM;EACJ,KAAK;EACL,SAAS;EACT,WAAW;EACX,QAAQ,CAAC,0CAA0C;EACnD,aAAa;EACb,MAAM,CAAC,OAAO;EACf;CACD,QAAQ;EACN,MAAM;EACN,WAAW;GACT,KAAK;GACL,SAAS;GACV;EACF;CACD,WAAW,CACT;EACE,KAAK;EACL,MAAM,EAAE,WAAW,EAAE,KAAK,yCAAyC,EAAE;EACrE,MAAM,CAAC;GAAE,MAAM;GAAgB,OAAO,EAAE;GAAE,CAAC;EAC5C,EACD;EACE,KAAK;EACL,MAAM,EAAE,WAAW,EAAE,KAAK,yCAAyC,EAAE;EACrE,MAAM,CAAC,EAAE,MAAM,eAAe,CAAC;EAChC,CACF;CACF,CAAC"}
@@ -0,0 +1,8 @@
1
+ import { LearningJourneyTrackSpec } from "@contractspec/module.learning-journey/track-spec";
2
+
3
+ //#region src/track.d.ts
4
+ declare const platformPrimitivesTourTrack: LearningJourneyTrackSpec;
5
+ declare const platformLearningTracks: LearningJourneyTrackSpec[];
6
+ //#endregion
7
+ export { platformLearningTracks, platformPrimitivesTourTrack };
8
+ //# sourceMappingURL=track.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"track.d.ts","names":[],"sources":["../src/track.ts"],"sourcesContent":[],"mappings":";;;cAEa,6BAA6B;cAqG7B,wBAAwB"}
package/dist/track.js ADDED
@@ -0,0 +1,106 @@
1
+ //#region src/track.ts
2
+ const platformPrimitivesTourTrack = {
3
+ id: "platform_primitives_tour",
4
+ productId: "contractspec-platform",
5
+ name: "Platform Primitives Tour",
6
+ description: "Hands-on tour across identity, audit, notifications, jobs, flags, files, and metering.",
7
+ targetUserSegment: "platform_developer",
8
+ targetRole: "developer",
9
+ totalXp: 140,
10
+ completionRewards: {
11
+ xpBonus: 20,
12
+ badgeKey: "platform_primitives"
13
+ },
14
+ steps: [
15
+ {
16
+ id: "identity_rbac",
17
+ title: "Create org and member",
18
+ description: "Create an org and add at least one member.",
19
+ order: 1,
20
+ completion: {
21
+ eventName: "org.member.added",
22
+ sourceModule: "@contractspec/lib.identity-rbac"
23
+ },
24
+ xpReward: 20,
25
+ metadata: { surface: "identity" }
26
+ },
27
+ {
28
+ id: "event_bus_audit",
29
+ title: "Emit an auditable event",
30
+ description: "Emit an event that lands in the audit log.",
31
+ order: 2,
32
+ completion: {
33
+ eventName: "audit_log.created",
34
+ sourceModule: "@contractspec/module.audit-trail"
35
+ },
36
+ xpReward: 20,
37
+ metadata: { surface: "bus+audit" }
38
+ },
39
+ {
40
+ id: "notifications",
41
+ title: "Send a notification",
42
+ description: "Send yourself a notification and verify delivery.",
43
+ order: 3,
44
+ completion: {
45
+ eventName: "notification.sent",
46
+ sourceModule: "@contractspec/module.notifications"
47
+ },
48
+ xpReward: 20,
49
+ metadata: { surface: "notifications" }
50
+ },
51
+ {
52
+ id: "jobs_scheduler",
53
+ title: "Schedule and run a job",
54
+ description: "Schedule a background job and let it run once.",
55
+ order: 4,
56
+ completion: {
57
+ eventName: "job.completed",
58
+ sourceModule: "@contractspec/lib.jobs"
59
+ },
60
+ xpReward: 20,
61
+ metadata: { surface: "jobs" }
62
+ },
63
+ {
64
+ id: "feature_flags",
65
+ title: "Create and toggle a feature flag",
66
+ description: "Create a feature flag and toggle it at least once.",
67
+ order: 5,
68
+ completion: {
69
+ eventName: "flag.toggled",
70
+ sourceModule: "@contractspec/lib.feature-flags"
71
+ },
72
+ xpReward: 20,
73
+ metadata: { surface: "feature-flags" }
74
+ },
75
+ {
76
+ id: "files_attachments",
77
+ title: "Attach a file",
78
+ description: "Upload and attach a file to any entity.",
79
+ order: 6,
80
+ completion: {
81
+ eventName: "attachment.attached",
82
+ sourceModule: "@contractspec/lib.files"
83
+ },
84
+ xpReward: 20,
85
+ metadata: { surface: "files" }
86
+ },
87
+ {
88
+ id: "usage_metering",
89
+ title: "Record usage",
90
+ description: "Emit a usage metric (regeneration, agent run, or similar).",
91
+ order: 7,
92
+ completion: {
93
+ eventName: "usage.recorded",
94
+ sourceModule: "@contractspec/lib.metering"
95
+ },
96
+ xpReward: 20,
97
+ metadata: { surface: "metering" }
98
+ }
99
+ ],
100
+ metadata: { surfacedIn: ["studio/learning", "platform/dev-center"] }
101
+ };
102
+ const platformLearningTracks = [platformPrimitivesTourTrack];
103
+
104
+ //#endregion
105
+ export { platformLearningTracks, platformPrimitivesTourTrack };
106
+ //# sourceMappingURL=track.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"track.js","names":[],"sources":["../src/track.ts"],"sourcesContent":["import type { LearningJourneyTrackSpec } from '@contractspec/module.learning-journey/track-spec';\n\nexport const platformPrimitivesTourTrack: LearningJourneyTrackSpec = {\n id: 'platform_primitives_tour',\n productId: 'contractspec-platform',\n name: 'Platform Primitives Tour',\n description:\n 'Hands-on tour across identity, audit, notifications, jobs, flags, files, and metering.',\n targetUserSegment: 'platform_developer',\n targetRole: 'developer',\n totalXp: 140,\n completionRewards: { xpBonus: 20, badgeKey: 'platform_primitives' },\n steps: [\n {\n id: 'identity_rbac',\n title: 'Create org and member',\n description: 'Create an org and add at least one member.',\n order: 1,\n completion: {\n eventName: 'org.member.added',\n sourceModule: '@contractspec/lib.identity-rbac',\n },\n xpReward: 20,\n metadata: { surface: 'identity' },\n },\n {\n id: 'event_bus_audit',\n title: 'Emit an auditable event',\n description: 'Emit an event that lands in the audit log.',\n order: 2,\n completion: {\n eventName: 'audit_log.created',\n sourceModule: '@contractspec/module.audit-trail',\n },\n xpReward: 20,\n metadata: { surface: 'bus+audit' },\n },\n {\n id: 'notifications',\n title: 'Send a notification',\n description: 'Send yourself a notification and verify delivery.',\n order: 3,\n completion: {\n eventName: 'notification.sent',\n sourceModule: '@contractspec/module.notifications',\n },\n xpReward: 20,\n metadata: { surface: 'notifications' },\n },\n {\n id: 'jobs_scheduler',\n title: 'Schedule and run a job',\n description: 'Schedule a background job and let it run once.',\n order: 4,\n completion: {\n eventName: 'job.completed',\n sourceModule: '@contractspec/lib.jobs',\n },\n xpReward: 20,\n metadata: { surface: 'jobs' },\n },\n {\n id: 'feature_flags',\n title: 'Create and toggle a feature flag',\n description: 'Create a feature flag and toggle it at least once.',\n order: 5,\n completion: {\n eventName: 'flag.toggled',\n sourceModule: '@contractspec/lib.feature-flags',\n },\n xpReward: 20,\n metadata: { surface: 'feature-flags' },\n },\n {\n id: 'files_attachments',\n title: 'Attach a file',\n description: 'Upload and attach a file to any entity.',\n order: 6,\n completion: {\n eventName: 'attachment.attached',\n sourceModule: '@contractspec/lib.files',\n },\n xpReward: 20,\n metadata: { surface: 'files' },\n },\n {\n id: 'usage_metering',\n title: 'Record usage',\n description: 'Emit a usage metric (regeneration, agent run, or similar).',\n order: 7,\n completion: {\n eventName: 'usage.recorded',\n sourceModule: '@contractspec/lib.metering',\n },\n xpReward: 20,\n metadata: { surface: 'metering' },\n },\n ],\n metadata: {\n surfacedIn: ['studio/learning', 'platform/dev-center'],\n },\n};\n\nexport const platformLearningTracks: LearningJourneyTrackSpec[] = [\n platformPrimitivesTourTrack,\n];\n"],"mappings":";AAEA,MAAa,8BAAwD;CACnE,IAAI;CACJ,WAAW;CACX,MAAM;CACN,aACE;CACF,mBAAmB;CACnB,YAAY;CACZ,SAAS;CACT,mBAAmB;EAAE,SAAS;EAAI,UAAU;EAAuB;CACnE,OAAO;EACL;GACE,IAAI;GACJ,OAAO;GACP,aAAa;GACb,OAAO;GACP,YAAY;IACV,WAAW;IACX,cAAc;IACf;GACD,UAAU;GACV,UAAU,EAAE,SAAS,YAAY;GAClC;EACD;GACE,IAAI;GACJ,OAAO;GACP,aAAa;GACb,OAAO;GACP,YAAY;IACV,WAAW;IACX,cAAc;IACf;GACD,UAAU;GACV,UAAU,EAAE,SAAS,aAAa;GACnC;EACD;GACE,IAAI;GACJ,OAAO;GACP,aAAa;GACb,OAAO;GACP,YAAY;IACV,WAAW;IACX,cAAc;IACf;GACD,UAAU;GACV,UAAU,EAAE,SAAS,iBAAiB;GACvC;EACD;GACE,IAAI;GACJ,OAAO;GACP,aAAa;GACb,OAAO;GACP,YAAY;IACV,WAAW;IACX,cAAc;IACf;GACD,UAAU;GACV,UAAU,EAAE,SAAS,QAAQ;GAC9B;EACD;GACE,IAAI;GACJ,OAAO;GACP,aAAa;GACb,OAAO;GACP,YAAY;IACV,WAAW;IACX,cAAc;IACf;GACD,UAAU;GACV,UAAU,EAAE,SAAS,iBAAiB;GACvC;EACD;GACE,IAAI;GACJ,OAAO;GACP,aAAa;GACb,OAAO;GACP,YAAY;IACV,WAAW;IACX,cAAc;IACf;GACD,UAAU;GACV,UAAU,EAAE,SAAS,SAAS;GAC/B;EACD;GACE,IAAI;GACJ,OAAO;GACP,aAAa;GACb,OAAO;GACP,YAAY;IACV,WAAW;IACX,cAAc;IACf;GACD,UAAU;GACV,UAAU,EAAE,SAAS,YAAY;GAClC;EACF;CACD,UAAU,EACR,YAAY,CAAC,mBAAmB,sBAAsB,EACvD;CACF;AAED,MAAa,yBAAqD,CAChE,4BACD"}
package/example.ts ADDED
@@ -0,0 +1 @@
1
+ export { default } from './src/example';
package/package.json ADDED
@@ -0,0 +1,66 @@
1
+ {
2
+ "name": "@contractspec/example.learning-journey-platform-tour",
3
+ "version": "0.0.0-canary-20260113162409",
4
+ "description": "Learning journey track covering ContractSpec platform primitives.",
5
+ "type": "module",
6
+ "types": "./dist/index.d.ts",
7
+ "exports": {
8
+ ".": "./dist/index.js",
9
+ "./docs": "./dist/docs/index.js",
10
+ "./docs/platform-tour.docblock": "./dist/docs/platform-tour.docblock.js",
11
+ "./example": "./dist/example.js",
12
+ "./handlers/demo.handlers": "./dist/handlers/demo.handlers.js",
13
+ "./learning-journey-platform-tour.feature": "./dist/learning-journey-platform-tour.feature.js",
14
+ "./operations": "./dist/operations/index.js",
15
+ "./presentations": "./dist/presentations/index.js",
16
+ "./tests/operations.test-spec": "./dist/tests/operations.test-spec.js",
17
+ "./track": "./dist/track.js",
18
+ "./*": "./*"
19
+ },
20
+ "scripts": {
21
+ "publish:pkg": "bun publish --tolerate-republish --ignore-scripts --verbose",
22
+ "publish:pkg:canary": "bun publish:pkg --tag canary",
23
+ "build": "bun build:types && bun build:bundle",
24
+ "build:bundle": "tsdown",
25
+ "build:types": "tsc --noEmit",
26
+ "dev": "bun build:bundle --watch",
27
+ "clean": "rimraf dist .turbo",
28
+ "lint": "bun lint:fix",
29
+ "lint:fix": "eslint src --fix",
30
+ "lint:check": "eslint src"
31
+ },
32
+ "dependencies": {
33
+ "@contractspec/lib.contracts": "0.0.0-canary-20260113162409",
34
+ "@contractspec/lib.schema": "0.0.0-canary-20260113162409",
35
+ "@contractspec/module.learning-journey": "0.0.0-canary-20260113162409"
36
+ },
37
+ "devDependencies": {
38
+ "@contractspec/tool.tsdown": "0.0.0-canary-20260113162409",
39
+ "@contractspec/tool.typescript": "0.0.0-canary-20260113162409",
40
+ "tsdown": "^0.19.0",
41
+ "typescript": "^5.9.3"
42
+ },
43
+ "publishConfig": {
44
+ "exports": {
45
+ ".": "./dist/index.js",
46
+ "./contracts": "./dist/contracts/index.js",
47
+ "./docs": "./dist/docs/index.js",
48
+ "./docs/platform-tour.docblock": "./dist/docs/platform-tour.docblock.js",
49
+ "./example": "./dist/example.js",
50
+ "./handlers/demo.handlers": "./dist/handlers/demo.handlers.js",
51
+ "./learning-journey-platform-tour.feature": "./dist/learning-journey-platform-tour.feature.js",
52
+ "./presentations": "./dist/presentations/index.js",
53
+ "./track": "./dist/track.js",
54
+ "./*": "./*"
55
+ },
56
+ "registry": "https://registry.npmjs.org/",
57
+ "access": "public"
58
+ },
59
+ "license": "MIT",
60
+ "repository": {
61
+ "type": "git",
62
+ "url": "https://github.com/lssm-tech/contractspec.git",
63
+ "directory": "packages/examples/learning-journey-platform-tour"
64
+ },
65
+ "homepage": "https://contractspec.io"
66
+ }
@@ -0,0 +1 @@
1
+ import './platform-tour.docblock';
@@ -0,0 +1,40 @@
1
+ import type { DocBlock } from '@contractspec/lib.contracts/docs';
2
+ import { registerDocBlocks } from '@contractspec/lib.contracts/docs';
3
+
4
+ const platformTourDocBlocks: DocBlock[] = [
5
+ {
6
+ id: 'docs.learning-journey.platform-tour',
7
+ title: 'Learning Journey — Platform Primitives Tour',
8
+ summary:
9
+ 'Cross-module tour that touches identity, audit, notifications, jobs, feature flags, files, and metering.',
10
+ kind: 'reference',
11
+ visibility: 'public',
12
+ route: '/docs/learning-journey/platform-tour',
13
+ tags: ['learning', 'platform', 'onboarding'],
14
+ body: `## Track
15
+ - **Key**: \`platform_primitives_tour\`
16
+ - **Persona**: platform developer exploring primitives
17
+ - **Goal**: Touch each cross-cutting module once, event-driven completion
18
+
19
+ ## Steps & Events
20
+ 1) \`identity_rbac\` → \`org.member.added\`
21
+ 2) \`event_bus_audit\` → \`audit_log.created\`
22
+ 3) \`notifications\` → \`notification.sent\`
23
+ 4) \`jobs_scheduler\` → \`job.completed\`
24
+ 5) \`feature_flags\` → \`flag.toggled\`
25
+ 6) \`files_attachments\` → \`attachment.attached\`
26
+ 7) \`usage_metering\` → \`usage.recorded\`
27
+
28
+ XP: 20 per step, 20 bonus XP upon completion.
29
+
30
+ ## Wiring
31
+ - Tracks export from \`@contractspec/example.learning-journey-platform-tour/track\`.
32
+ - Use onboarding API to surface progress:
33
+ - \`learning.onboarding.listTracks\`
34
+ - \`learning.onboarding.getProgress\`
35
+ - \`learning.onboarding.recordEvent\` wired from each module's event bus handlers.
36
+ - Align event payloads with modules: identity-rbac, audit-trail, notifications, jobs, feature-flags, files, metering.`,
37
+ },
38
+ ];
39
+
40
+ registerDocBlocks(platformTourDocBlocks);
package/src/example.ts ADDED
@@ -0,0 +1,33 @@
1
+ import { defineExample } from '@contractspec/lib.contracts';
2
+
3
+ const example = defineExample({
4
+ meta: {
5
+ key: 'learning-journey-platform-tour',
6
+ version: '1.0.0',
7
+ title: 'Learning Journey — Platform Tour',
8
+ description:
9
+ 'Learning journey track + contracts + presentations for a platform tour.',
10
+ kind: 'template',
11
+ visibility: 'public',
12
+ stability: 'experimental',
13
+ owners: ['@platform.core'],
14
+ tags: ['learning', 'journey', 'platform-tour'],
15
+ },
16
+ docs: {
17
+ rootDocId: 'docs.examples.platform-tour',
18
+ goalDocId: 'docs.examples.platform-tour.goal',
19
+ usageDocId: 'docs.examples.platform-tour.usage',
20
+ },
21
+ entrypoints: {
22
+ packageName: '@contractspec/example.learning-journey-platform-tour',
23
+ docs: './docs',
24
+ },
25
+ surfaces: {
26
+ templates: true,
27
+ sandbox: { enabled: true, modes: ['markdown', 'playground'] },
28
+ studio: { enabled: true, installable: true },
29
+ mcp: { enabled: true },
30
+ },
31
+ });
32
+
33
+ export default example;
@@ -0,0 +1,50 @@
1
+ import { platformPrimitivesTourTrack } from '../track';
2
+
3
+ interface EmitParams {
4
+ learnerId: string;
5
+ occurredAt?: Date;
6
+ payload?: Record<string, unknown>;
7
+ }
8
+
9
+ interface LearningJourneyEvent {
10
+ learnerId: string;
11
+ name: string;
12
+ occurredAt: Date;
13
+ trackId: string;
14
+ payload?: Record<string, unknown>;
15
+ }
16
+
17
+ type RecordEvent = (event: LearningJourneyEvent) => unknown;
18
+
19
+ export const platformTourEvents = [
20
+ 'org.member.added',
21
+ 'audit_log.created',
22
+ 'notification.sent',
23
+ 'job.completed',
24
+ 'flag.toggled',
25
+ 'attachment.attached',
26
+ 'usage.recorded',
27
+ ] as const;
28
+
29
+ export type PlatformEvent = (typeof platformTourEvents)[number];
30
+
31
+ export const emitPlatformTourEvent = (
32
+ eventName: PlatformEvent,
33
+ { learnerId, occurredAt = new Date(), payload }: EmitParams,
34
+ record?: RecordEvent
35
+ ) => {
36
+ const event: LearningJourneyEvent = {
37
+ learnerId,
38
+ name: eventName,
39
+ occurredAt,
40
+ payload,
41
+ trackId: platformPrimitivesTourTrack.id,
42
+ };
43
+ return record ? record(event) : event;
44
+ };
45
+
46
+ export const emitAllPlatformTourEvents = (
47
+ params: EmitParams,
48
+ record?: RecordEvent
49
+ ) =>
50
+ platformTourEvents.map((name) => emitPlatformTourEvent(name, params, record));
package/src/index.ts ADDED
@@ -0,0 +1,7 @@
1
+ export * from './track';
2
+ export * from './docs';
3
+ export * from './operations';
4
+ export * from './handlers/demo.handlers';
5
+ export * from './presentations';
6
+ export * from './learning-journey-platform-tour.feature';
7
+ export { default as example } from './example';
@@ -0,0 +1,66 @@
1
+ /**
2
+ * Learning Journey Platform Tour Feature Module Specification
3
+ *
4
+ * Defines the feature module for platform primitives tour journey.
5
+ */
6
+ import { defineFeature } from '@contractspec/lib.contracts';
7
+
8
+ /**
9
+ * Learning Journey Platform Tour feature module that bundles
10
+ * platform-specific tour track operations and presentations.
11
+ */
12
+ export const LearningJourneyPlatformTourFeature = defineFeature({
13
+ meta: {
14
+ key: 'learning-journey-platform-tour',
15
+ version: '1.0.0',
16
+ title: 'Learning Journey: Platform Tour',
17
+ description:
18
+ 'Platform primitives tour journey for exploring ContractSpec core features',
19
+ domain: 'learning-journey',
20
+ owners: ['@examples.learning-journey.platform-tour'],
21
+ tags: ['learning', 'platform', 'tour', 'journey'],
22
+ stability: 'experimental',
23
+ },
24
+
25
+ // All contract operations included in this feature
26
+ operations: [
27
+ { key: 'learningJourney.platformTour.recordEvent', version: '1.0.0' },
28
+ { key: 'learningJourney.platformTour.getTrack', version: '1.0.0' },
29
+ ],
30
+
31
+ // Events emitted by this feature
32
+ events: [],
33
+
34
+ // Presentations associated with this feature
35
+ presentations: [
36
+ { key: 'learning.journey.platform.track', version: '1.0.0' },
37
+ { key: 'learning.journey.platform.widget', version: '1.0.0' },
38
+ ],
39
+
40
+ // Link operations to their primary presentations
41
+ opToPresentation: [
42
+ {
43
+ op: { key: 'learningJourney.platformTour.getTrack', version: '1.0.0' },
44
+ pres: { key: 'learning.journey.platform.track', version: '1.0.0' },
45
+ },
46
+ ],
47
+
48
+ // Target requirements for multi-surface rendering
49
+ presentationsTargets: [
50
+ {
51
+ key: 'learning.journey.platform.track',
52
+ version: '1.0.0',
53
+ targets: ['react', 'markdown', 'application/json'],
54
+ },
55
+ {
56
+ key: 'learning.journey.platform.widget',
57
+ version: '1.0.0',
58
+ targets: ['react'],
59
+ },
60
+ ],
61
+
62
+ // Capability requirements
63
+ capabilities: {
64
+ requires: [{ key: 'identity', version: '1.0.0' }],
65
+ },
66
+ });
@@ -0,0 +1,49 @@
1
+ import { describe, expect, it } from 'bun:test';
2
+
3
+ import {
4
+ GetPlatformTourTrack,
5
+ RecordPlatformTourEvent,
6
+ platformTourContracts,
7
+ } from './index';
8
+ import { platformPrimitivesTourTrack } from '../track';
9
+ import {
10
+ emitPlatformTourEvent,
11
+ platformTourEvents,
12
+ } from '../handlers/demo.handlers';
13
+ import type { PlatformEvent } from '../handlers/demo.handlers';
14
+
15
+ describe('platform tour contracts', () => {
16
+ it('exposes track metadata', () => {
17
+ expect(platformTourContracts.track.id).toBe('platform_primitives_tour');
18
+ expect(platformTourContracts.track.steps.length).toBeGreaterThan(0);
19
+ expect(GetPlatformTourTrack.meta.key).toBe(
20
+ 'learningJourney.platformTour.getTrack'
21
+ );
22
+ });
23
+
24
+ it('allows recording events via demo handler', async () => {
25
+ const [step] = platformPrimitivesTourTrack.steps;
26
+ expect(step).toBeDefined();
27
+ if (!step) throw new Error('Expected at least one platform tour step');
28
+
29
+ const eventName = step.completion.eventName;
30
+ const isPlatformEvent = (value: string): value is PlatformEvent =>
31
+ platformTourEvents.includes(value as PlatformEvent);
32
+
33
+ expect(isPlatformEvent(eventName)).toBe(true);
34
+ if (!isPlatformEvent(eventName)) {
35
+ throw new Error(`Unexpected event name: ${eventName}`);
36
+ }
37
+
38
+ const result = await emitPlatformTourEvent(eventName, {
39
+ learnerId: 'demo-learner',
40
+ });
41
+ expect(result).toBeDefined();
42
+ });
43
+
44
+ it('exposes record event contract', () => {
45
+ expect(RecordPlatformTourEvent.meta.key).toBe(
46
+ 'learningJourney.platformTour.recordEvent'
47
+ );
48
+ });
49
+ });
@@ -0,0 +1,122 @@
1
+ import { ScalarTypeEnum, defineSchemaModel } from '@contractspec/lib.schema';
2
+ import { defineCommand, defineQuery } from '@contractspec/lib.contracts';
3
+
4
+ import { platformPrimitivesTourTrack } from '../track';
5
+
6
+ const OWNERS = ['examples.learning-journey.platform-tour'] as const;
7
+
8
+ const StepModel = defineSchemaModel({
9
+ name: 'PlatformTourStep',
10
+ description: 'Step metadata for platform primitives tour',
11
+ fields: {
12
+ id: { type: ScalarTypeEnum.String_unsecure(), isOptional: false },
13
+ title: { type: ScalarTypeEnum.String_unsecure(), isOptional: false },
14
+ description: { type: ScalarTypeEnum.String_unsecure(), isOptional: true },
15
+ completionEvent: {
16
+ type: ScalarTypeEnum.String_unsecure(),
17
+ isOptional: false,
18
+ },
19
+ sourceModule: { type: ScalarTypeEnum.String_unsecure(), isOptional: true },
20
+ xpReward: { type: ScalarTypeEnum.Int_unsecure(), isOptional: true },
21
+ order: { type: ScalarTypeEnum.Int_unsecure(), isOptional: true },
22
+ },
23
+ });
24
+
25
+ export const PlatformTourTrackModel = defineSchemaModel({
26
+ name: 'PlatformTourTrack',
27
+ description: 'Platform primitives tour track definition',
28
+ fields: {
29
+ id: { type: ScalarTypeEnum.String_unsecure(), isOptional: false },
30
+ name: { type: ScalarTypeEnum.String_unsecure(), isOptional: false },
31
+ description: { type: ScalarTypeEnum.String_unsecure(), isOptional: true },
32
+ totalXp: { type: ScalarTypeEnum.Int_unsecure(), isOptional: true },
33
+ completionXpBonus: {
34
+ type: ScalarTypeEnum.Int_unsecure(),
35
+ isOptional: true,
36
+ },
37
+ completionBadgeKey: {
38
+ type: ScalarTypeEnum.String_unsecure(),
39
+ isOptional: true,
40
+ },
41
+ streakHoursWindow: {
42
+ type: ScalarTypeEnum.Int_unsecure(),
43
+ isOptional: true,
44
+ },
45
+ streakBonusXp: { type: ScalarTypeEnum.Int_unsecure(), isOptional: true },
46
+ steps: { type: StepModel, isArray: true, isOptional: false },
47
+ },
48
+ });
49
+
50
+ const TrackResponseModel = defineSchemaModel({
51
+ name: 'PlatformTourTrackResponse',
52
+ description: 'Response wrapper for platform tour track',
53
+ fields: {
54
+ track: { type: PlatformTourTrackModel, isOptional: false },
55
+ },
56
+ });
57
+
58
+ const RecordDemoEventInput = defineSchemaModel({
59
+ name: 'PlatformTourRecordEventInput',
60
+ description: 'Emit a demo event to advance platform tour steps',
61
+ fields: {
62
+ learnerId: { type: ScalarTypeEnum.String_unsecure(), isOptional: false },
63
+ eventName: { type: ScalarTypeEnum.String_unsecure(), isOptional: false },
64
+ payload: { type: ScalarTypeEnum.JSON(), isOptional: true },
65
+ occurredAt: { type: ScalarTypeEnum.DateTime(), isOptional: true },
66
+ },
67
+ });
68
+
69
+ const SuccessModel = defineSchemaModel({
70
+ name: 'PlatformTourSuccess',
71
+ description: 'Generic success response',
72
+ fields: {
73
+ success: { type: ScalarTypeEnum.Boolean(), isOptional: false },
74
+ },
75
+ });
76
+
77
+ export const GetPlatformTourTrack = defineQuery({
78
+ meta: {
79
+ key: 'learningJourney.platformTour.getTrack',
80
+ version: '1.0.0',
81
+ stability: 'experimental',
82
+ owners: [...OWNERS],
83
+ tags: ['learning', 'platform', 'tour'],
84
+ description: 'Fetch platform primitives tour track definition.',
85
+ goal: 'Expose track metadata to UIs and templates.',
86
+ context: 'Called by Studio/Playground to render journey steps.',
87
+ },
88
+ io: {
89
+ input: defineSchemaModel({
90
+ name: 'PlatformTourTrackInput',
91
+ description: 'Track input',
92
+ fields: {},
93
+ }),
94
+ output: TrackResponseModel,
95
+ },
96
+ policy: { auth: 'user' },
97
+ });
98
+
99
+ export const RecordPlatformTourEvent = defineCommand({
100
+ meta: {
101
+ key: 'learningJourney.platformTour.recordEvent',
102
+ version: '1.0.0',
103
+ stability: 'experimental',
104
+ owners: [...OWNERS],
105
+ tags: ['learning', 'platform', 'tour'],
106
+ description: 'Record an event to advance platform tour progress.',
107
+ goal: 'Advance steps via domain events in demo/sandbox contexts.',
108
+ context:
109
+ 'Called by handlers or demo scripts to emit step completion events.',
110
+ },
111
+ io: {
112
+ input: RecordDemoEventInput,
113
+ output: SuccessModel,
114
+ },
115
+ policy: { auth: 'user' },
116
+ });
117
+
118
+ export const platformTourContracts = {
119
+ GetPlatformTourTrack,
120
+ RecordPlatformTourEvent,
121
+ track: platformPrimitivesTourTrack,
122
+ };
@@ -0,0 +1,51 @@
1
+ import { definePresentation, StabilityEnum, type PresentationSpecMeta } from '@contractspec/lib.contracts';
2
+ import { PlatformTourTrackModel } from '../operations';
3
+
4
+ const baseMeta: Pick<
5
+ PresentationSpecMeta,
6
+ 'domain' | 'owners' | 'tags' | 'title' | 'stability' | 'goal' | 'context'
7
+ > = {
8
+ domain: 'learning-journey',
9
+ title: 'Platform Tour',
10
+ owners: ['@examples.learning-journey.platform-tour'],
11
+ tags: ['learning', 'platform', 'tour'],
12
+ stability: StabilityEnum.Experimental,
13
+ goal: 'Visualize platform tour progress',
14
+ context: 'Used in platform tour dashboard and widgets',
15
+ };
16
+
17
+ export const PlatformTourTrackPresentation = definePresentation({
18
+ meta: {
19
+ key: 'learning.journey.platform.track',
20
+ version: '1.0.0',
21
+ description: 'Platform primitives tour track detail',
22
+ ...baseMeta,
23
+ },
24
+ source: {
25
+ type: 'component',
26
+ framework: 'react',
27
+ componentKey: 'LearningTrackDetail',
28
+ props: PlatformTourTrackModel,
29
+ },
30
+ targets: ['react', 'markdown', 'application/json'],
31
+ });
32
+
33
+ export const PlatformTourWidgetPresentation = definePresentation({
34
+ meta: {
35
+ key: 'learning.journey.platform.widget',
36
+ version: '1.0.0',
37
+ description: 'Compact widget for platform tour progress',
38
+ ...baseMeta,
39
+ },
40
+ source: {
41
+ type: 'component',
42
+ framework: 'react',
43
+ componentKey: 'LearningTrackProgressWidget',
44
+ },
45
+ targets: ['react'],
46
+ });
47
+
48
+ export const platformTourPresentations = [
49
+ PlatformTourTrackPresentation,
50
+ PlatformTourWidgetPresentation,
51
+ ];