openuispec 0.1.25 → 0.1.28

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 (139) hide show
  1. package/README.md +63 -18
  2. package/cli/index.ts +21 -3
  3. package/cli/init.ts +27 -11
  4. package/docs/implementation-notes.md +119 -0
  5. package/docs/release-notes-v0.1.26.md +64 -0
  6. package/docs/release-notes-v0.1.27.md +28 -0
  7. package/docs/release-notes-v0.1.28.md +25 -0
  8. package/docs/stress-test-maturity-report.md +1 -1
  9. package/drift/index.ts +396 -22
  10. package/examples/taskflow/AGENTS.md +112 -0
  11. package/examples/taskflow/CLAUDE.md +112 -0
  12. package/examples/taskflow/generated/android/TaskFlow/README.md +43 -0
  13. package/examples/taskflow/generated/android/TaskFlow/app/build.gradle.kts +76 -0
  14. package/examples/taskflow/generated/android/TaskFlow/app/proguard-rules.pro +1 -0
  15. package/examples/taskflow/generated/android/TaskFlow/app/src/main/AndroidManifest.xml +21 -0
  16. package/examples/taskflow/generated/android/TaskFlow/app/src/main/java/uz/rsteam/taskflow/MainActivity.kt +19 -0
  17. package/examples/taskflow/generated/android/TaskFlow/app/src/main/java/uz/rsteam/taskflow/TaskFlowApp.kt +283 -0
  18. package/examples/taskflow/generated/android/TaskFlow/app/src/main/java/uz/rsteam/taskflow/model/DomainModels.kt +106 -0
  19. package/examples/taskflow/generated/android/TaskFlow/app/src/main/java/uz/rsteam/taskflow/model/SampleData.kt +57 -0
  20. package/examples/taskflow/generated/android/TaskFlow/app/src/main/java/uz/rsteam/taskflow/ui/components/Common.kt +109 -0
  21. package/examples/taskflow/generated/android/TaskFlow/app/src/main/java/uz/rsteam/taskflow/ui/screens/HomeScreen.kt +112 -0
  22. package/examples/taskflow/generated/android/TaskFlow/app/src/main/java/uz/rsteam/taskflow/ui/screens/ProjectsScreen.kt +61 -0
  23. package/examples/taskflow/generated/android/TaskFlow/app/src/main/java/uz/rsteam/taskflow/ui/screens/SettingsScreen.kt +82 -0
  24. package/examples/taskflow/generated/android/TaskFlow/app/src/main/java/uz/rsteam/taskflow/ui/screens/TaskDetailScreen.kt +111 -0
  25. package/examples/taskflow/generated/android/TaskFlow/app/src/main/java/uz/rsteam/taskflow/ui/sheets/Sheets.kt +77 -0
  26. package/examples/taskflow/generated/android/TaskFlow/app/src/main/java/uz/rsteam/taskflow/ui/theme/Color.kt +30 -0
  27. package/examples/taskflow/generated/android/TaskFlow/app/src/main/java/uz/rsteam/taskflow/ui/theme/Theme.kt +86 -0
  28. package/examples/taskflow/generated/android/TaskFlow/app/src/main/java/uz/rsteam/taskflow/ui/theme/Type.kt +57 -0
  29. package/examples/taskflow/generated/android/TaskFlow/app/src/main/res/values/strings.xml +155 -0
  30. package/examples/taskflow/generated/android/TaskFlow/app/src/main/res/values/themes.xml +4 -0
  31. package/examples/taskflow/generated/android/TaskFlow/build.gradle.kts +5 -0
  32. package/examples/taskflow/generated/android/TaskFlow/gradle/gradle-daemon-jvm.properties +12 -0
  33. package/examples/taskflow/generated/android/TaskFlow/gradle/wrapper/gradle-wrapper.jar +0 -0
  34. package/examples/taskflow/generated/android/TaskFlow/gradle/wrapper/gradle-wrapper.properties +7 -0
  35. package/examples/taskflow/generated/android/TaskFlow/gradle.properties +4 -0
  36. package/examples/taskflow/generated/android/TaskFlow/gradlew +18 -0
  37. package/examples/taskflow/generated/android/TaskFlow/gradlew.bat +12 -0
  38. package/examples/taskflow/generated/android/TaskFlow/settings.gradle.kts +18 -0
  39. package/examples/taskflow/generated/ios/TaskFlow/README.md +21 -0
  40. package/examples/taskflow/generated/ios/TaskFlow/Resources/en.lproj/Localizable.strings +115 -0
  41. package/examples/taskflow/generated/ios/TaskFlow/Sources/TaskFlow/App/TaskFlowApp.swift +24 -0
  42. package/examples/taskflow/generated/ios/TaskFlow/Sources/TaskFlow/Components/AppChrome.swift +150 -0
  43. package/examples/taskflow/generated/ios/TaskFlow/Sources/TaskFlow/Flows/TaskEditorSheet.swift +220 -0
  44. package/examples/taskflow/generated/ios/TaskFlow/Sources/TaskFlow/Models/DomainModels.swift +122 -0
  45. package/examples/taskflow/generated/ios/TaskFlow/Sources/TaskFlow/Screens/CalendarView.swift +21 -0
  46. package/examples/taskflow/generated/ios/TaskFlow/Sources/TaskFlow/Screens/HomeView.swift +201 -0
  47. package/examples/taskflow/generated/ios/TaskFlow/Sources/TaskFlow/Screens/ProfileEditView.swift +48 -0
  48. package/examples/taskflow/generated/ios/TaskFlow/Sources/TaskFlow/Screens/ProjectDetailView.swift +59 -0
  49. package/examples/taskflow/generated/ios/TaskFlow/Sources/TaskFlow/Screens/ProjectsView.swift +63 -0
  50. package/examples/taskflow/generated/ios/TaskFlow/Sources/TaskFlow/Screens/SettingsView.swift +85 -0
  51. package/examples/taskflow/generated/ios/TaskFlow/Sources/TaskFlow/Screens/TaskDetailView.swift +219 -0
  52. package/examples/taskflow/generated/ios/TaskFlow/Sources/TaskFlow/Support/AppModel.swift +320 -0
  53. package/examples/taskflow/generated/ios/TaskFlow/Sources/TaskFlow/Support/AppSupport.swift +41 -0
  54. package/examples/taskflow/generated/ios/TaskFlow/project.yml +26 -0
  55. package/examples/taskflow/generated/web/TaskFlow/README.md +19 -0
  56. package/examples/taskflow/generated/web/TaskFlow/index.html +12 -0
  57. package/examples/taskflow/generated/web/TaskFlow/package-lock.json +1908 -0
  58. package/examples/taskflow/generated/web/TaskFlow/package.json +24 -0
  59. package/examples/taskflow/generated/web/TaskFlow/src/App.tsx +58 -0
  60. package/examples/taskflow/generated/web/TaskFlow/src/AppShell.tsx +55 -0
  61. package/examples/taskflow/generated/web/TaskFlow/src/components/Common.tsx +82 -0
  62. package/examples/taskflow/generated/web/TaskFlow/src/components/Modals.tsx +191 -0
  63. package/examples/taskflow/generated/web/TaskFlow/src/components/Nav.tsx +41 -0
  64. package/examples/taskflow/generated/web/TaskFlow/src/generated/messages.ts +131 -0
  65. package/examples/taskflow/generated/web/TaskFlow/src/hooks.ts +25 -0
  66. package/examples/taskflow/generated/web/TaskFlow/src/i18n.ts +39 -0
  67. package/examples/taskflow/generated/web/TaskFlow/src/locales.en.json +111 -0
  68. package/examples/taskflow/generated/web/TaskFlow/src/main.tsx +13 -0
  69. package/examples/taskflow/generated/web/TaskFlow/src/screens/HomeScreen.tsx +111 -0
  70. package/examples/taskflow/generated/web/TaskFlow/src/screens/ProjectsScreen.tsx +82 -0
  71. package/examples/taskflow/generated/web/TaskFlow/src/screens/SettingsScreens.tsx +132 -0
  72. package/examples/taskflow/generated/web/TaskFlow/src/screens/TaskDetail.tsx +105 -0
  73. package/examples/taskflow/generated/web/TaskFlow/src/store.ts +216 -0
  74. package/examples/taskflow/generated/web/TaskFlow/src/styles.css +617 -0
  75. package/examples/taskflow/generated/web/TaskFlow/src/types.ts +64 -0
  76. package/examples/taskflow/generated/web/TaskFlow/src/utils.ts +78 -0
  77. package/examples/taskflow/generated/web/TaskFlow/tsconfig.json +21 -0
  78. package/examples/taskflow/generated/web/TaskFlow/vite.config.ts +6 -0
  79. package/examples/taskflow/openuispec/README.md +49 -0
  80. package/examples/todo-orbit/AGENTS.md +46 -14
  81. package/examples/todo-orbit/CLAUDE.md +46 -14
  82. package/examples/todo-orbit/generated/android/Todo Orbit/app/src/main/java/uz/rsteam/todoorbit/ui/components/CommonComponents.kt +69 -18
  83. package/examples/todo-orbit/generated/android/Todo Orbit/app/src/main/java/uz/rsteam/todoorbit/ui/screens/TasksScreen.kt +5 -0
  84. package/examples/todo-orbit/generated/android/Todo Orbit/app/src/main/java/uz/rsteam/todoorbit/ui/sheets/EditorSheets.kt +5 -2
  85. package/examples/todo-orbit/generated/android/Todo Orbit/app/src/main/res/values/strings.xml +1 -0
  86. package/examples/todo-orbit/generated/android/Todo Orbit/app/src/main/res/values-ru/strings.xml +1 -0
  87. package/examples/todo-orbit/generated/ios/Todo Orbit/Resources/en.lproj/Localizable.strings +1 -0
  88. package/examples/todo-orbit/generated/ios/Todo Orbit/Resources/ru.lproj/Localizable.strings +1 -0
  89. package/examples/todo-orbit/generated/ios/Todo Orbit/Sources/TodoOrbit/Flows/RecurringRuleSheet.swift +3 -0
  90. package/examples/todo-orbit/generated/ios/Todo Orbit/Sources/TodoOrbit/Flows/TaskEditorSheet.swift +1 -0
  91. package/examples/todo-orbit/generated/ios/Todo Orbit/Sources/TodoOrbit/Screens/SettingsView.swift +2 -0
  92. package/examples/todo-orbit/generated/ios/Todo Orbit/Sources/TodoOrbit/Screens/TasksHomeView.swift +1 -0
  93. package/examples/todo-orbit/generated/ios/Todo Orbit/Sources/TodoOrbit/Support/AppModel.swift +1 -1
  94. package/examples/todo-orbit/generated/web/Todo Orbit/src/App.tsx +59 -6
  95. package/examples/todo-orbit/generated/web/Todo Orbit/src/styles.css +40 -0
  96. package/examples/todo-orbit/openuispec/README.md +24 -131
  97. package/examples/todo-orbit/openuispec/flows/create_recurring_rule.yaml +3 -0
  98. package/examples/todo-orbit/openuispec/flows/create_task.yaml +1 -0
  99. package/examples/todo-orbit/openuispec/flows/edit_task.yaml +1 -0
  100. package/examples/todo-orbit/openuispec/locales/en.json +1 -0
  101. package/examples/todo-orbit/openuispec/locales/ru.json +1 -0
  102. package/examples/todo-orbit/openuispec/screens/task_detail.yaml +1 -0
  103. package/examples/todo-orbit/openuispec/tokens/icons.yaml +6 -0
  104. package/package.json +6 -1
  105. package/prepare/index.ts +391 -0
  106. package/schema/semantic-lint.ts +592 -0
  107. package/schema/validate.ts +17 -13
  108. package/status/index.ts +200 -0
  109. /package/examples/taskflow/{contracts → openuispec/contracts}/README.md +0 -0
  110. /package/examples/taskflow/{contracts → openuispec/contracts}/action_trigger.yaml +0 -0
  111. /package/examples/taskflow/{contracts → openuispec/contracts}/collection.yaml +0 -0
  112. /package/examples/taskflow/{contracts → openuispec/contracts}/data_display.yaml +0 -0
  113. /package/examples/taskflow/{contracts → openuispec/contracts}/feedback.yaml +0 -0
  114. /package/examples/taskflow/{contracts → openuispec/contracts}/input_field.yaml +0 -0
  115. /package/examples/taskflow/{contracts → openuispec/contracts}/nav_container.yaml +0 -0
  116. /package/examples/taskflow/{contracts → openuispec/contracts}/surface.yaml +0 -0
  117. /package/examples/taskflow/{contracts → openuispec/contracts}/x_media_player.yaml +0 -0
  118. /package/examples/taskflow/{flows → openuispec/flows}/create_task.yaml +0 -0
  119. /package/examples/taskflow/{flows → openuispec/flows}/edit_task.yaml +0 -0
  120. /package/examples/taskflow/{locales → openuispec/locales}/en.json +0 -0
  121. /package/examples/taskflow/{openuispec.yaml → openuispec/openuispec.yaml} +0 -0
  122. /package/examples/taskflow/{platform → openuispec/platform}/android.yaml +0 -0
  123. /package/examples/taskflow/{platform → openuispec/platform}/ios.yaml +0 -0
  124. /package/examples/taskflow/{platform → openuispec/platform}/web.yaml +0 -0
  125. /package/examples/taskflow/{screens → openuispec/screens}/calendar.yaml +0 -0
  126. /package/examples/taskflow/{screens → openuispec/screens}/home.yaml +0 -0
  127. /package/examples/taskflow/{screens → openuispec/screens}/profile_edit.yaml +0 -0
  128. /package/examples/taskflow/{screens → openuispec/screens}/project_detail.yaml +0 -0
  129. /package/examples/taskflow/{screens → openuispec/screens}/projects.yaml +0 -0
  130. /package/examples/taskflow/{screens → openuispec/screens}/settings.yaml +0 -0
  131. /package/examples/taskflow/{screens → openuispec/screens}/task_detail.yaml +0 -0
  132. /package/examples/taskflow/{tokens → openuispec/tokens}/color.yaml +0 -0
  133. /package/examples/taskflow/{tokens → openuispec/tokens}/elevation.yaml +0 -0
  134. /package/examples/taskflow/{tokens → openuispec/tokens}/icons.yaml +0 -0
  135. /package/examples/taskflow/{tokens → openuispec/tokens}/layout.yaml +0 -0
  136. /package/examples/taskflow/{tokens → openuispec/tokens}/motion.yaml +0 -0
  137. /package/examples/taskflow/{tokens → openuispec/tokens}/spacing.yaml +0 -0
  138. /package/examples/taskflow/{tokens → openuispec/tokens}/themes.yaml +0 -0
  139. /package/examples/taskflow/{tokens → openuispec/tokens}/typography.yaml +0 -0
@@ -0,0 +1,200 @@
1
+ #!/usr/bin/env tsx
2
+ /**
3
+ * Cross-target status summary for OpenUISpec projects.
4
+ *
5
+ * Usage:
6
+ * openuispec status # summarize every target
7
+ * openuispec status --json # machine-readable output
8
+ */
9
+
10
+ import { existsSync } from "node:fs";
11
+ import {
12
+ computeDrift,
13
+ discoverTargets,
14
+ explainDrift,
15
+ findProjectDir,
16
+ formatBaseline,
17
+ readOutputDirs,
18
+ readProjectName,
19
+ resolveOutputDir,
20
+ stateFilePath,
21
+ type StateFile,
22
+ } from "../drift/index.js";
23
+
24
+ import { readFileSync } from "node:fs";
25
+
26
+ interface TargetStatus {
27
+ target: string;
28
+ output_dir: string;
29
+ output_exists: boolean;
30
+ snapshot: boolean;
31
+ snapshot_at: string | null;
32
+ baseline: {
33
+ kind: string | null;
34
+ commit: string | null;
35
+ branch: string | null;
36
+ label: string | null;
37
+ };
38
+ changed: number;
39
+ added: number;
40
+ removed: number;
41
+ behind: boolean;
42
+ explain_available: boolean;
43
+ note?: string;
44
+ }
45
+
46
+ interface StatusResult {
47
+ project: string;
48
+ targets: TargetStatus[];
49
+ }
50
+
51
+ function configuredTargets(projectDir: string): string[] {
52
+ try {
53
+ const manifest = readOutputDirs(projectDir);
54
+ const keys = Object.keys(manifest);
55
+ if (keys.length > 0) return keys.sort();
56
+ } catch {
57
+ // ignore
58
+ }
59
+
60
+ // Fallback to common targets when manifest output_dir is absent.
61
+ return ["android", "ios", "web"];
62
+ }
63
+
64
+ function allTargets(projectDir: string, projectName: string): string[] {
65
+ const seen = new Set<string>(configuredTargets(projectDir));
66
+ for (const target of discoverTargets(projectDir, projectName)) {
67
+ seen.add(target);
68
+ }
69
+ return Array.from(seen).sort();
70
+ }
71
+
72
+ function readState(statePath: string): StateFile {
73
+ return JSON.parse(readFileSync(statePath, "utf-8")) as StateFile;
74
+ }
75
+
76
+ function buildTargetStatus(cwd: string, projectDir: string, projectName: string, target: string): TargetStatus {
77
+ const outputDir = resolveOutputDir(projectDir, projectName, target);
78
+ const outputExists = existsSync(outputDir);
79
+ const path = stateFilePath(projectDir, projectName, target);
80
+
81
+ if (!existsSync(path)) {
82
+ return {
83
+ target,
84
+ output_dir: outputDir,
85
+ output_exists: outputExists,
86
+ snapshot: false,
87
+ snapshot_at: null,
88
+ baseline: {
89
+ kind: null,
90
+ commit: null,
91
+ branch: null,
92
+ label: null,
93
+ },
94
+ changed: 0,
95
+ added: 0,
96
+ removed: 0,
97
+ behind: false,
98
+ explain_available: false,
99
+ note: outputExists
100
+ ? "No snapshot found for this target."
101
+ : `Output directory not found. Run code generation for "${target}" first.`,
102
+ };
103
+ }
104
+
105
+ const state = readState(path);
106
+ const result = computeDrift(projectDir, state, false);
107
+ const explanation = explainDrift(projectDir, result);
108
+ const changed = result.drift.changed.length;
109
+ const added = result.drift.added.length;
110
+ const removed = result.drift.removed.length;
111
+
112
+ return {
113
+ target,
114
+ output_dir: outputDir,
115
+ output_exists: outputExists,
116
+ snapshot: true,
117
+ snapshot_at: state.snapshot_at,
118
+ baseline: {
119
+ kind: state.baseline?.kind ?? null,
120
+ commit: state.baseline?.commit ?? null,
121
+ branch: state.baseline?.branch ?? null,
122
+ label: formatBaseline(state.baseline),
123
+ },
124
+ changed,
125
+ added,
126
+ removed,
127
+ behind: changed + added + removed > 0,
128
+ explain_available: explanation.available,
129
+ note: explanation.available ? undefined : explanation.note,
130
+ };
131
+ }
132
+
133
+ function buildStatusResult(): StatusResult {
134
+ const cwd = process.cwd();
135
+ const projectDir = findProjectDir(cwd);
136
+ const projectName = readProjectName(projectDir);
137
+ const targets = allTargets(projectDir, projectName).map((target) =>
138
+ buildTargetStatus(cwd, projectDir, projectName, target)
139
+ );
140
+
141
+ return {
142
+ project: projectName,
143
+ targets,
144
+ };
145
+ }
146
+
147
+ function printReport(result: StatusResult): void {
148
+ console.log("OpenUISpec Status");
149
+ console.log("=================");
150
+ console.log(`Project: ${result.project}`);
151
+ console.log("");
152
+
153
+ for (const target of result.targets) {
154
+ const summary = target.snapshot
155
+ ? `${target.changed} changed, ${target.added} added, ${target.removed} removed`
156
+ : target.output_exists
157
+ ? "no snapshot"
158
+ : "output missing";
159
+ const status = target.snapshot
160
+ ? (target.behind ? "behind" : "up to date")
161
+ : target.output_exists
162
+ ? "needs baseline"
163
+ : "needs generation";
164
+
165
+ console.log(`${target.target}`);
166
+ console.log(` output: ${target.output_dir}`);
167
+ console.log(` output exists: ${target.output_exists ? "yes" : "no"}`);
168
+ console.log(` snapshot: ${target.snapshot ? target.snapshot_at : "missing"}`);
169
+ if (target.baseline.label) {
170
+ console.log(` baseline: ${target.baseline.label}`);
171
+ }
172
+ console.log(` drift: ${summary}`);
173
+ console.log(` status: ${status}`);
174
+ console.log(` explain: ${target.explain_available ? "available" : "unavailable"}`);
175
+ if (target.note) {
176
+ console.log(` note: ${target.note}`);
177
+ }
178
+ console.log("");
179
+ }
180
+ }
181
+
182
+ export function runStatus(argv: string[]): void {
183
+ const isJson = argv.includes("--json");
184
+ const result = buildStatusResult();
185
+
186
+ if (isJson) {
187
+ console.log(JSON.stringify(result, null, 2));
188
+ return;
189
+ }
190
+
191
+ printReport(result);
192
+ }
193
+
194
+ const isDirectRun =
195
+ process.argv[1]?.endsWith("status/index.ts") ||
196
+ process.argv[1]?.endsWith("status/index.js");
197
+
198
+ if (isDirectRun) {
199
+ runStatus(process.argv.slice(2));
200
+ }