@contractspec/example.learning-journey-studio-onboarding 3.7.6 → 3.7.10

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.
@@ -1,122 +1,122 @@
1
- import { ScalarTypeEnum, defineSchemaModel } from '@contractspec/lib.schema';
2
1
  import { defineCommand, defineQuery } from '@contractspec/lib.contracts-spec';
2
+ import { defineSchemaModel, ScalarTypeEnum } from '@contractspec/lib.schema';
3
3
 
4
4
  import { studioGettingStartedTrack } from '../track';
5
5
 
6
6
  const OWNERS = ['examples.learning-journey.studio-onboarding'] as const;
7
7
 
8
8
  const StepModel = defineSchemaModel({
9
- name: 'StudioOnboardingStep',
10
- description: 'Step metadata for Studio onboarding journey',
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
- },
9
+ name: 'StudioOnboardingStep',
10
+ description: 'Step metadata for Studio onboarding journey',
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
23
  });
24
24
 
25
25
  export const StudioOnboardingTrackModel = defineSchemaModel({
26
- name: 'StudioOnboardingTrack',
27
- description: 'Studio onboarding 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
- },
26
+ name: 'StudioOnboardingTrack',
27
+ description: 'Studio onboarding 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
48
  });
49
49
 
50
50
  const TrackResponseModel = defineSchemaModel({
51
- name: 'StudioOnboardingTrackResponse',
52
- description: 'Response wrapper for studio onboarding track',
53
- fields: {
54
- track: { type: StudioOnboardingTrackModel, isOptional: false },
55
- },
51
+ name: 'StudioOnboardingTrackResponse',
52
+ description: 'Response wrapper for studio onboarding track',
53
+ fields: {
54
+ track: { type: StudioOnboardingTrackModel, isOptional: false },
55
+ },
56
56
  });
57
57
 
58
58
  const RecordDemoEventInput = defineSchemaModel({
59
- name: 'StudioOnboardingRecordEventInput',
60
- description: 'Emit a demo event to advance Studio onboarding 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
- },
59
+ name: 'StudioOnboardingRecordEventInput',
60
+ description: 'Emit a demo event to advance Studio onboarding 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
67
  });
68
68
 
69
69
  const SuccessModel = defineSchemaModel({
70
- name: 'StudioOnboardingSuccess',
71
- description: 'Generic success response',
72
- fields: {
73
- success: { type: ScalarTypeEnum.Boolean(), isOptional: false },
74
- },
70
+ name: 'StudioOnboardingSuccess',
71
+ description: 'Generic success response',
72
+ fields: {
73
+ success: { type: ScalarTypeEnum.Boolean(), isOptional: false },
74
+ },
75
75
  });
76
76
 
77
77
  export const GetStudioOnboardingTrack = defineQuery({
78
- meta: {
79
- key: 'learningJourney.studioOnboarding.getTrack',
80
- version: '1.0.0',
81
- stability: 'experimental',
82
- owners: [...OWNERS],
83
- tags: ['learning', 'onboarding', 'studio'],
84
- description: 'Fetch the Studio onboarding 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: 'StudioOnboardingTrackInput',
91
- description: 'Track input',
92
- fields: {},
93
- }),
94
- output: TrackResponseModel,
95
- },
96
- policy: { auth: 'user' },
78
+ meta: {
79
+ key: 'learningJourney.studioOnboarding.getTrack',
80
+ version: '1.0.0',
81
+ stability: 'experimental',
82
+ owners: [...OWNERS],
83
+ tags: ['learning', 'onboarding', 'studio'],
84
+ description: 'Fetch the Studio onboarding 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: 'StudioOnboardingTrackInput',
91
+ description: 'Track input',
92
+ fields: {},
93
+ }),
94
+ output: TrackResponseModel,
95
+ },
96
+ policy: { auth: 'user' },
97
97
  });
98
98
 
99
99
  export const RecordStudioOnboardingEvent = defineCommand({
100
- meta: {
101
- key: 'learningJourney.studioOnboarding.recordEvent',
102
- version: '1.0.0',
103
- stability: 'experimental',
104
- owners: [...OWNERS],
105
- tags: ['learning', 'onboarding', 'studio'],
106
- description: 'Record an event to advance Studio onboarding 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' },
100
+ meta: {
101
+ key: 'learningJourney.studioOnboarding.recordEvent',
102
+ version: '1.0.0',
103
+ stability: 'experimental',
104
+ owners: [...OWNERS],
105
+ tags: ['learning', 'onboarding', 'studio'],
106
+ description: 'Record an event to advance Studio onboarding 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
116
  });
117
117
 
118
118
  export const studioOnboardingContracts = {
119
- GetStudioOnboardingTrack,
120
- RecordStudioOnboardingEvent,
121
- track: studioGettingStartedTrack,
119
+ GetStudioOnboardingTrack,
120
+ RecordStudioOnboardingEvent,
121
+ track: studioGettingStartedTrack,
122
122
  };
@@ -1,57 +1,57 @@
1
1
  import {
2
- definePresentation,
3
- StabilityEnum,
4
- type PresentationSpecMeta,
2
+ definePresentation,
3
+ type PresentationSpecMeta,
4
+ StabilityEnum,
5
5
  } from '@contractspec/lib.contracts-spec';
6
6
  import { StudioOnboardingTrackModel } from '../operations';
7
7
 
8
8
  const baseMeta: Pick<
9
- PresentationSpecMeta,
10
- 'domain' | 'owners' | 'tags' | 'title' | 'stability'
9
+ PresentationSpecMeta,
10
+ 'domain' | 'owners' | 'tags' | 'title' | 'stability'
11
11
  > = {
12
- domain: 'learning-journey',
13
- title: 'Studio Onboarding',
14
- owners: ['@examples.learning-journey.studio-onboarding'] as string[],
15
- tags: ['learning', 'onboarding', 'studio'] as string[],
16
- stability: StabilityEnum.Experimental,
12
+ domain: 'learning-journey',
13
+ title: 'Studio Onboarding',
14
+ owners: ['@examples.learning-journey.studio-onboarding'] as string[],
15
+ tags: ['learning', 'onboarding', 'studio'] as string[],
16
+ stability: StabilityEnum.Experimental,
17
17
  };
18
18
 
19
19
  export const StudioOnboardingTrackPresentation = definePresentation({
20
- meta: {
21
- key: 'learning.journey.studio.track',
22
- version: '1.0.0',
23
- description: 'Studio onboarding track detail',
24
- goal: 'Visualize the onboarding track for the user.',
25
- context: 'Displayed in the Studio dashboard.',
26
- ...baseMeta,
27
- },
28
- source: {
29
- type: 'component',
30
- framework: 'react',
31
- componentKey: 'LearningTrackDetail',
32
- props: StudioOnboardingTrackModel,
33
- },
34
- targets: ['react', 'markdown', 'application/json'],
20
+ meta: {
21
+ key: 'learning.journey.studio.track',
22
+ version: '1.0.0',
23
+ description: 'Studio onboarding track detail',
24
+ goal: 'Visualize the onboarding track for the user.',
25
+ context: 'Displayed in the Studio dashboard.',
26
+ ...baseMeta,
27
+ },
28
+ source: {
29
+ type: 'component',
30
+ framework: 'react',
31
+ componentKey: 'LearningTrackDetail',
32
+ props: StudioOnboardingTrackModel,
33
+ },
34
+ targets: ['react', 'markdown', 'application/json'],
35
35
  });
36
36
 
37
37
  export const StudioOnboardingWidgetPresentation = definePresentation({
38
- meta: {
39
- key: 'learning.journey.studio.widget',
40
- version: '1.0.0',
41
- description: 'Compact widget for Studio onboarding progress',
42
- goal: 'Show quick progress summary.',
43
- context: 'Displayed in the Studio sidebar or header.',
44
- ...baseMeta,
45
- },
46
- source: {
47
- type: 'component',
48
- framework: 'react',
49
- componentKey: 'LearningTrackProgressWidget',
50
- },
51
- targets: ['react'],
38
+ meta: {
39
+ key: 'learning.journey.studio.widget',
40
+ version: '1.0.0',
41
+ description: 'Compact widget for Studio onboarding progress',
42
+ goal: 'Show quick progress summary.',
43
+ context: 'Displayed in the Studio sidebar or header.',
44
+ ...baseMeta,
45
+ },
46
+ source: {
47
+ type: 'component',
48
+ framework: 'react',
49
+ componentKey: 'LearningTrackProgressWidget',
50
+ },
51
+ targets: ['react'],
52
52
  });
53
53
 
54
54
  export const studioOnboardingPresentations = [
55
- StudioOnboardingTrackPresentation,
56
- StudioOnboardingWidgetPresentation,
55
+ StudioOnboardingTrackPresentation,
56
+ StudioOnboardingWidgetPresentation,
57
57
  ];
@@ -1,31 +1,31 @@
1
1
  import { defineTestSpec } from '@contractspec/lib.contracts-spec/tests';
2
2
 
3
3
  export const GetTrackTest = defineTestSpec({
4
- meta: {
5
- key: 'learningJourney.studioOnboarding.getTrack.test',
6
- version: '1.0.0',
7
- stability: 'experimental',
8
- owners: ['@example.learning-journey-studio-onboarding'],
9
- description: 'Test for getting studio onboarding track',
10
- tags: ['test'],
11
- },
12
- target: {
13
- type: 'operation',
14
- operation: {
15
- key: 'learningJourney.studioOnboarding.getTrack',
16
- version: '1.0.0',
17
- },
18
- },
19
- scenarios: [
20
- {
21
- key: 'success',
22
- when: { operation: { key: 'learningJourney.studioOnboarding.getTrack' } },
23
- then: [{ type: 'expectOutput', match: {} }],
24
- },
25
- {
26
- key: 'error',
27
- when: { operation: { key: 'learningJourney.studioOnboarding.getTrack' } },
28
- then: [{ type: 'expectError' }],
29
- },
30
- ],
4
+ meta: {
5
+ key: 'learningJourney.studioOnboarding.getTrack.test',
6
+ version: '1.0.0',
7
+ stability: 'experimental',
8
+ owners: ['@example.learning-journey-studio-onboarding'],
9
+ description: 'Test for getting studio onboarding track',
10
+ tags: ['test'],
11
+ },
12
+ target: {
13
+ type: 'operation',
14
+ operation: {
15
+ key: 'learningJourney.studioOnboarding.getTrack',
16
+ version: '1.0.0',
17
+ },
18
+ },
19
+ scenarios: [
20
+ {
21
+ key: 'success',
22
+ when: { operation: { key: 'learningJourney.studioOnboarding.getTrack' } },
23
+ then: [{ type: 'expectOutput', match: {} }],
24
+ },
25
+ {
26
+ key: 'error',
27
+ when: { operation: { key: 'learningJourney.studioOnboarding.getTrack' } },
28
+ then: [{ type: 'expectError' }],
29
+ },
30
+ ],
31
31
  });
package/src/track.ts CHANGED
@@ -1,86 +1,86 @@
1
1
  import type { LearningJourneyTrackSpec } from '@contractspec/module.learning-journey/track-spec';
2
2
 
3
3
  export const studioGettingStartedTrack: LearningJourneyTrackSpec = {
4
- id: 'studio_getting_started',
5
- productId: 'contractspec-studio',
6
- name: 'Studio Getting Started',
7
- description:
8
- 'First 30 minutes in Studio: create a project, edit the spec, deploy/regenerate, and try key modules.',
9
- targetUserSegment: 'new_studio_user',
10
- targetRole: 'developer',
11
- totalXp: 110,
12
- streakRule: { hoursWindow: 48, bonusXp: 25 },
13
- completionRewards: { xpBonus: 25, badgeKey: 'studio_first_30m' },
14
- steps: [
15
- {
16
- id: 'choose_template',
17
- title: 'Choose a template',
18
- description: 'Create your first Studio project (starter template).',
19
- order: 1,
20
- completion: {
21
- eventName: 'studio.template.instantiated',
22
- sourceModule: '@contractspec/bundle.studio',
23
- },
24
- xpReward: 20,
25
- metadata: { surface: 'projects' },
26
- },
27
- {
28
- id: 'edit_spec',
29
- title: 'Edit the spec',
30
- description: 'Change the spec (not generated code) and save.',
31
- instructions: 'Open spec editor, tweak a contract or presentation, save.',
32
- order: 2,
33
- completion: {
34
- eventName: 'spec.changed',
35
- sourceModule: '@contractspec/bundle.studio',
36
- },
37
- xpReward: 20,
38
- metadata: { surface: 'spec-editor' },
39
- },
40
- {
41
- id: 'regenerate_app',
42
- title: 'Regenerate the app',
43
- description: 'Regenerate artifacts from the updated spec.',
44
- order: 3,
45
- completion: {
46
- eventName: 'regeneration.completed',
47
- sourceModule: '@contractspec/lib.contracts-spec/regenerator',
48
- },
49
- xpReward: 20,
50
- metadata: { surface: 'regenerator' },
51
- },
52
- {
53
- id: 'open_canvas',
54
- title: 'Open the canvas',
55
- description: 'Visit the canvas module for your project.',
56
- order: 4,
57
- completion: {
58
- eventName: 'module.navigated',
59
- sourceModule: '@contractspec/bundle.studio',
60
- payloadFilter: { moduleId: 'canvas' },
61
- },
62
- xpReward: 20,
63
- metadata: { surface: 'canvas' },
64
- },
65
- {
66
- id: 'try_evolution_mode',
67
- title: 'Try evolution mode',
68
- description: 'Request a change via Evolution, then regenerate.',
69
- order: 5,
70
- completion: {
71
- eventName: 'studio.evolution.applied',
72
- sourceModule: '@contractspec/lib.evolution',
73
- },
74
- xpReward: 30,
75
- metadata: { surface: 'evolution' },
76
- },
77
- ],
78
- metadata: {
79
- persona: 'first_run',
80
- surfacedIn: ['studio/home', 'studio/sidebar/learning'],
81
- },
4
+ id: 'studio_getting_started',
5
+ productId: 'contractspec-studio',
6
+ name: 'Studio Getting Started',
7
+ description:
8
+ 'First 30 minutes in Studio: create a project, edit the spec, deploy/regenerate, and try key modules.',
9
+ targetUserSegment: 'new_studio_user',
10
+ targetRole: 'developer',
11
+ totalXp: 110,
12
+ streakRule: { hoursWindow: 48, bonusXp: 25 },
13
+ completionRewards: { xpBonus: 25, badgeKey: 'studio_first_30m' },
14
+ steps: [
15
+ {
16
+ id: 'choose_template',
17
+ title: 'Choose a template',
18
+ description: 'Create your first Studio project (starter template).',
19
+ order: 1,
20
+ completion: {
21
+ eventName: 'studio.template.instantiated',
22
+ sourceModule: '@contractspec/bundle.studio',
23
+ },
24
+ xpReward: 20,
25
+ metadata: { surface: 'projects' },
26
+ },
27
+ {
28
+ id: 'edit_spec',
29
+ title: 'Edit the spec',
30
+ description: 'Change the spec (not generated code) and save.',
31
+ instructions: 'Open spec editor, tweak a contract or presentation, save.',
32
+ order: 2,
33
+ completion: {
34
+ eventName: 'spec.changed',
35
+ sourceModule: '@contractspec/bundle.studio',
36
+ },
37
+ xpReward: 20,
38
+ metadata: { surface: 'spec-editor' },
39
+ },
40
+ {
41
+ id: 'regenerate_app',
42
+ title: 'Regenerate the app',
43
+ description: 'Regenerate artifacts from the updated spec.',
44
+ order: 3,
45
+ completion: {
46
+ eventName: 'regeneration.completed',
47
+ sourceModule: '@contractspec/lib.contracts-spec/regenerator',
48
+ },
49
+ xpReward: 20,
50
+ metadata: { surface: 'regenerator' },
51
+ },
52
+ {
53
+ id: 'open_canvas',
54
+ title: 'Open the canvas',
55
+ description: 'Visit the canvas module for your project.',
56
+ order: 4,
57
+ completion: {
58
+ eventName: 'module.navigated',
59
+ sourceModule: '@contractspec/bundle.studio',
60
+ payloadFilter: { moduleId: 'canvas' },
61
+ },
62
+ xpReward: 20,
63
+ metadata: { surface: 'canvas' },
64
+ },
65
+ {
66
+ id: 'try_evolution_mode',
67
+ title: 'Try evolution mode',
68
+ description: 'Request a change via Evolution, then regenerate.',
69
+ order: 5,
70
+ completion: {
71
+ eventName: 'studio.evolution.applied',
72
+ sourceModule: '@contractspec/lib.evolution',
73
+ },
74
+ xpReward: 30,
75
+ metadata: { surface: 'evolution' },
76
+ },
77
+ ],
78
+ metadata: {
79
+ persona: 'first_run',
80
+ surfacedIn: ['studio/home', 'studio/sidebar/learning'],
81
+ },
82
82
  };
83
83
 
84
84
  export const studioLearningTracks: LearningJourneyTrackSpec[] = [
85
- studioGettingStartedTrack,
85
+ studioGettingStartedTrack,
86
86
  ];
package/tsconfig.json CHANGED
@@ -1,9 +1,9 @@
1
1
  {
2
- "extends": "@contractspec/tool.typescript/react-library.json",
3
- "include": ["src"],
4
- "exclude": ["node_modules"],
5
- "compilerOptions": {
6
- "rootDir": "src",
7
- "outDir": "dist"
8
- }
2
+ "extends": "@contractspec/tool.typescript/react-library.json",
3
+ "include": ["src"],
4
+ "exclude": ["node_modules"],
5
+ "compilerOptions": {
6
+ "rootDir": "src",
7
+ "outDir": "dist"
8
+ }
9
9
  }
package/tsdown.config.js CHANGED
@@ -1,16 +1,10 @@
1
- import { defineConfig, moduleLibrary, withDevExports } from '@contractspec/tool.bun';
1
+ import {
2
+ defineConfig,
3
+ moduleLibrary,
4
+ withDevExports,
5
+ } from '@contractspec/tool.bun';
2
6
 
3
7
  export default defineConfig(() => ({
4
- ...moduleLibrary,
5
- ...withDevExports,
8
+ ...moduleLibrary,
9
+ ...withDevExports,
6
10
  }));
7
-
8
-
9
-
10
-
11
-
12
-
13
-
14
-
15
-
16
-