@mandujs/core 0.54.12 → 0.54.14
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/package.json +9 -1
- package/scripts/postinstall-lock.ts +153 -153
- package/src/a11y/run-audit.ts +15 -15
- package/src/agent/__tests__/context.test.ts +49 -1
- package/src/agent/context.ts +535 -535
- package/src/agent/index.ts +6 -6
- package/src/agent/plan.ts +282 -282
- package/src/agent/repair.ts +171 -171
- package/src/agent/sync.ts +200 -200
- package/src/agent/types.ts +8 -0
- package/src/agent/verify.ts +100 -2
- package/src/brain/doctor/analyzer.ts +7 -7
- package/src/bundler/__tests__/build-runner.ts +36 -16
- package/src/bundler/__tests__/cold-start.test.ts +60 -60
- package/src/bundler/__tests__/css.test.ts +20 -20
- package/src/bundler/__tests__/fast-refresh.test.ts +24 -17
- package/src/bundler/analyzer.ts +15 -15
- package/src/bundler/build.test.ts +136 -48
- package/src/bundler/build.ts +193 -122
- package/src/bundler/css.ts +42 -42
- package/src/bundler/manifest-schema.ts +21 -21
- package/src/bundler/plugins/__tests__/block-generated-imports.test.ts +13 -13
- package/src/bundler/plugins/block-generated-imports.ts +13 -13
- package/src/bundler/types.ts +31 -31
- package/src/client/island.ts +79 -79
- package/src/config/validate.ts +1 -1
- package/src/contract/schema.ts +7 -0
- package/src/deploy/inference/context.ts +82 -82
- package/src/devtools/client/components/panel/islands-panel.tsx +16 -16
- package/src/devtools/client/components/panel/panel-container.tsx +1 -1
- package/src/error/formatter.ts +10 -1
- package/src/experimental/index.ts +10 -0
- package/src/filling/context.ts +17 -17
- package/src/filling/filling.ts +22 -1
- package/src/filling/index.ts +15 -1
- package/src/generator/generate.ts +30 -30
- package/src/generator/index.ts +3 -3
- package/src/generator/templates.ts +210 -210
- package/src/guard/check.ts +9 -9
- package/src/guard/config-guard.ts +13 -13
- package/src/guard/fs-routes-policy.ts +51 -51
- package/src/guard/index.ts +11 -11
- package/src/index.ts +0 -10
- package/src/internal/index.ts +25 -0
- package/src/kitchen/api/file-api.ts +11 -11
- package/src/report/index.ts +1 -1
- package/src/resource/__tests__/generator.test.ts +6 -6
- package/src/resource/__tests__/schema.test.ts +14 -14
- package/src/resource/ddl/__tests__/emit.test.ts +165 -165
- package/src/resource/ddl/emit.ts +146 -146
- package/src/resource/generator-schema.ts +11 -11
- package/src/resource/generators/slot.ts +72 -72
- package/src/resource/schema.ts +21 -21
- package/src/router/client-entry.test.ts +84 -41
- package/src/router/client-entry.ts +156 -89
- package/src/router/fs-routes.test.ts +90 -0
- package/src/router/fs-routes.ts +37 -29
- package/src/router/fs-scanner.ts +81 -33
- package/src/router/fs-types.ts +8 -5
- package/src/runtime/__tests__/devtools-adapter.test.ts +68 -68
- package/src/runtime/__tests__/observability-lifecycle.test.ts +103 -103
- package/src/runtime/__tests__/page-render-response.test.ts +164 -103
- package/src/runtime/__tests__/request-middleware.test.ts +70 -70
- package/src/runtime/devtools-adapter.ts +68 -68
- package/src/runtime/escape.ts +34 -34
- package/src/runtime/image-feature.ts +15 -0
- package/src/runtime/observability-lifecycle.ts +290 -290
- package/src/runtime/page-render-response.ts +208 -106
- package/src/runtime/rate-limit.ts +231 -0
- package/src/runtime/request-middleware.ts +31 -31
- package/src/runtime/router.test.ts +4 -4
- package/src/runtime/router.ts +10 -12
- package/src/runtime/scheduler-lifecycle.ts +64 -0
- package/src/runtime/server.ts +148 -353
- package/src/runtime/ssr.ts +59 -59
- package/src/runtime/static-files.ts +289 -289
- package/src/runtime/streaming-ssr.ts +22 -22
- package/src/spec/schema.ts +4 -3
- package/src/watcher/__tests__/watcher.test.ts +59 -59
- package/src/watcher/watcher.ts +61 -61
|
@@ -415,112 +415,112 @@ describe("emitChange — add-column", () => {
|
|
|
415
415
|
expect(emitChange(change, "mysql"))
|
|
416
416
|
.toBe("ALTER TABLE `users` ADD COLUMN `age` DOUBLE;");
|
|
417
417
|
});
|
|
418
|
-
test("sqlite", () => {
|
|
419
|
-
expect(emitChange(change, "sqlite"))
|
|
420
|
-
.toBe('ALTER TABLE "users" ADD COLUMN "age" REAL;');
|
|
421
|
-
});
|
|
422
|
-
|
|
423
|
-
test("sqlite refuses required add-column without a non-NULL constant default (#294)", () => {
|
|
424
|
-
const required: Change = {
|
|
425
|
-
kind: "add-column",
|
|
426
|
-
resourceName: "votes",
|
|
427
|
-
field: field({ name: "created_at", type: "date" }),
|
|
428
|
-
};
|
|
429
|
-
|
|
430
|
-
expect(() => emitChange(required, "sqlite")).toThrow(
|
|
431
|
-
/SQLite cannot add required column "created_at"/,
|
|
432
|
-
);
|
|
433
|
-
});
|
|
434
|
-
|
|
435
|
-
test("sqlite allows required add-column when a scalar literal default is present", () => {
|
|
436
|
-
const requiredWithDefault: Change = {
|
|
437
|
-
kind: "add-column",
|
|
438
|
-
resourceName: "votes",
|
|
439
|
-
field: field({
|
|
440
|
-
name: "created_at",
|
|
441
|
-
type: "date",
|
|
442
|
-
default: { kind: "literal", value: "1970-01-01T00:00:00.000Z" },
|
|
443
|
-
}),
|
|
444
|
-
};
|
|
445
|
-
|
|
446
|
-
expect(emitChange(requiredWithDefault, "sqlite")).toBe(
|
|
447
|
-
'ALTER TABLE "votes" ADD COLUMN "created_at" TEXT NOT NULL DEFAULT \'1970-01-01T00:00:00.000Z\';',
|
|
448
|
-
);
|
|
449
|
-
});
|
|
450
|
-
|
|
451
|
-
test("sqlite refuses default: now on add-column because SQLite requires a constant default", () => {
|
|
452
|
-
const nowDefault: Change = {
|
|
453
|
-
kind: "add-column",
|
|
454
|
-
resourceName: "votes",
|
|
455
|
-
field: field({
|
|
456
|
-
name: "created_at",
|
|
457
|
-
type: "date",
|
|
458
|
-
nullable: true,
|
|
459
|
-
default: { kind: "now" },
|
|
460
|
-
}),
|
|
461
|
-
};
|
|
462
|
-
|
|
463
|
-
expect(() => emitChange(nowDefault, "sqlite")).toThrow(
|
|
464
|
-
/CURRENT_TIMESTAMP, which SQLite rejects/,
|
|
465
|
-
);
|
|
466
|
-
});
|
|
467
|
-
|
|
468
|
-
test("sqlite refuses UNIQUE add-column because SQLite cannot add the constraint in place", () => {
|
|
469
|
-
const unique: Change = {
|
|
470
|
-
kind: "add-column",
|
|
471
|
-
resourceName: "votes",
|
|
472
|
-
field: field({ name: "slug", type: "string", nullable: true, unique: true }),
|
|
473
|
-
};
|
|
474
|
-
|
|
475
|
-
expect(() => emitChange(unique, "sqlite")).toThrow(/cannot add UNIQUE column/);
|
|
476
|
-
});
|
|
477
|
-
|
|
478
|
-
test("sqlite refuses PRIMARY KEY add-column because SQLite cannot add the constraint in place", () => {
|
|
479
|
-
const primary: Change = {
|
|
480
|
-
kind: "add-column",
|
|
481
|
-
resourceName: "votes",
|
|
482
|
-
field: field({ name: "other_id", type: "uuid", primary: true }),
|
|
483
|
-
};
|
|
484
|
-
|
|
485
|
-
expect(() => emitChange(primary, "sqlite")).toThrow(/cannot add PRIMARY KEY column/);
|
|
486
|
-
});
|
|
487
|
-
|
|
488
|
-
test("sqlite refuses raw function defaults on add-column", () => {
|
|
489
|
-
const rawFunction: Change = {
|
|
490
|
-
kind: "add-column",
|
|
491
|
-
resourceName: "votes",
|
|
492
|
-
field: field({
|
|
493
|
-
name: "created_at",
|
|
494
|
-
type: "date",
|
|
495
|
-
nullable: true,
|
|
496
|
-
default: { kind: "sql", expr: "datetime('now')" },
|
|
497
|
-
}),
|
|
498
|
-
};
|
|
499
|
-
|
|
500
|
-
expect(() => emitChange(rawFunction, "sqlite")).toThrow(
|
|
501
|
-
/non-constant function defaults/,
|
|
502
|
-
);
|
|
503
|
-
});
|
|
504
|
-
|
|
505
|
-
test("sqlite refuses raw expression defaults on add-column", () => {
|
|
506
|
-
const rawExpression: Change = {
|
|
507
|
-
kind: "add-column",
|
|
508
|
-
resourceName: "votes",
|
|
509
|
-
field: field({
|
|
510
|
-
name: "score",
|
|
511
|
-
type: "number",
|
|
512
|
-
nullable: true,
|
|
513
|
-
default: { kind: "sql", expr: "(1+2)" },
|
|
514
|
-
}),
|
|
515
|
-
};
|
|
516
|
-
|
|
517
|
-
expect(() => emitChange(rawExpression, "sqlite")).toThrow(
|
|
518
|
-
/only accepts literal constant defaults/,
|
|
519
|
-
);
|
|
520
|
-
});
|
|
521
|
-
|
|
522
|
-
test("indexed:true field emits ADD COLUMN plus auto CREATE INDEX", () => {
|
|
523
|
-
const indexed: Change = {
|
|
418
|
+
test("sqlite", () => {
|
|
419
|
+
expect(emitChange(change, "sqlite"))
|
|
420
|
+
.toBe('ALTER TABLE "users" ADD COLUMN "age" REAL;');
|
|
421
|
+
});
|
|
422
|
+
|
|
423
|
+
test("sqlite refuses required add-column without a non-NULL constant default (#294)", () => {
|
|
424
|
+
const required: Change = {
|
|
425
|
+
kind: "add-column",
|
|
426
|
+
resourceName: "votes",
|
|
427
|
+
field: field({ name: "created_at", type: "date" }),
|
|
428
|
+
};
|
|
429
|
+
|
|
430
|
+
expect(() => emitChange(required, "sqlite")).toThrow(
|
|
431
|
+
/SQLite cannot add required column "created_at"/,
|
|
432
|
+
);
|
|
433
|
+
});
|
|
434
|
+
|
|
435
|
+
test("sqlite allows required add-column when a scalar literal default is present", () => {
|
|
436
|
+
const requiredWithDefault: Change = {
|
|
437
|
+
kind: "add-column",
|
|
438
|
+
resourceName: "votes",
|
|
439
|
+
field: field({
|
|
440
|
+
name: "created_at",
|
|
441
|
+
type: "date",
|
|
442
|
+
default: { kind: "literal", value: "1970-01-01T00:00:00.000Z" },
|
|
443
|
+
}),
|
|
444
|
+
};
|
|
445
|
+
|
|
446
|
+
expect(emitChange(requiredWithDefault, "sqlite")).toBe(
|
|
447
|
+
'ALTER TABLE "votes" ADD COLUMN "created_at" TEXT NOT NULL DEFAULT \'1970-01-01T00:00:00.000Z\';',
|
|
448
|
+
);
|
|
449
|
+
});
|
|
450
|
+
|
|
451
|
+
test("sqlite refuses default: now on add-column because SQLite requires a constant default", () => {
|
|
452
|
+
const nowDefault: Change = {
|
|
453
|
+
kind: "add-column",
|
|
454
|
+
resourceName: "votes",
|
|
455
|
+
field: field({
|
|
456
|
+
name: "created_at",
|
|
457
|
+
type: "date",
|
|
458
|
+
nullable: true,
|
|
459
|
+
default: { kind: "now" },
|
|
460
|
+
}),
|
|
461
|
+
};
|
|
462
|
+
|
|
463
|
+
expect(() => emitChange(nowDefault, "sqlite")).toThrow(
|
|
464
|
+
/CURRENT_TIMESTAMP, which SQLite rejects/,
|
|
465
|
+
);
|
|
466
|
+
});
|
|
467
|
+
|
|
468
|
+
test("sqlite refuses UNIQUE add-column because SQLite cannot add the constraint in place", () => {
|
|
469
|
+
const unique: Change = {
|
|
470
|
+
kind: "add-column",
|
|
471
|
+
resourceName: "votes",
|
|
472
|
+
field: field({ name: "slug", type: "string", nullable: true, unique: true }),
|
|
473
|
+
};
|
|
474
|
+
|
|
475
|
+
expect(() => emitChange(unique, "sqlite")).toThrow(/cannot add UNIQUE column/);
|
|
476
|
+
});
|
|
477
|
+
|
|
478
|
+
test("sqlite refuses PRIMARY KEY add-column because SQLite cannot add the constraint in place", () => {
|
|
479
|
+
const primary: Change = {
|
|
480
|
+
kind: "add-column",
|
|
481
|
+
resourceName: "votes",
|
|
482
|
+
field: field({ name: "other_id", type: "uuid", primary: true }),
|
|
483
|
+
};
|
|
484
|
+
|
|
485
|
+
expect(() => emitChange(primary, "sqlite")).toThrow(/cannot add PRIMARY KEY column/);
|
|
486
|
+
});
|
|
487
|
+
|
|
488
|
+
test("sqlite refuses raw function defaults on add-column", () => {
|
|
489
|
+
const rawFunction: Change = {
|
|
490
|
+
kind: "add-column",
|
|
491
|
+
resourceName: "votes",
|
|
492
|
+
field: field({
|
|
493
|
+
name: "created_at",
|
|
494
|
+
type: "date",
|
|
495
|
+
nullable: true,
|
|
496
|
+
default: { kind: "sql", expr: "datetime('now')" },
|
|
497
|
+
}),
|
|
498
|
+
};
|
|
499
|
+
|
|
500
|
+
expect(() => emitChange(rawFunction, "sqlite")).toThrow(
|
|
501
|
+
/non-constant function defaults/,
|
|
502
|
+
);
|
|
503
|
+
});
|
|
504
|
+
|
|
505
|
+
test("sqlite refuses raw expression defaults on add-column", () => {
|
|
506
|
+
const rawExpression: Change = {
|
|
507
|
+
kind: "add-column",
|
|
508
|
+
resourceName: "votes",
|
|
509
|
+
field: field({
|
|
510
|
+
name: "score",
|
|
511
|
+
type: "number",
|
|
512
|
+
nullable: true,
|
|
513
|
+
default: { kind: "sql", expr: "(1+2)" },
|
|
514
|
+
}),
|
|
515
|
+
};
|
|
516
|
+
|
|
517
|
+
expect(() => emitChange(rawExpression, "sqlite")).toThrow(
|
|
518
|
+
/only accepts literal constant defaults/,
|
|
519
|
+
);
|
|
520
|
+
});
|
|
521
|
+
|
|
522
|
+
test("indexed:true field emits ADD COLUMN plus auto CREATE INDEX", () => {
|
|
523
|
+
const indexed: Change = {
|
|
524
524
|
kind: "add-column",
|
|
525
525
|
resourceName: "users",
|
|
526
526
|
field: field({ name: "role", type: "string", indexed: true }),
|
|
@@ -576,24 +576,24 @@ describe("emitChange — alter-column-type stub", () => {
|
|
|
576
576
|
stub: true,
|
|
577
577
|
};
|
|
578
578
|
|
|
579
|
-
test("emits comment block with required TODO text", () => {
|
|
580
|
-
for (const p of PROVIDERS) {
|
|
581
|
-
const sql = emitChange(change, p);
|
|
582
|
-
expect(sql).toContain("-- TODO: Mandu does not auto-generate ALTER COLUMN TYPE in v1.");
|
|
583
|
-
expect(sql).toContain("mandu db apply");
|
|
584
|
-
expect(sql).toContain("Column type change detected: users.age");
|
|
585
|
-
expect(sql).toContain("from: number");
|
|
586
|
-
expect(sql).toContain("to: string");
|
|
587
|
-
expect(sql).toContain("mandu_manual_migration_required");
|
|
588
|
-
}
|
|
589
|
-
});
|
|
590
|
-
|
|
591
|
-
test("includes a deliberate failing manual-migration sentinel", () => {
|
|
592
|
-
const sql = emitChange(change, "postgres");
|
|
593
|
-
expect(sql).toContain("SELECT mandu_manual_migration_required");
|
|
594
|
-
expect(sql).not.toContain("SELECT 1;");
|
|
595
|
-
});
|
|
596
|
-
});
|
|
579
|
+
test("emits comment block with required TODO text", () => {
|
|
580
|
+
for (const p of PROVIDERS) {
|
|
581
|
+
const sql = emitChange(change, p);
|
|
582
|
+
expect(sql).toContain("-- TODO: Mandu does not auto-generate ALTER COLUMN TYPE in v1.");
|
|
583
|
+
expect(sql).toContain("mandu db apply");
|
|
584
|
+
expect(sql).toContain("Column type change detected: users.age");
|
|
585
|
+
expect(sql).toContain("from: number");
|
|
586
|
+
expect(sql).toContain("to: string");
|
|
587
|
+
expect(sql).toContain("mandu_manual_migration_required");
|
|
588
|
+
}
|
|
589
|
+
});
|
|
590
|
+
|
|
591
|
+
test("includes a deliberate failing manual-migration sentinel", () => {
|
|
592
|
+
const sql = emitChange(change, "postgres");
|
|
593
|
+
expect(sql).toContain("SELECT mandu_manual_migration_required");
|
|
594
|
+
expect(sql).not.toContain("SELECT 1;");
|
|
595
|
+
});
|
|
596
|
+
});
|
|
597
597
|
|
|
598
598
|
describe("emitChange — alter-column-nullable", () => {
|
|
599
599
|
test("postgres SET NOT NULL / DROP NOT NULL", () => {
|
|
@@ -611,24 +611,24 @@ describe("emitChange — alter-column-nullable", () => {
|
|
|
611
611
|
).toBe('ALTER TABLE "users" ALTER COLUMN "email" DROP NOT NULL;');
|
|
612
612
|
});
|
|
613
613
|
|
|
614
|
-
test("sqlite emits a stub (cannot toggle NOT NULL in place)", () => {
|
|
615
|
-
const sql = emitChange(
|
|
616
|
-
{ kind: "alter-column-nullable", resourceName: "users", fieldName: "email", nullable: true },
|
|
617
|
-
"sqlite",
|
|
618
|
-
);
|
|
619
|
-
expect(sql).toContain("TODO: SQLite cannot toggle NOT NULL in place");
|
|
620
|
-
expect(sql).toContain("mandu_manual_migration_required");
|
|
621
|
-
});
|
|
622
|
-
|
|
623
|
-
test("mysql emits a stub (MODIFY COLUMN needs full type)", () => {
|
|
624
|
-
const sql = emitChange(
|
|
625
|
-
{ kind: "alter-column-nullable", resourceName: "users", fieldName: "email", nullable: false },
|
|
626
|
-
"mysql",
|
|
627
|
-
);
|
|
628
|
-
expect(sql).toContain("MySQL MODIFY COLUMN requires");
|
|
629
|
-
expect(sql).toContain("mandu_manual_migration_required");
|
|
630
|
-
});
|
|
631
|
-
});
|
|
614
|
+
test("sqlite emits a stub (cannot toggle NOT NULL in place)", () => {
|
|
615
|
+
const sql = emitChange(
|
|
616
|
+
{ kind: "alter-column-nullable", resourceName: "users", fieldName: "email", nullable: true },
|
|
617
|
+
"sqlite",
|
|
618
|
+
);
|
|
619
|
+
expect(sql).toContain("TODO: SQLite cannot toggle NOT NULL in place");
|
|
620
|
+
expect(sql).toContain("mandu_manual_migration_required");
|
|
621
|
+
});
|
|
622
|
+
|
|
623
|
+
test("mysql emits a stub (MODIFY COLUMN needs full type)", () => {
|
|
624
|
+
const sql = emitChange(
|
|
625
|
+
{ kind: "alter-column-nullable", resourceName: "users", fieldName: "email", nullable: false },
|
|
626
|
+
"mysql",
|
|
627
|
+
);
|
|
628
|
+
expect(sql).toContain("MySQL MODIFY COLUMN requires");
|
|
629
|
+
expect(sql).toContain("mandu_manual_migration_required");
|
|
630
|
+
});
|
|
631
|
+
});
|
|
632
632
|
|
|
633
633
|
describe("emitChange — alter-column-default", () => {
|
|
634
634
|
test("postgres SET DEFAULT", () => {
|
|
@@ -652,35 +652,35 @@ describe("emitChange — alter-column-default", () => {
|
|
|
652
652
|
expect(sql).toBe('ALTER TABLE "users" ALTER COLUMN "status" DROP DEFAULT;');
|
|
653
653
|
});
|
|
654
654
|
|
|
655
|
-
test("mysql supports SET/DROP DEFAULT directly", () => {
|
|
656
|
-
expect(
|
|
657
|
-
emitChange(
|
|
658
|
-
{
|
|
655
|
+
test("mysql supports SET/DROP DEFAULT directly", () => {
|
|
656
|
+
expect(
|
|
657
|
+
emitChange(
|
|
658
|
+
{
|
|
659
659
|
kind: "alter-column-default",
|
|
660
660
|
resourceName: "u",
|
|
661
661
|
fieldName: "f",
|
|
662
662
|
default: { kind: "literal", value: 1 },
|
|
663
663
|
},
|
|
664
664
|
"mysql",
|
|
665
|
-
),
|
|
666
|
-
).toBe("ALTER TABLE `u` ALTER COLUMN `f` SET DEFAULT 1;");
|
|
667
|
-
});
|
|
668
|
-
|
|
669
|
-
test("sqlite emits a failing manual stub for default changes", () => {
|
|
670
|
-
const sql = emitChange(
|
|
671
|
-
{
|
|
672
|
-
kind: "alter-column-default",
|
|
673
|
-
resourceName: "users",
|
|
674
|
-
fieldName: "status",
|
|
675
|
-
default: { kind: "literal", value: "active" },
|
|
676
|
-
},
|
|
677
|
-
"sqlite",
|
|
678
|
-
);
|
|
679
|
-
expect(sql).toContain("TODO: SQLite cannot ALTER DEFAULT in place");
|
|
680
|
-
expect(sql).toContain("mandu_manual_migration_required");
|
|
681
|
-
expect(sql).not.toContain("SELECT 1;");
|
|
682
|
-
});
|
|
683
|
-
});
|
|
665
|
+
),
|
|
666
|
+
).toBe("ALTER TABLE `u` ALTER COLUMN `f` SET DEFAULT 1;");
|
|
667
|
+
});
|
|
668
|
+
|
|
669
|
+
test("sqlite emits a failing manual stub for default changes", () => {
|
|
670
|
+
const sql = emitChange(
|
|
671
|
+
{
|
|
672
|
+
kind: "alter-column-default",
|
|
673
|
+
resourceName: "users",
|
|
674
|
+
fieldName: "status",
|
|
675
|
+
default: { kind: "literal", value: "active" },
|
|
676
|
+
},
|
|
677
|
+
"sqlite",
|
|
678
|
+
);
|
|
679
|
+
expect(sql).toContain("TODO: SQLite cannot ALTER DEFAULT in place");
|
|
680
|
+
expect(sql).toContain("mandu_manual_migration_required");
|
|
681
|
+
expect(sql).not.toContain("SELECT 1;");
|
|
682
|
+
});
|
|
683
|
+
});
|
|
684
684
|
|
|
685
685
|
describe("emitChange — indexes", () => {
|
|
686
686
|
test("add-index single column, non-unique", () => {
|