@owlmeans/viable-common 0.0.24 → 0.0.26

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 (131) hide show
  1. package/README.md +4 -4
  2. package/agent-meta/manifest.json +2 -2
  3. package/agent-meta/skills/agent-presentation/SKILL.md +1 -1
  4. package/agent-meta/skills/viable-common/SKILL.md +115 -13
  5. package/build/blueprint/case.d.ts.map +1 -1
  6. package/build/blueprint/case.js +58 -16
  7. package/build/blueprint/case.js.map +1 -1
  8. package/build/blueprint/resolve.d.ts.map +1 -1
  9. package/build/blueprint/resolve.js +3 -0
  10. package/build/blueprint/resolve.js.map +1 -1
  11. package/build/blueprint/types.d.ts +44 -2
  12. package/build/blueprint/types.d.ts.map +1 -1
  13. package/build/blueprint/types.js +35 -1
  14. package/build/blueprint/types.js.map +1 -1
  15. package/build/branding.d.ts +5 -1
  16. package/build/branding.d.ts.map +1 -1
  17. package/build/branding.js +6 -0
  18. package/build/branding.js.map +1 -1
  19. package/build/connect/consts.d.ts +31 -43
  20. package/build/connect/consts.d.ts.map +1 -1
  21. package/build/connect/consts.js +34 -48
  22. package/build/connect/consts.js.map +1 -1
  23. package/build/connect/entrypoints.d.ts +36 -19
  24. package/build/connect/entrypoints.d.ts.map +1 -1
  25. package/build/connect/entrypoints.js +23 -4
  26. package/build/connect/entrypoints.js.map +1 -1
  27. package/build/connect/index.d.ts +0 -1
  28. package/build/connect/index.d.ts.map +1 -1
  29. package/build/connect/index.js +0 -1
  30. package/build/connect/index.js.map +1 -1
  31. package/build/connect/ops.d.ts +1 -4
  32. package/build/connect/ops.d.ts.map +1 -1
  33. package/build/connect/references.d.ts +33 -16
  34. package/build/connect/references.d.ts.map +1 -1
  35. package/build/connect/references.js +7 -1
  36. package/build/connect/references.js.map +1 -1
  37. package/build/connect/schemas.d.ts +17 -3
  38. package/build/connect/schemas.d.ts.map +1 -1
  39. package/build/connect/schemas.js +31 -5
  40. package/build/connect/schemas.js.map +1 -1
  41. package/build/connect/types.d.ts +63 -66
  42. package/build/connect/types.d.ts.map +1 -1
  43. package/build/consts.d.ts +1 -1
  44. package/build/consts.d.ts.map +1 -1
  45. package/build/consts.js +3 -0
  46. package/build/consts.js.map +1 -1
  47. package/build/design/runtime.d.ts +1 -1
  48. package/build/design/runtime.d.ts.map +1 -1
  49. package/build/metadata/types.d.ts +8 -0
  50. package/build/metadata/types.d.ts.map +1 -1
  51. package/build/metadata/types.js.map +1 -1
  52. package/build/planning/consts.d.ts +1 -1
  53. package/build/planning/consts.js +1 -1
  54. package/build/planning/helpers.d.ts +2 -1
  55. package/build/planning/helpers.d.ts.map +1 -1
  56. package/build/planning/helpers.js +5 -2
  57. package/build/planning/helpers.js.map +1 -1
  58. package/build/planning/index.d.ts +1 -0
  59. package/build/planning/index.d.ts.map +1 -1
  60. package/build/planning/index.js +1 -0
  61. package/build/planning/index.js.map +1 -1
  62. package/build/planning/landing.d.ts +25 -0
  63. package/build/planning/landing.d.ts.map +1 -0
  64. package/build/planning/landing.js +38 -0
  65. package/build/planning/landing.js.map +1 -0
  66. package/build/planning/schemas.d.ts.map +1 -1
  67. package/build/planning/schemas.js +13 -0
  68. package/build/planning/schemas.js.map +1 -1
  69. package/build/planning/types.d.ts +28 -3
  70. package/build/planning/types.d.ts.map +1 -1
  71. package/build/scaffold/consts.d.ts +8 -0
  72. package/build/scaffold/consts.d.ts.map +1 -1
  73. package/build/scaffold/consts.js +7 -0
  74. package/build/scaffold/consts.js.map +1 -1
  75. package/build/scaffold/schemas.d.ts.map +1 -1
  76. package/build/scaffold/schemas.js +257 -12
  77. package/build/scaffold/schemas.js.map +1 -1
  78. package/build/scaffold/types.d.ts +119 -4
  79. package/build/scaffold/types.d.ts.map +1 -1
  80. package/build/skills/catalogue.d.ts.map +1 -1
  81. package/build/skills/catalogue.js +150 -39
  82. package/build/skills/catalogue.js.map +1 -1
  83. package/build/skills/consts.d.ts +5 -0
  84. package/build/skills/consts.d.ts.map +1 -1
  85. package/build/skills/consts.js +8 -0
  86. package/build/skills/consts.js.map +1 -1
  87. package/build/skills/roles.d.ts.map +1 -1
  88. package/build/skills/roles.js +11 -5
  89. package/build/skills/roles.js.map +1 -1
  90. package/build/types.d.ts +30 -0
  91. package/build/types.d.ts.map +1 -1
  92. package/package.json +8 -8
  93. package/src/blueprint/case.ts +64 -16
  94. package/src/blueprint/resolve.ts +3 -0
  95. package/src/blueprint/types.ts +57 -1
  96. package/src/branding.ts +6 -0
  97. package/src/connect/consts.ts +32 -45
  98. package/src/connect/entrypoints.ts +51 -23
  99. package/src/connect/index.ts +0 -1
  100. package/src/connect/ops.ts +1 -4
  101. package/src/connect/references.ts +48 -29
  102. package/src/connect/schemas.ts +40 -11
  103. package/src/connect/types.ts +66 -69
  104. package/src/consts.ts +3 -0
  105. package/src/design/runtime.ts +1 -1
  106. package/src/metadata/types.ts +8 -0
  107. package/src/planning/consts.ts +1 -1
  108. package/src/planning/helpers.ts +5 -2
  109. package/src/planning/index.ts +1 -0
  110. package/src/planning/landing.ts +43 -0
  111. package/src/planning/schemas.ts +13 -0
  112. package/src/planning/types.ts +29 -3
  113. package/src/scaffold/consts.ts +10 -0
  114. package/src/scaffold/schemas.ts +262 -13
  115. package/src/scaffold/types.ts +105 -5
  116. package/src/skills/catalogue.ts +151 -39
  117. package/src/skills/consts.ts +8 -0
  118. package/src/skills/roles.ts +11 -5
  119. package/src/types.ts +30 -0
  120. package/tests/blueprint.spec.ts +98 -0
  121. package/tests/branding.spec.ts +21 -1
  122. package/tests/connect-convert.spec.ts +2 -8
  123. package/tests/connect-entrypoints.spec.ts +49 -28
  124. package/tests/planning.spec.ts +56 -1
  125. package/tests/scaffold.spec.ts +131 -0
  126. package/tests/skills.spec.ts +63 -2
  127. package/build/connect/jobs.d.ts +0 -25
  128. package/build/connect/jobs.d.ts.map +0 -1
  129. package/build/connect/jobs.js +0 -29
  130. package/build/connect/jobs.js.map +0 -1
  131. package/src/connect/jobs.ts +0 -40
@@ -4,7 +4,7 @@ import addFormats from 'ajv-formats'
4
4
  import { ResilientError } from '@owlmeans/error'
5
5
  import {
6
6
  canTransit, CodeScope, CodeStyle, intrinsicOf, IntrinsicStatus, makeSchemaRegistry,
7
- SpecificationFormat, transitionsFrom, WorkcardKind,
7
+ SpecificationFormat, TITLE_MAX, transitionsFrom, WorkcardKind,
8
8
  } from '@owlmeans/planning'
9
9
  import type { Specification } from '@owlmeans/planning'
10
10
  import { ProjectArea } from '../src/areas/consts.js'
@@ -14,6 +14,9 @@ import { STORY_DESIGN_VERSION } from '../src/design/consts.js'
14
14
  import { emptyStoryDesign } from '../src/design/helpers.js'
15
15
  import { StoryActor } from '../src/design/runtime.js'
16
16
  import type { StoryDesign } from '../src/design/types.js'
17
+ import {
18
+ hasLandingSentence, LANDING_STORY_SENTENCE, withLandingSentence,
19
+ } from '../src/index.js'
17
20
  import {
18
21
  isUserChannel, isViableProject, isViableStory, ProjectAgentOccupied, ProjectNotFound,
19
22
  ProjectStoryMissconfigured, projectBriefOf, storyDraftOf, storyWriteInputOf, userStoryOf,
@@ -255,9 +258,24 @@ describe('viable-common - the viable field schemas', () => {
255
258
  expect(project({
256
259
  formerAliases: ['old-name'], language: 'en', blueprint: 'owlmeans', blueprintCase: 'web',
257
260
  target: null, connectLlmMode: 'local', origin: { kind: 'github', repoUrl: 'https://x/y' },
261
+ landing: { story: 'US-ABC12', at },
258
262
  })).toBe(true)
259
263
  expect(project({ alias: 'slot-booker' })).toBe(false)
260
264
  })
265
+
266
+ test('a story carries the landing flag, spelled or nulled', () => {
267
+ expect(story({ area: ProjectArea.User, primary: false, landing: true })).toBe(true)
268
+ expect(story({ area: ProjectArea.User, primary: false, landing: null })).toBe(true)
269
+ expect(story({ area: ProjectArea.User, primary: false, landing: 'yes' })).toBe(false)
270
+ })
271
+
272
+ test('a project records a decided "no gate" as story null, and never a decision without a time', () => {
273
+ // Absent = never decided; `story: null` = decided, no gate. Both must be spellable.
274
+ expect(project({ landing: { story: null, at } })).toBe(true)
275
+ expect(project({ landing: null })).toBe(true)
276
+ expect(project({ landing: { story: 'US-ABC12' } })).toBe(false)
277
+ expect(project({ landing: { story: 'US-ABC12', at, reason: 'best fit' } })).toBe(false)
278
+ })
261
279
  })
262
280
 
263
281
  describe('viable-common - the viable card helpers', () => {
@@ -311,6 +329,16 @@ describe('viable-common - the viable card helpers', () => {
311
329
  .toThrow(ProjectStoryMissconfigured)
312
330
  })
313
331
 
332
+ test('storyWriteInputOf copies the landing flag from the card, and only when it is set', () => {
333
+ const content = {
334
+ userStory: userStoryOf(storyCard()), screenPaths: {}, componentPaths: {}, transitions: [],
335
+ }
336
+ const landing = storyCard({ fields: { area: ProjectArea.User, primary: false, landing: true } })
337
+
338
+ expect(storyWriteInputOf(landing, content).landing).toBe(true)
339
+ expect('landing' in storyWriteInputOf(storyCard(), content)).toBe(false)
340
+ })
341
+
314
342
  test('only a person writes through the web and connect channels', () => {
315
343
  expect(isUserChannel(ViableChannel.Web)).toBe(true)
316
344
  expect(isUserChannel(ViableChannel.Connect)).toBe(true)
@@ -319,6 +347,33 @@ describe('viable-common - the viable card helpers', () => {
319
347
  })
320
348
  })
321
349
 
350
+ describe('viable-common - the landing sentence', () => {
351
+ test('is appended once, with one space, and a resumed step never adds a second copy', () => {
352
+ const once = withLandingSentence('A member books a slot.')
353
+
354
+ expect(once).toBe(`A member books a slot. ${LANDING_STORY_SENTENCE}`)
355
+ expect(withLandingSentence(once)).toBe(once)
356
+ expect(hasLandingSentence(once)).toBe(true)
357
+ expect(hasLandingSentence('A member books a slot.')).toBe(false)
358
+ })
359
+
360
+ test('is recognised whatever whitespace a person left around it', () => {
361
+ const rewrapped = `A member books a slot.\n${LANDING_STORY_SENTENCE.replace('; after', ';\n after')}`
362
+
363
+ expect(hasLandingSentence(rewrapped)).toBe(true)
364
+ expect(withLandingSentence(rewrapped)).toBe(rewrapped)
365
+ })
366
+
367
+ test('never makes a title longer than a card accepts, and never cuts the narrative', () => {
368
+ const long = 'x'.repeat(TITLE_MAX - 10)
369
+
370
+ expect(withLandingSentence(long)).toBe(long)
371
+ expect(withLandingSentence('x'.repeat(TITLE_MAX - LANDING_STORY_SENTENCE.length - 1)).length)
372
+ .toBe(TITLE_MAX)
373
+ expect(withLandingSentence(' ')).toBe(LANDING_STORY_SENTENCE)
374
+ })
375
+ })
376
+
322
377
  describe('viable-common - the follows anchor', () => {
323
378
  test('mergeConnectingStories carries the clamped anchor on each connective entry', () => {
324
379
  const flow = [
@@ -0,0 +1,131 @@
1
+ import { describe, expect, test } from 'bun:test'
2
+ import Ajv from 'ajv'
3
+ import { validateSpecificationBody } from '@owlmeans/planning'
4
+ import { ProjectArea } from '../src/areas/consts.js'
5
+ import { ViableSpecCategory, VIABLE_PROJECT_SLOTS } from '../src/planning/index.js'
6
+ import { BENTO_FRAGMENT_KINDS, WidgetKind } from '../src/scaffold/consts.js'
7
+ import { ScaffoldPlanSchema } from '../src/scaffold/schemas.js'
8
+ import type { ScaffoldPlan } from '../src/scaffold/types.js'
9
+
10
+ /**
11
+ * The scaffold plan's schema is TWO things at once: the shape a model answers with, and the
12
+ * validator of the project card's `scaffold` document. A plan written before the landing-page
13
+ * overhaul carries none of its fields, and must still pass — or that project's plan can never be
14
+ * revised again. Compiled the way the planning registry compiles it (no formats, not strict).
15
+ */
16
+ const oldPlan = (): ScaffoldPlan => ({
17
+ identity: { name: 'Crumb & Crust', description: 'Recipes and bakes from a welcoming community.' },
18
+ guestHome: {
19
+ hero: { headline: 'Find your next bake.', sub: 'Photo-led recipes.', cta: 'Get started', eyebrow: 'New' },
20
+ problem: { title: 'Inspiration lacks detail', text: 'A bake is easy to find.' },
21
+ solution: { title: 'Bakes worth making', text: 'The full process in one place.' },
22
+ features: [{ title: 'Complete recipes', text: 'Clear ingredient lists.' }],
23
+ testimonials: [{ quote: 'I found a rye loaf.', name: 'Mara L.', role: 'Home baker' }],
24
+ },
25
+ areas: [{ area: ProjectArea.Guest, intro: { title: 'Welcome', text: 'Browse.' }, sections: ['Bakes'] }],
26
+ stories: [{
27
+ code: 'US-ABC12',
28
+ section: 'Bakes',
29
+ screen: 'Bakes/Find a bake',
30
+ widget: { kind: WidgetKind.List, title: 'Bake finder', description: 'Bakes you can make.' },
31
+ sketch: { headline: 'Your bakes', caption: 'What you can bake', items: ['Rye loaf'] },
32
+ home: true,
33
+ }],
34
+ motifs: 'A rye loaf on a board.',
35
+ })
36
+
37
+ const newPlan = (): ScaffoldPlan => {
38
+ const plan = oldPlan()
39
+
40
+ return {
41
+ ...plan,
42
+ guestHome: {
43
+ ...plan.guestHome,
44
+ hero: {
45
+ headline: 'Find your next bake.', sub: 'Photo-led recipes.', cta: 'Get started',
46
+ secondary: { label: 'Browse bakes' },
47
+ browse: { label: 'Just browsing? Explore bakes', href: '#features' },
48
+ },
49
+ features: [
50
+ {
51
+ title: 'Complete recipes', text: 'Clear ingredient lists.',
52
+ fragment: {
53
+ kind: 'list', title: 'INGREDIENTS · 1 LOAF',
54
+ rows: [{ label: 'Rye flour', value: '350 g' }, { label: 'Water', value: '390 g' }],
55
+ },
56
+ },
57
+ { title: 'Baking notes', text: 'Small adjustments.', fragment: { kind: 'note', rows: [{ label: 'Drop the oven.' }] } },
58
+ { title: 'Photo-led bakes', text: 'Every idea starts with the bake.' },
59
+ { title: 'Baker attribution', text: 'See who made it.', fragment: { kind: 'people', rows: [{ label: 'Mara L.', value: 'Rye' }] } },
60
+ ],
61
+ steps: [
62
+ { title: 'Pick what you have', text: 'Tap the ingredients.' },
63
+ { title: 'See what you can bake', text: 'Ranked by your pantry.' },
64
+ { title: 'Open the full method', text: 'Sign in with your email.' },
65
+ ],
66
+ labels: { steps: 'How it works', stepsTitle: 'From pantry to basket.', problem: 'The problem' },
67
+ closing: {
68
+ headline: 'Your next bake starts here.', lead: 'Browse freely.', primary: 'Get started',
69
+ secondary: { label: 'Browse bakes' },
70
+ links: [{ title: 'Explore bakes', text: 'Open to everyone.' }, { title: 'Share your bake', text: 'Post it.', href: '#' }],
71
+ },
72
+ gate: {
73
+ story: 'US-ABC12',
74
+ target: 'web:bake-finder',
75
+ question: "What's in your pantry?",
76
+ hint: 'No account needed',
77
+ label: 'Your pantry',
78
+ inputs: ['Bread flour', 'Rye flour', 'Butter', 'Eggs', 'Yeast'],
79
+ selected: ['Bread flour', 'Rye flour', 'Butter', 'Yeast'],
80
+ results: [{ title: 'Seeded rye loaf', meta: 'Uses all 3 · 3 h 20 min', needs: ['Bread flour', 'Rye flour', 'Yeast'] }],
81
+ count: { one: '{n} bake matches', many: '{n} bakes match', none: 'No matches yet' },
82
+ empty: 'Pick two or more ingredients.',
83
+ note: 'Sign in with your email. Your picks come with you.',
84
+ cta: 'Open recipes →',
85
+ lock: 'Full method after sign-in',
86
+ },
87
+ },
88
+ }
89
+ }
90
+
91
+ describe('viable-common - the scaffold plan schema', () => {
92
+ const validate = new Ajv({ strict: false, allErrors: true }).compile(ScaffoldPlanSchema)
93
+ const slot = VIABLE_PROJECT_SLOTS.find(entry => entry.category === ViableSpecCategory.Scaffold)!
94
+
95
+ test('a plan stored before the landing overhaul still validates', () => {
96
+ expect(validate(oldPlan()), JSON.stringify(validate.errors)).toBe(true)
97
+ expect(() => validateSpecificationBody(slot, JSON.stringify(oldPlan()))).not.toThrow()
98
+ })
99
+
100
+ test('a plan carrying every new field validates', () => {
101
+ expect(validate(newPlan()), JSON.stringify(validate.errors)).toBe(true)
102
+ expect(() => validateSpecificationBody(slot, JSON.stringify(newPlan()))).not.toThrow()
103
+ })
104
+
105
+ test('a provider that spells an unset optional as null is accepted', () => {
106
+ const plan = newPlan() as unknown as { guestHome: Record<string, unknown> }
107
+ plan.guestHome.gate = null
108
+ plan.guestHome.closing = null
109
+ ;(plan.guestHome.hero as Record<string, unknown>).secondary = null
110
+
111
+ expect(validate(plan), JSON.stringify(validate.errors)).toBe(true)
112
+ })
113
+
114
+ test('still refuses an undeclared field and a fragment kind nothing can draw', () => {
115
+ const stray = newPlan() as unknown as { guestHome: Record<string, unknown> }
116
+ stray.guestHome.badge = 'New'
117
+ expect(validate(stray)).toBe(false)
118
+
119
+ const fragment = newPlan()
120
+ fragment.guestHome.features[0].fragment = { kind: 'chart' as never, rows: [] }
121
+ expect(validate(fragment)).toBe(false)
122
+ })
123
+
124
+ test('declares no count as minItems/maxItems — counts live in the descriptions', () => {
125
+ const text = JSON.stringify(ScaffoldPlanSchema)
126
+
127
+ expect(text).not.toContain('minItems')
128
+ expect(text).not.toContain('maxItems')
129
+ expect(BENTO_FRAGMENT_KINDS).toEqual(['list', 'note', 'people', 'steps'])
130
+ })
131
+ })
@@ -1,7 +1,8 @@
1
1
  import { describe, expect, it } from 'bun:test'
2
2
 
3
- import { ViableSkill } from '../src/skills/consts.js'
4
- import { viableSkill } from '../src/skills/catalogue.js'
3
+ import { SKILL_ORDER, ViableSkill } from '../src/skills/consts.js'
4
+ import { VIABLE_SKILLS, viableSkill } from '../src/skills/catalogue.js'
5
+ import { VIABLE_PERSONAS, ViablePersona } from '../src/skills/roles.js'
5
6
 
6
7
  /**
7
8
  * Pins the catalogue's own "wrap exactly once" teaching — the incident this guards against was
@@ -45,3 +46,63 @@ describe('viable-common catalogue — handler wrap-once', () => {
45
46
  }
46
47
  })
47
48
  })
49
+
50
+ /**
51
+ * The prompt service SKIPS an alias it cannot resolve, so a skill in the enum with no body is a
52
+ * rule no model ever receives — nothing fails, the prompt simply lacks it.
53
+ */
54
+ describe('viable-common catalogue — completeness', () => {
55
+ it('declares one body and one sort weight for every skill in the enum', () => {
56
+ const declared = VIABLE_SKILLS.map(entry => entry.alias)
57
+
58
+ expect(Object.values(ViableSkill).filter(alias => !declared.includes(alias))).toEqual([])
59
+ expect(new Set(declared).size).toBe(declared.length)
60
+ for (const alias of Object.values(ViableSkill)) {
61
+ expect(typeof SKILL_ORDER[alias], alias).toBe('number')
62
+ }
63
+ })
64
+ })
65
+
66
+ /**
67
+ * The house style is taught in two places a designer and a coder read — the visual designer's
68
+ * persona and the shadcn skill — and a template ships the same values. Neither may drift back
69
+ * to teaching the decoration the template now paints flat.
70
+ */
71
+ describe('viable-common catalogue — the house style', () => {
72
+ it('ShadcnUi teaches the white ground, one accent and flat depth, and repaints the old classes', () => {
73
+ const body = viableSkill(ViableSkill.ShadcnUi).body
74
+
75
+ expect(body).toContain('bg-background')
76
+ expect(body).toContain('ONE product accent')
77
+ expect(body).toContain('shadow-floating')
78
+ expect(body).toContain('REPAINTED flat')
79
+ expect(body).toContain('explicitly asks')
80
+ expect(body).not.toContain('DECORATION VOCABULARY')
81
+ expect(body).not.toMatch(/\/\/ right[^\n]*gradient/)
82
+ expect(body).toContain('SelectItem')
83
+ })
84
+
85
+ it('the visual designer defaults to the house style and changes it only on an explicit ask', () => {
86
+ const role = VIABLE_PERSONAS[ViablePersona.VisualDesigner].role
87
+
88
+ expect(role).toContain('white ground')
89
+ expect(role).toContain('ONE')
90
+ expect(role).toContain('explicitly asks')
91
+ expect(role).not.toContain('expressive and bright')
92
+ expect(role).not.toMatch(/default to .*gradients/)
93
+ })
94
+
95
+ it('LandingGate teaches the gate card, the synchronous handoff and the screen that reads it', () => {
96
+ const body = viableSkill(ViableSkill.LandingGate).body
97
+
98
+ expect(body).toContain('data-home-gate')
99
+ expect(body).toContain('aria-pressed')
100
+ expect(body).toContain('writeLandingHandoff(target')
101
+ expect(body).toContain('readLandingHandoff')
102
+ expect(body).toContain('clearLandingHandoff()')
103
+ expect(body).toContain("useLogin(target)")
104
+ expect(body).toContain('SYNCHRONOUS')
105
+ expect(body).toContain('WRONG')
106
+ expect(body).not.toContain('${')
107
+ })
108
+ })
@@ -1,25 +0,0 @@
1
- import type { ConnectJobKind } from './consts.js';
2
- /**
3
- * The separator a job id is joined with.
4
- *
5
- * `~`, because every other separator in play is already spoken for: a route alias is
6
- * colon-delimited and so is every run id (`init:<projectId>`, `story:<storyId>`), so a job id
7
- * built with one could not be split back apart.
8
- */
9
- export declare const JOB_SEPARATOR = "~";
10
- /**
11
- * A job's id: its kind, the project card it belongs to, and the subject it is about.
12
- *
13
- * The suffix is a CARD id for a story job and a run id for a pipeline job — never a story code.
14
- * Declared here rather than by whoever answers the job, because the SDK composes the id it then
15
- * polls for: two spellings of one id is a job nobody can find.
16
- */
17
- export declare const jobIdOf: (kind: ConnectJobKind, projectId: string, suffix?: string) => string;
18
- export interface ParsedJobId {
19
- kind: ConnectJobKind;
20
- projectId: string;
21
- suffix?: string;
22
- }
23
- /** Split a job id back into what {@link jobIdOf} composed it from. */
24
- export declare const parseJobId: (jobId: string) => ParsedJobId;
25
- //# sourceMappingURL=jobs.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"jobs.d.ts","sourceRoot":"","sources":["../../src/connect/jobs.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,aAAa,CAAA;AAEjD;;;;;;GAMG;AACH,eAAO,MAAM,aAAa,MAAM,CAAA;AAEhC;;;;;;GAMG;AACH,eAAO,MAAM,OAAO,SAAU,cAAc,aAAa,MAAM,WAAW,MAAM,KAAG,MACP,CAAA;AAE5E,MAAM,WAAW,WAAW;IAC1B,IAAI,EAAE,cAAc,CAAA;IACpB,SAAS,EAAE,MAAM,CAAA;IACjB,MAAM,CAAC,EAAE,MAAM,CAAA;CAChB;AAED,sEAAsE;AACtE,eAAO,MAAM,UAAU,UAAW,MAAM,KAAG,WAW1C,CAAA"}
@@ -1,29 +0,0 @@
1
- /**
2
- * The separator a job id is joined with.
3
- *
4
- * `~`, because every other separator in play is already spoken for: a route alias is
5
- * colon-delimited and so is every run id (`init:<projectId>`, `story:<storyId>`), so a job id
6
- * built with one could not be split back apart.
7
- */
8
- export const JOB_SEPARATOR = '~';
9
- /**
10
- * A job's id: its kind, the project card it belongs to, and the subject it is about.
11
- *
12
- * The suffix is a CARD id for a story job and a run id for a pipeline job — never a story code.
13
- * Declared here rather than by whoever answers the job, because the SDK composes the id it then
14
- * polls for: two spellings of one id is a job nobody can find.
15
- */
16
- export const jobIdOf = (kind, projectId, suffix) => [kind, projectId, ...(suffix != null ? [suffix] : [])].join(JOB_SEPARATOR);
17
- /** Split a job id back into what {@link jobIdOf} composed it from. */
18
- export const parseJobId = (jobId) => {
19
- const [kind, projectId, ...rest] = jobId.split(JOB_SEPARATOR);
20
- // A suffix may carry the separator back if one ever ends up in a card or run id, so the tail is
21
- // rejoined rather than taken as its first segment.
22
- const suffix = rest.length > 0 ? rest.join(JOB_SEPARATOR) : undefined;
23
- return {
24
- kind: kind,
25
- projectId: projectId ?? '',
26
- ...(suffix != null ? { suffix } : {}),
27
- };
28
- };
29
- //# sourceMappingURL=jobs.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"jobs.js","sourceRoot":"","sources":["../../src/connect/jobs.ts"],"names":[],"mappings":"AAEA;;;;;;GAMG;AACH,MAAM,CAAC,MAAM,aAAa,GAAG,GAAG,CAAA;AAEhC;;;;;;GAMG;AACH,MAAM,CAAC,MAAM,OAAO,GAAG,CAAC,IAAoB,EAAE,SAAiB,EAAE,MAAe,EAAU,EAAE,CAC1F,CAAC,IAAI,EAAE,SAAS,EAAE,GAAG,CAAC,MAAM,IAAI,IAAI,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,aAAa,CAAC,CAAA;AAQ5E,sEAAsE;AACtE,MAAM,CAAC,MAAM,UAAU,GAAG,CAAC,KAAa,EAAe,EAAE;IACvD,MAAM,CAAC,IAAI,EAAE,SAAS,EAAE,GAAG,IAAI,CAAC,GAAG,KAAK,CAAC,KAAK,CAAC,aAAa,CAAC,CAAA;IAC7D,gGAAgG;IAChG,mDAAmD;IACnD,MAAM,MAAM,GAAG,IAAI,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC,CAAC,CAAC,SAAS,CAAA;IAErE,OAAO;QACL,IAAI,EAAE,IAAsB;QAC5B,SAAS,EAAE,SAAS,IAAI,EAAE;QAC1B,GAAG,CAAC,MAAM,IAAI,IAAI,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;KACtC,CAAA;AACH,CAAC,CAAA"}
@@ -1,40 +0,0 @@
1
- import type { ConnectJobKind } from './consts.js'
2
-
3
- /**
4
- * The separator a job id is joined with.
5
- *
6
- * `~`, because every other separator in play is already spoken for: a route alias is
7
- * colon-delimited and so is every run id (`init:<projectId>`, `story:<storyId>`), so a job id
8
- * built with one could not be split back apart.
9
- */
10
- export const JOB_SEPARATOR = '~'
11
-
12
- /**
13
- * A job's id: its kind, the project card it belongs to, and the subject it is about.
14
- *
15
- * The suffix is a CARD id for a story job and a run id for a pipeline job — never a story code.
16
- * Declared here rather than by whoever answers the job, because the SDK composes the id it then
17
- * polls for: two spellings of one id is a job nobody can find.
18
- */
19
- export const jobIdOf = (kind: ConnectJobKind, projectId: string, suffix?: string): string =>
20
- [kind, projectId, ...(suffix != null ? [suffix] : [])].join(JOB_SEPARATOR)
21
-
22
- export interface ParsedJobId {
23
- kind: ConnectJobKind
24
- projectId: string
25
- suffix?: string
26
- }
27
-
28
- /** Split a job id back into what {@link jobIdOf} composed it from. */
29
- export const parseJobId = (jobId: string): ParsedJobId => {
30
- const [kind, projectId, ...rest] = jobId.split(JOB_SEPARATOR)
31
- // A suffix may carry the separator back if one ever ends up in a card or run id, so the tail is
32
- // rejoined rather than taken as its first segment.
33
- const suffix = rest.length > 0 ? rest.join(JOB_SEPARATOR) : undefined
34
-
35
- return {
36
- kind: kind as ConnectJobKind,
37
- projectId: projectId ?? '',
38
- ...(suffix != null ? { suffix } : {}),
39
- }
40
- }