Skip to content

Commit 9ae1ff9

Browse files
committed
Refine schema handling and improve outdated schema checks
Enhanced DDL logic to accurately detect outdated schemas and return detailed results. Adjusted file handling to ensure consistent behavior with relative paths and added improvements to test coverage. Minor updates to comments and types for better clarity.
1 parent 0a1c300 commit 9ae1ff9

File tree

2 files changed

+39
-7
lines changed

2 files changed

+39
-7
lines changed

src/ddl.ts

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -89,7 +89,8 @@ export class DDL {
8989
const schemas = await DDL.generator(classFiles, base);
9090
for (const [c, f] of Object.entries(classFiles)) {
9191
const etag = await eTag(await Deno.stat(f));
92-
schemas[c] = DDL.#cleanSchema(schemas[c], c, undefined, "file://./" + f, etag);
92+
const file = f.startsWith("/") ? f : "./" + f;
93+
schemas[c] = DDL.#cleanSchema(schemas[c], c, undefined, "file://" + file, etag);
9394
if (enhance) schemas[c] = DDL.enhanceSchema(schemas[c]);
9495
}
9596

@@ -141,16 +142,19 @@ export class DDL {
141142
* @param base - the directory where the schema file is located
142143
*/
143144
static async outdatedSchema(schema: Schema, base = ""): Promise<boolean> {
145+
if (!base.startsWith("/")) throw new Error("Base must be absolute within the system");
144146
if (!schema.$id) throw new Error("Schema must have an '$id' property to test if it is outdated");
145147

146148
// Get file and schema create date from $id
147149
const url = new URL(schema.$id);
148-
const file = (base + url.pathname).replace(/\/\//g, "/");
150+
const file = ((schema.$id.startsWith("file://./") ? base : "") + url.pathname).replace(/\/\//g, "/");
149151
const fileInfo = await Deno.stat(file);
150152
const schemaDate = url.hash.substring(1);
151153

152154
// First compare dates
153-
if (schemaDate > fileInfo.mtime!.toISOString()) return true;
155+
const fileDate = fileInfo.mtime!.toISOString().substring(0, 19);
156+
// console.log(url.pathname, " --- ", schemaDate, " : ", fileDate, " -> ", schemaDate < fileInfo.mtime!.toISOString());
157+
if (schemaDate < fileDate) return true;
154158

155159
// If the date comparison is not enough to tell, then compare etags
156160
const etag = await eTag(await Deno.stat(file));

test/ddl.test.ts

Lines changed: 32 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ console = hub("*", "debug", { fileLine: true });
1414

1515
const CI = Deno.env.has("CI");
1616
const DB = await dbInit(getProvider());
17+
const BASE = import.meta.dirname + "/../";
1718

1819
// Generator function is declared here so that it does not go into the published module
1920
DDL.generator = async function (classFiles: Record<string, string>, base?: string) {
@@ -28,8 +29,7 @@ DDL.generator = async function (classFiles: Record<string, string>, base?: strin
2829
import staticSchema from "../resources/account.json" with { type: "json" };
2930

3031
// Generate dynamic schema to make sure it's the same result
31-
// const classFiles = { "Account": "resources/account.ts", "Point": "resources/point.ts" };
32-
const classFiles = { "Account": "resources/account.ts" };
32+
const classFiles: Record<string, string> = { "Account": "resources/account.ts", "Point": "resources/point.ts" };
3333

3434
// Track bug https://github.com/denoland/deno/issues/28206
3535
// const { Account: dynamicSchema } = await DDL.generateSchemas(classFiles, import.meta.dirname! + "/../", true);
@@ -175,13 +175,41 @@ Deno.test("Schema Generation", async function () {
175175
await delay(1000 - (new Date()).getMilliseconds());
176176

177177
// Generate two schemas in a row, they should be identical
178-
const first = await DDL.generateSchemas(classFiles, import.meta.dirname! + "/../", true);
178+
const first = await DDL.generateSchemas(classFiles, BASE, true);
179179
assertExists(first);
180-
const second = await DDL.generateSchemas(classFiles, import.meta.dirname! + "/../", true);
180+
const second = await DDL.generateSchemas(classFiles, BASE, true);
181181
assertNotEquals(first, second);
182182
assertEquals(JSON.stringify(first), JSON.stringify(second));
183183
});
184184

185+
// Execute the table creation on the provided platform
186+
Deno.test.only("Schema Outdated", async function () {
187+
// Generate schemas and save it
188+
let schemas = await DDL.generateSchemas(classFiles, BASE, true);
189+
Deno.writeTextFileSync("/tmp/schemas.json", JSON.stringify(schemas, null, 2));
190+
191+
// Is it outdated from the get-go?
192+
assertEquals(await DDL.outdatedSchemas(schemas, BASE), []);
193+
194+
// Create other specific classes called Point2D/Point3D and add to schema (with error)
195+
Deno.writeTextFileSync("/tmp/point2d.ts", "export default class Point2D { x = 0; y = 0; }");
196+
Deno.writeTextFileSync("/tmp/point3d.ts", "export default class Point3D { x = 0; y = 0; }");
197+
classFiles["Point2D"] = "/tmp/point2d.ts";
198+
classFiles["Point3D"] = "/tmp/point3d.ts";
199+
Deno.writeTextFileSync("/tmp/schemas.json", JSON.stringify(await DDL.generateSchemas(classFiles, BASE, true), null, 2));
200+
201+
// Load the schema with a random query string to force a reload
202+
schemas = (await import("/tmp/schemas.json?force=" + Date.now(), { with: { type: "json" } })).default as Record<string, Schema>;
203+
// console.log(JSON.stringify(schemas, null, 2));
204+
205+
// They should not be outdated
206+
assertEquals(await DDL.outdatedSchemas(schemas, BASE), []);
207+
208+
// Now correct initial mistake and check again
209+
Deno.writeTextFileSync("/tmp/point3d.ts", "export default class Point3D { x = 0; y = 0; z = 0; }");
210+
assertEquals(await DDL.outdatedSchemas(schemas, BASE), ["Point3D"]);
211+
});
212+
185213
// Execute the table creation on the provided platform
186214
Deno.test("Disconnect", { sanitizeResources: false, sanitizeOps: false }, async function () {
187215
await DB.disconnect();

0 commit comments

Comments
 (0)