@ogygie/studio 0.5.4 → 0.7.0
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/dist/server.js
CHANGED
|
@@ -104,6 +104,7 @@ import { z as z3 } from "zod";
|
|
|
104
104
|
// ../ogygie-core/src/manifest.schema.ts
|
|
105
105
|
import { z as z2 } from "zod";
|
|
106
106
|
var FeatureNameSchema = z2.string().regex(/^[a-z][a-z0-9]*(-[a-z0-9]+)*$/, "kebab-case required");
|
|
107
|
+
var PackageDependencySchema = z2.string().regex(/^package:[a-z][a-z0-9]*(-[a-z0-9]+)*$/, "expected package:<kebab-case-name>");
|
|
107
108
|
var HttpRouteSchema = z2.object({
|
|
108
109
|
method: z2.enum(["GET", "POST", "PUT", "PATCH", "DELETE"]),
|
|
109
110
|
path: z2.string().startsWith("/api/"),
|
|
@@ -128,7 +129,9 @@ var FeatureManifestSchema = z2.object({
|
|
|
128
129
|
dbTables: z2.array(DbTableDeclarationSchema).describe(
|
|
129
130
|
"Drizzle tables owned by this feature (one table = one owner). String = tenant-scoped; { name, shared: true } = shared referential"
|
|
130
131
|
),
|
|
131
|
-
dependsOn: z2.array(FeatureNameSchema).describe(
|
|
132
|
+
dependsOn: z2.array(z2.union([FeatureNameSchema, PackageDependencySchema])).describe(
|
|
133
|
+
"Features imported through their index.ts, and product packages as package:<name> \u2014 nothing else"
|
|
134
|
+
),
|
|
132
135
|
status: z2.enum(["skeleton", "in-progress", "delivered"])
|
|
133
136
|
});
|
|
134
137
|
var OgygieVersionSchema = z2.string().regex(/^\d+\.\d+\.\d+$/, "expected a plain x.y.z version");
|
|
@@ -156,6 +159,20 @@ var VocabularyEntrySchema = z2.object({
|
|
|
156
159
|
var ProductVocabularySchema = z2.object({
|
|
157
160
|
entries: z2.array(VocabularyEntrySchema)
|
|
158
161
|
});
|
|
162
|
+
var PackageManifestSchema = z2.object({
|
|
163
|
+
name: FeatureNameSchema,
|
|
164
|
+
path: z2.string().describe("Folder relative to the repo root, e.g. packages/solver"),
|
|
165
|
+
intent: z2.string().min(20).max(300).describe("The package's 'why' in 1-3 sentences"),
|
|
166
|
+
spec: z2.string().nullable(),
|
|
167
|
+
dependsOn: z2.array(PackageDependencySchema).describe("Other PRODUCT packages, as package:<name> \u2014 never a feature: a package that depended on one would live under an app, and would be a feature"),
|
|
168
|
+
status: z2.enum(["skeleton", "in-progress", "delivered"])
|
|
169
|
+
});
|
|
170
|
+
var TenancyManifestSchema = z2.object({
|
|
171
|
+
column: z2.string().min(1).describe("SQL name of the tenant column, e.g. workspace_id \u2014 the one AGENTS.product.md announces"),
|
|
172
|
+
rawDbAllowed: z2.array(FeatureNameSchema).default([]).describe(
|
|
173
|
+
"Features allowed to reach the raw database: the tenancy socle, which BUILDS the contexts and therefore predates them. Every other feature goes through tenantDb"
|
|
174
|
+
)
|
|
175
|
+
});
|
|
159
176
|
var OgygieManifestSchema = z2.object({
|
|
160
177
|
version: z2.literal(1),
|
|
161
178
|
product: z2.object({
|
|
@@ -186,6 +203,10 @@ var OgygieManifestSchema = z2.object({
|
|
|
186
203
|
})
|
|
187
204
|
),
|
|
188
205
|
features: z2.array(FeatureManifestSchema),
|
|
206
|
+
tenancy: TenancyManifestSchema.optional().describe(
|
|
207
|
+
"Product values the framework gates need \u2014 absent, the tenancy checks do not run"
|
|
208
|
+
),
|
|
209
|
+
packages: z2.array(PackageManifestSchema).optional().describe("Product code living outside every app \u2014 libraries, engines. Absent = the project has none"),
|
|
189
210
|
vocabulary: ProductVocabularySchema.optional().describe(
|
|
190
211
|
"The product's closed vocabulary \u2014 declared here, enforced by `ogygie verify-vocabulary`. Absent = gate silent"
|
|
191
212
|
),
|
|
@@ -195,6 +216,53 @@ var OgygieManifestSchema = z2.object({
|
|
|
195
216
|
specsFolder: z2.literal("specs/")
|
|
196
217
|
})
|
|
197
218
|
}).superRefine((manifest, context) => {
|
|
219
|
+
const featureNames = new Set(manifest.features.map((feature) => feature.name));
|
|
220
|
+
const packageNames = /* @__PURE__ */ new Set();
|
|
221
|
+
(manifest.packages ?? []).forEach((packageEntry, index) => {
|
|
222
|
+
if (featureNames.has(packageEntry.name)) {
|
|
223
|
+
context.addIssue({
|
|
224
|
+
code: "custom",
|
|
225
|
+
path: ["packages", index, "name"],
|
|
226
|
+
message: `"${packageEntry.name}" is already the name of a feature \u2014 one name designates one thing`
|
|
227
|
+
});
|
|
228
|
+
}
|
|
229
|
+
if (packageNames.has(packageEntry.name)) {
|
|
230
|
+
context.addIssue({
|
|
231
|
+
code: "custom",
|
|
232
|
+
path: ["packages", index, "name"],
|
|
233
|
+
message: `package "${packageEntry.name}" is declared twice`
|
|
234
|
+
});
|
|
235
|
+
}
|
|
236
|
+
packageNames.add(packageEntry.name);
|
|
237
|
+
});
|
|
238
|
+
const checkPackageDependencies = (dependsOn, path) => {
|
|
239
|
+
dependsOn.forEach((dependency, dependencyIndex) => {
|
|
240
|
+
if (!dependency.startsWith("package:")) return;
|
|
241
|
+
const target = dependency.slice("package:".length);
|
|
242
|
+
if (!packageNames.has(target)) {
|
|
243
|
+
context.addIssue({
|
|
244
|
+
code: "custom",
|
|
245
|
+
path: [...path, dependencyIndex],
|
|
246
|
+
message: `dependency "${dependency}" matches no declared package`
|
|
247
|
+
});
|
|
248
|
+
}
|
|
249
|
+
});
|
|
250
|
+
};
|
|
251
|
+
manifest.features.forEach((feature, index) => {
|
|
252
|
+
checkPackageDependencies(feature.dependsOn, ["features", index, "dependsOn"]);
|
|
253
|
+
});
|
|
254
|
+
(manifest.packages ?? []).forEach((packageEntry, index) => {
|
|
255
|
+
checkPackageDependencies(packageEntry.dependsOn, ["packages", index, "dependsOn"]);
|
|
256
|
+
});
|
|
257
|
+
(manifest.tenancy?.rawDbAllowed ?? []).forEach((featureName, index) => {
|
|
258
|
+
if (!featureNames.has(featureName)) {
|
|
259
|
+
context.addIssue({
|
|
260
|
+
code: "custom",
|
|
261
|
+
path: ["tenancy", "rawDbAllowed", index],
|
|
262
|
+
message: `"${featureName}" matches no declared feature`
|
|
263
|
+
});
|
|
264
|
+
}
|
|
265
|
+
});
|
|
198
266
|
const canonicalOwners = /* @__PURE__ */ new Map();
|
|
199
267
|
const aliasOwners = /* @__PURE__ */ new Map();
|
|
200
268
|
(manifest.vocabulary?.entries ?? []).forEach((entry, index) => {
|