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.
- package/README.md +63 -18
- package/cli/index.ts +21 -3
- package/cli/init.ts +27 -11
- package/docs/implementation-notes.md +119 -0
- package/docs/release-notes-v0.1.26.md +64 -0
- package/docs/release-notes-v0.1.27.md +28 -0
- package/docs/release-notes-v0.1.28.md +25 -0
- package/docs/stress-test-maturity-report.md +1 -1
- package/drift/index.ts +396 -22
- package/examples/taskflow/AGENTS.md +112 -0
- package/examples/taskflow/CLAUDE.md +112 -0
- package/examples/taskflow/generated/android/TaskFlow/README.md +43 -0
- package/examples/taskflow/generated/android/TaskFlow/app/build.gradle.kts +76 -0
- package/examples/taskflow/generated/android/TaskFlow/app/proguard-rules.pro +1 -0
- package/examples/taskflow/generated/android/TaskFlow/app/src/main/AndroidManifest.xml +21 -0
- package/examples/taskflow/generated/android/TaskFlow/app/src/main/java/uz/rsteam/taskflow/MainActivity.kt +19 -0
- package/examples/taskflow/generated/android/TaskFlow/app/src/main/java/uz/rsteam/taskflow/TaskFlowApp.kt +283 -0
- package/examples/taskflow/generated/android/TaskFlow/app/src/main/java/uz/rsteam/taskflow/model/DomainModels.kt +106 -0
- package/examples/taskflow/generated/android/TaskFlow/app/src/main/java/uz/rsteam/taskflow/model/SampleData.kt +57 -0
- package/examples/taskflow/generated/android/TaskFlow/app/src/main/java/uz/rsteam/taskflow/ui/components/Common.kt +109 -0
- package/examples/taskflow/generated/android/TaskFlow/app/src/main/java/uz/rsteam/taskflow/ui/screens/HomeScreen.kt +112 -0
- package/examples/taskflow/generated/android/TaskFlow/app/src/main/java/uz/rsteam/taskflow/ui/screens/ProjectsScreen.kt +61 -0
- package/examples/taskflow/generated/android/TaskFlow/app/src/main/java/uz/rsteam/taskflow/ui/screens/SettingsScreen.kt +82 -0
- package/examples/taskflow/generated/android/TaskFlow/app/src/main/java/uz/rsteam/taskflow/ui/screens/TaskDetailScreen.kt +111 -0
- package/examples/taskflow/generated/android/TaskFlow/app/src/main/java/uz/rsteam/taskflow/ui/sheets/Sheets.kt +77 -0
- package/examples/taskflow/generated/android/TaskFlow/app/src/main/java/uz/rsteam/taskflow/ui/theme/Color.kt +30 -0
- package/examples/taskflow/generated/android/TaskFlow/app/src/main/java/uz/rsteam/taskflow/ui/theme/Theme.kt +86 -0
- package/examples/taskflow/generated/android/TaskFlow/app/src/main/java/uz/rsteam/taskflow/ui/theme/Type.kt +57 -0
- package/examples/taskflow/generated/android/TaskFlow/app/src/main/res/values/strings.xml +155 -0
- package/examples/taskflow/generated/android/TaskFlow/app/src/main/res/values/themes.xml +4 -0
- package/examples/taskflow/generated/android/TaskFlow/build.gradle.kts +5 -0
- package/examples/taskflow/generated/android/TaskFlow/gradle/gradle-daemon-jvm.properties +12 -0
- package/examples/taskflow/generated/android/TaskFlow/gradle/wrapper/gradle-wrapper.jar +0 -0
- package/examples/taskflow/generated/android/TaskFlow/gradle/wrapper/gradle-wrapper.properties +7 -0
- package/examples/taskflow/generated/android/TaskFlow/gradle.properties +4 -0
- package/examples/taskflow/generated/android/TaskFlow/gradlew +18 -0
- package/examples/taskflow/generated/android/TaskFlow/gradlew.bat +12 -0
- package/examples/taskflow/generated/android/TaskFlow/settings.gradle.kts +18 -0
- package/examples/taskflow/generated/ios/TaskFlow/README.md +21 -0
- package/examples/taskflow/generated/ios/TaskFlow/Resources/en.lproj/Localizable.strings +115 -0
- package/examples/taskflow/generated/ios/TaskFlow/Sources/TaskFlow/App/TaskFlowApp.swift +24 -0
- package/examples/taskflow/generated/ios/TaskFlow/Sources/TaskFlow/Components/AppChrome.swift +150 -0
- package/examples/taskflow/generated/ios/TaskFlow/Sources/TaskFlow/Flows/TaskEditorSheet.swift +220 -0
- package/examples/taskflow/generated/ios/TaskFlow/Sources/TaskFlow/Models/DomainModels.swift +122 -0
- package/examples/taskflow/generated/ios/TaskFlow/Sources/TaskFlow/Screens/CalendarView.swift +21 -0
- package/examples/taskflow/generated/ios/TaskFlow/Sources/TaskFlow/Screens/HomeView.swift +201 -0
- package/examples/taskflow/generated/ios/TaskFlow/Sources/TaskFlow/Screens/ProfileEditView.swift +48 -0
- package/examples/taskflow/generated/ios/TaskFlow/Sources/TaskFlow/Screens/ProjectDetailView.swift +59 -0
- package/examples/taskflow/generated/ios/TaskFlow/Sources/TaskFlow/Screens/ProjectsView.swift +63 -0
- package/examples/taskflow/generated/ios/TaskFlow/Sources/TaskFlow/Screens/SettingsView.swift +85 -0
- package/examples/taskflow/generated/ios/TaskFlow/Sources/TaskFlow/Screens/TaskDetailView.swift +219 -0
- package/examples/taskflow/generated/ios/TaskFlow/Sources/TaskFlow/Support/AppModel.swift +320 -0
- package/examples/taskflow/generated/ios/TaskFlow/Sources/TaskFlow/Support/AppSupport.swift +41 -0
- package/examples/taskflow/generated/ios/TaskFlow/project.yml +26 -0
- package/examples/taskflow/generated/web/TaskFlow/README.md +19 -0
- package/examples/taskflow/generated/web/TaskFlow/index.html +12 -0
- package/examples/taskflow/generated/web/TaskFlow/package-lock.json +1908 -0
- package/examples/taskflow/generated/web/TaskFlow/package.json +24 -0
- package/examples/taskflow/generated/web/TaskFlow/src/App.tsx +58 -0
- package/examples/taskflow/generated/web/TaskFlow/src/AppShell.tsx +55 -0
- package/examples/taskflow/generated/web/TaskFlow/src/components/Common.tsx +82 -0
- package/examples/taskflow/generated/web/TaskFlow/src/components/Modals.tsx +191 -0
- package/examples/taskflow/generated/web/TaskFlow/src/components/Nav.tsx +41 -0
- package/examples/taskflow/generated/web/TaskFlow/src/generated/messages.ts +131 -0
- package/examples/taskflow/generated/web/TaskFlow/src/hooks.ts +25 -0
- package/examples/taskflow/generated/web/TaskFlow/src/i18n.ts +39 -0
- package/examples/taskflow/generated/web/TaskFlow/src/locales.en.json +111 -0
- package/examples/taskflow/generated/web/TaskFlow/src/main.tsx +13 -0
- package/examples/taskflow/generated/web/TaskFlow/src/screens/HomeScreen.tsx +111 -0
- package/examples/taskflow/generated/web/TaskFlow/src/screens/ProjectsScreen.tsx +82 -0
- package/examples/taskflow/generated/web/TaskFlow/src/screens/SettingsScreens.tsx +132 -0
- package/examples/taskflow/generated/web/TaskFlow/src/screens/TaskDetail.tsx +105 -0
- package/examples/taskflow/generated/web/TaskFlow/src/store.ts +216 -0
- package/examples/taskflow/generated/web/TaskFlow/src/styles.css +617 -0
- package/examples/taskflow/generated/web/TaskFlow/src/types.ts +64 -0
- package/examples/taskflow/generated/web/TaskFlow/src/utils.ts +78 -0
- package/examples/taskflow/generated/web/TaskFlow/tsconfig.json +21 -0
- package/examples/taskflow/generated/web/TaskFlow/vite.config.ts +6 -0
- package/examples/taskflow/openuispec/README.md +49 -0
- package/examples/todo-orbit/AGENTS.md +46 -14
- package/examples/todo-orbit/CLAUDE.md +46 -14
- package/examples/todo-orbit/generated/android/Todo Orbit/app/src/main/java/uz/rsteam/todoorbit/ui/components/CommonComponents.kt +69 -18
- package/examples/todo-orbit/generated/android/Todo Orbit/app/src/main/java/uz/rsteam/todoorbit/ui/screens/TasksScreen.kt +5 -0
- package/examples/todo-orbit/generated/android/Todo Orbit/app/src/main/java/uz/rsteam/todoorbit/ui/sheets/EditorSheets.kt +5 -2
- package/examples/todo-orbit/generated/android/Todo Orbit/app/src/main/res/values/strings.xml +1 -0
- package/examples/todo-orbit/generated/android/Todo Orbit/app/src/main/res/values-ru/strings.xml +1 -0
- package/examples/todo-orbit/generated/ios/Todo Orbit/Resources/en.lproj/Localizable.strings +1 -0
- package/examples/todo-orbit/generated/ios/Todo Orbit/Resources/ru.lproj/Localizable.strings +1 -0
- package/examples/todo-orbit/generated/ios/Todo Orbit/Sources/TodoOrbit/Flows/RecurringRuleSheet.swift +3 -0
- package/examples/todo-orbit/generated/ios/Todo Orbit/Sources/TodoOrbit/Flows/TaskEditorSheet.swift +1 -0
- package/examples/todo-orbit/generated/ios/Todo Orbit/Sources/TodoOrbit/Screens/SettingsView.swift +2 -0
- package/examples/todo-orbit/generated/ios/Todo Orbit/Sources/TodoOrbit/Screens/TasksHomeView.swift +1 -0
- package/examples/todo-orbit/generated/ios/Todo Orbit/Sources/TodoOrbit/Support/AppModel.swift +1 -1
- package/examples/todo-orbit/generated/web/Todo Orbit/src/App.tsx +59 -6
- package/examples/todo-orbit/generated/web/Todo Orbit/src/styles.css +40 -0
- package/examples/todo-orbit/openuispec/README.md +24 -131
- package/examples/todo-orbit/openuispec/flows/create_recurring_rule.yaml +3 -0
- package/examples/todo-orbit/openuispec/flows/create_task.yaml +1 -0
- package/examples/todo-orbit/openuispec/flows/edit_task.yaml +1 -0
- package/examples/todo-orbit/openuispec/locales/en.json +1 -0
- package/examples/todo-orbit/openuispec/locales/ru.json +1 -0
- package/examples/todo-orbit/openuispec/screens/task_detail.yaml +1 -0
- package/examples/todo-orbit/openuispec/tokens/icons.yaml +6 -0
- package/package.json +6 -1
- package/prepare/index.ts +391 -0
- package/schema/semantic-lint.ts +592 -0
- package/schema/validate.ts +17 -13
- package/status/index.ts +200 -0
- /package/examples/taskflow/{contracts → openuispec/contracts}/README.md +0 -0
- /package/examples/taskflow/{contracts → openuispec/contracts}/action_trigger.yaml +0 -0
- /package/examples/taskflow/{contracts → openuispec/contracts}/collection.yaml +0 -0
- /package/examples/taskflow/{contracts → openuispec/contracts}/data_display.yaml +0 -0
- /package/examples/taskflow/{contracts → openuispec/contracts}/feedback.yaml +0 -0
- /package/examples/taskflow/{contracts → openuispec/contracts}/input_field.yaml +0 -0
- /package/examples/taskflow/{contracts → openuispec/contracts}/nav_container.yaml +0 -0
- /package/examples/taskflow/{contracts → openuispec/contracts}/surface.yaml +0 -0
- /package/examples/taskflow/{contracts → openuispec/contracts}/x_media_player.yaml +0 -0
- /package/examples/taskflow/{flows → openuispec/flows}/create_task.yaml +0 -0
- /package/examples/taskflow/{flows → openuispec/flows}/edit_task.yaml +0 -0
- /package/examples/taskflow/{locales → openuispec/locales}/en.json +0 -0
- /package/examples/taskflow/{openuispec.yaml → openuispec/openuispec.yaml} +0 -0
- /package/examples/taskflow/{platform → openuispec/platform}/android.yaml +0 -0
- /package/examples/taskflow/{platform → openuispec/platform}/ios.yaml +0 -0
- /package/examples/taskflow/{platform → openuispec/platform}/web.yaml +0 -0
- /package/examples/taskflow/{screens → openuispec/screens}/calendar.yaml +0 -0
- /package/examples/taskflow/{screens → openuispec/screens}/home.yaml +0 -0
- /package/examples/taskflow/{screens → openuispec/screens}/profile_edit.yaml +0 -0
- /package/examples/taskflow/{screens → openuispec/screens}/project_detail.yaml +0 -0
- /package/examples/taskflow/{screens → openuispec/screens}/projects.yaml +0 -0
- /package/examples/taskflow/{screens → openuispec/screens}/settings.yaml +0 -0
- /package/examples/taskflow/{screens → openuispec/screens}/task_detail.yaml +0 -0
- /package/examples/taskflow/{tokens → openuispec/tokens}/color.yaml +0 -0
- /package/examples/taskflow/{tokens → openuispec/tokens}/elevation.yaml +0 -0
- /package/examples/taskflow/{tokens → openuispec/tokens}/icons.yaml +0 -0
- /package/examples/taskflow/{tokens → openuispec/tokens}/layout.yaml +0 -0
- /package/examples/taskflow/{tokens → openuispec/tokens}/motion.yaml +0 -0
- /package/examples/taskflow/{tokens → openuispec/tokens}/spacing.yaml +0 -0
- /package/examples/taskflow/{tokens → openuispec/tokens}/themes.yaml +0 -0
- /package/examples/taskflow/{tokens → openuispec/tokens}/typography.yaml +0 -0
package/status/index.ts
ADDED
|
@@ -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
|
+
}
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|