@constela/start 0.4.1 → 1.0.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.
Files changed (3) hide show
  1. package/dist/index.d.ts +77 -9
  2. package/dist/index.js +365 -24
  3. package/package.json +12 -11
package/dist/index.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { CompiledProgram } from '@constela/compiler';
1
+ import { CompiledProgram, CompiledNode } from '@constela/compiler';
2
2
  import { LayoutProgram, Program, StaticPathsDefinition, DataSource } from '@constela/core';
3
3
 
4
4
  /**
@@ -357,6 +357,47 @@ declare class LayoutResolver {
357
357
  getAll(): ScannedLayout[];
358
358
  }
359
359
 
360
+ /**
361
+ * MDX to Constela AST Pipeline
362
+ *
363
+ * Transforms MDX content into CompiledProgram for Constela runtime.
364
+ * Uses unified/remark for parsing and gray-matter for frontmatter.
365
+ */
366
+
367
+ /**
368
+ * Component definition for custom MDX components
369
+ */
370
+ interface ComponentDef$1 {
371
+ params?: Record<string, {
372
+ type: string;
373
+ required?: boolean;
374
+ }>;
375
+ view: CompiledNode;
376
+ }
377
+ /**
378
+ * Options for MDX to Constela transformation
379
+ */
380
+ interface MDXToConstelaOptions {
381
+ components?: Record<string, ComponentDef$1>;
382
+ }
383
+ /**
384
+ * Transform MDX source to CompiledProgram
385
+ *
386
+ * @param source - MDX source string
387
+ * @param options - Transformation options
388
+ * @returns CompiledProgram
389
+ */
390
+ declare function mdxToConstela(source: string, options?: MDXToConstelaOptions): Promise<CompiledProgram>;
391
+ /**
392
+ * Transform MDX content (without frontmatter) to CompiledNode
393
+ * For use when frontmatter has already been extracted
394
+ *
395
+ * @param content - MDX content string (frontmatter already removed)
396
+ * @param options - Transformation options
397
+ * @returns CompiledNode
398
+ */
399
+ declare function mdxContentToNode$1(content: string, options?: MDXToConstelaOptions): Promise<CompiledNode>;
400
+
360
401
  /**
361
402
  * Data Loader for Build-time Content Loading
362
403
  *
@@ -374,17 +415,35 @@ interface GlobResult {
374
415
  frontmatter?: Record<string, unknown>;
375
416
  content?: string;
376
417
  }
418
+ interface MdxGlobResult {
419
+ file: string;
420
+ raw: string;
421
+ frontmatter: Record<string, unknown>;
422
+ content: CompiledNode;
423
+ slug: string;
424
+ }
425
+ interface ComponentDef {
426
+ params?: Record<string, {
427
+ type: string;
428
+ required?: boolean;
429
+ }>;
430
+ view: CompiledNode;
431
+ }
432
+ declare const mdxContentToNode: typeof mdxContentToNode$1;
377
433
  interface StaticPath {
378
434
  params: Record<string, string>;
379
435
  data?: unknown;
380
436
  }
381
437
  /**
382
- * Transform MDX content - parse frontmatter and content
438
+ * Load component definitions from a JSON file
383
439
  */
384
- declare function transformMdx(content: string): {
385
- frontmatter: Record<string, unknown>;
386
- content: string;
387
- };
440
+ declare function loadComponentDefinitions(baseDir: string, componentsPath: string): Record<string, ComponentDef>;
441
+ /**
442
+ * Transform MDX content - parse frontmatter and compile content to CompiledNode
443
+ */
444
+ declare function transformMdx(content: string, file: string, options?: {
445
+ components?: Record<string, ComponentDef>;
446
+ }): Promise<MdxGlobResult>;
388
447
  /**
389
448
  * Transform YAML content
390
449
  */
@@ -396,7 +455,9 @@ declare function transformCsv(content: string): Record<string, string>[];
396
455
  /**
397
456
  * Load files matching a glob pattern
398
457
  */
399
- declare function loadGlob(baseDir: string, pattern: string, transform?: string): Promise<GlobResult[]>;
458
+ declare function loadGlob(baseDir: string, pattern: string, transform?: string, options?: {
459
+ components?: Record<string, ComponentDef>;
460
+ }): Promise<GlobResult[] | MdxGlobResult[]>;
400
461
  /**
401
462
  * Load a single file
402
463
  */
@@ -414,12 +475,19 @@ declare function generateStaticPaths(data: unknown[], staticPathsDef: StaticPath
414
475
  */
415
476
  declare class DataLoader {
416
477
  private cache;
478
+ private componentCache;
417
479
  private projectRoot;
418
480
  constructor(projectRoot: string);
481
+ /**
482
+ * Resolve components from string path or import reference
483
+ */
484
+ private resolveComponents;
419
485
  /**
420
486
  * Load a single data source
421
487
  */
422
- loadDataSource(name: string, dataSource: DataSource): Promise<unknown>;
488
+ loadDataSource(name: string, dataSource: DataSource, context?: {
489
+ imports?: Record<string, unknown>;
490
+ }): Promise<unknown>;
423
491
  /**
424
492
  * Load all data sources
425
493
  */
@@ -438,4 +506,4 @@ declare class DataLoader {
438
506
  getCacheSize(): number;
439
507
  }
440
508
 
441
- export { type APIContext, type APIModule, type BuildOptions, type ConstelaConfig, DataLoader, type DevServerOptions, type GenerateStaticPagesOptions, type GlobResult, type LayoutInfo, LayoutResolver, type Middleware, type MiddlewareContext, type MiddlewareNext, type PageExportFunction, type PageModule, type ScannedLayout, type ScannedRoute, type StaticFileResult, type StaticPath, type StaticPathsProvider, type StaticPathsResult, build, createAPIHandler, createAdapter, createDevServer, createMiddlewareChain, filePathToPattern, generateStaticPages, generateStaticPaths, getMimeType, isPageExportFunction, isPathSafe, loadApi, loadFile, loadGlob, loadLayout, resolveLayout, resolvePageExport, resolveStaticFile, scanLayouts, scanRoutes, transformCsv, transformMdx, transformYaml };
509
+ export { type APIContext, type APIModule, type BuildOptions, type ComponentDef$1 as ComponentDef, type ConstelaConfig, DataLoader, type DevServerOptions, type GenerateStaticPagesOptions, type GlobResult, type LayoutInfo, LayoutResolver, type MDXToConstelaOptions, type MdxGlobResult, type Middleware, type MiddlewareContext, type MiddlewareNext, type PageExportFunction, type PageModule, type ScannedLayout, type ScannedRoute, type StaticFileResult, type StaticPath, type StaticPathsProvider, type StaticPathsResult, build, createAPIHandler, createAdapter, createDevServer, createMiddlewareChain, filePathToPattern, generateStaticPages, generateStaticPaths, getMimeType, isPageExportFunction, isPathSafe, loadApi, loadComponentDefinitions, loadFile, loadGlob, loadLayout, mdxContentToNode, mdxToConstela, resolveLayout, resolvePageExport, resolveStaticFile, scanLayouts, scanRoutes, transformCsv, transformMdx, transformYaml };
package/dist/index.js CHANGED
@@ -415,8 +415,276 @@ var LayoutResolver = class {
415
415
 
416
416
  // src/data/loader.ts
417
417
  import { existsSync as existsSync2, readFileSync } from "fs";
418
- import { join as join3 } from "path";
418
+ import { basename as basename2, extname, join as join3 } from "path";
419
419
  import fg2 from "fast-glob";
420
+
421
+ // src/build/mdx.ts
422
+ import { unified } from "unified";
423
+ import remarkParse from "remark-parse";
424
+ import remarkMdx from "remark-mdx";
425
+ import remarkGfm from "remark-gfm";
426
+ import matter from "gray-matter";
427
+ function lit(value) {
428
+ return { expr: "lit", value };
429
+ }
430
+ function textNode(value) {
431
+ return { kind: "text", value: lit(value) };
432
+ }
433
+ function elementNode(tag, props, children) {
434
+ const node = { kind: "element", tag };
435
+ if (props && Object.keys(props).length > 0) {
436
+ node.props = props;
437
+ }
438
+ if (children && children.length > 0) {
439
+ node.children = children;
440
+ }
441
+ return node;
442
+ }
443
+ function codeNode(language, content) {
444
+ return {
445
+ kind: "code",
446
+ language: lit(language),
447
+ content: lit(content)
448
+ };
449
+ }
450
+ function wrapNodes(nodes) {
451
+ if (nodes.length === 0) {
452
+ return elementNode("div");
453
+ }
454
+ if (nodes.length === 1 && nodes[0]) {
455
+ return nodes[0];
456
+ }
457
+ return elementNode("div", void 0, nodes);
458
+ }
459
+ function isCustomComponent(name) {
460
+ if (!name) return false;
461
+ return /^[A-Z]/.test(name);
462
+ }
463
+ function parseAttributeValue(attr) {
464
+ if (attr.value === null) {
465
+ return lit(true);
466
+ }
467
+ if (typeof attr.value === "string") {
468
+ return lit(attr.value);
469
+ }
470
+ if (attr.value.type === "mdxJsxAttributeValueExpression") {
471
+ const exprValue = attr.value.value.trim();
472
+ if (exprValue === "true") return lit(true);
473
+ if (exprValue === "false") return lit(false);
474
+ if (exprValue === "null") return lit(null);
475
+ const num = Number(exprValue);
476
+ if (!Number.isNaN(num)) return lit(num);
477
+ return lit(exprValue);
478
+ }
479
+ return lit(null);
480
+ }
481
+ function transformNode(node, ctx) {
482
+ switch (node.type) {
483
+ case "heading":
484
+ return elementNode(
485
+ `h${node.depth}`,
486
+ void 0,
487
+ transformChildren(node.children, ctx)
488
+ );
489
+ case "paragraph":
490
+ return elementNode("p", void 0, transformChildren(node.children, ctx));
491
+ case "text":
492
+ return textNode(node.value);
493
+ case "emphasis":
494
+ return elementNode("em", void 0, transformChildren(node.children, ctx));
495
+ case "strong":
496
+ return elementNode("strong", void 0, transformChildren(node.children, ctx));
497
+ case "link": {
498
+ const props = {
499
+ href: lit(node.url)
500
+ };
501
+ if (node["title"]) {
502
+ props["title"] = lit(node["title"]);
503
+ }
504
+ return elementNode("a", props, transformChildren(node.children, ctx));
505
+ }
506
+ case "inlineCode":
507
+ return elementNode("code", void 0, [textNode(node.value)]);
508
+ case "code": {
509
+ const lang = node.lang || "text";
510
+ return codeNode(lang, node.value);
511
+ }
512
+ case "blockquote":
513
+ return elementNode("blockquote", void 0, transformChildren(node.children, ctx));
514
+ case "list": {
515
+ const tag = node.ordered ? "ol" : "ul";
516
+ return elementNode(tag, void 0, transformChildren(node.children, ctx));
517
+ }
518
+ case "listItem": {
519
+ const children = [];
520
+ for (const child of node.children) {
521
+ if (child.type === "paragraph") {
522
+ children.push(...transformChildren(child.children, ctx));
523
+ } else {
524
+ const transformed = transformNode(child, ctx);
525
+ if (transformed) {
526
+ if (Array.isArray(transformed)) {
527
+ children.push(...transformed);
528
+ } else {
529
+ children.push(transformed);
530
+ }
531
+ }
532
+ }
533
+ }
534
+ return elementNode("li", void 0, children);
535
+ }
536
+ case "thematicBreak":
537
+ return elementNode("hr");
538
+ case "break":
539
+ return elementNode("br");
540
+ case "image": {
541
+ const props = {
542
+ src: lit(node.url)
543
+ };
544
+ if (node["alt"]) {
545
+ props["alt"] = lit(node["alt"]);
546
+ }
547
+ if (node["title"]) {
548
+ props["title"] = lit(node["title"]);
549
+ }
550
+ return elementNode("img", props);
551
+ }
552
+ case "html":
553
+ return textNode(node.value);
554
+ // MDX JSX elements
555
+ case "mdxJsxFlowElement":
556
+ case "mdxJsxTextElement":
557
+ return transformJsxElement(node, ctx);
558
+ // MDX expressions
559
+ case "mdxFlowExpression":
560
+ case "mdxTextExpression": {
561
+ const exprNode = node;
562
+ const value = exprNode.value.trim();
563
+ if (value === "") return null;
564
+ if (value === "true") return textNode("true");
565
+ if (value === "false") return textNode("false");
566
+ if (value === "null") return textNode("null");
567
+ const num = Number(value);
568
+ if (!Number.isNaN(num)) return textNode(String(num));
569
+ return textNode(value);
570
+ }
571
+ // GFM extensions
572
+ case "table":
573
+ return elementNode("table", void 0, transformChildren(node.children, ctx));
574
+ case "tableRow":
575
+ return elementNode("tr", void 0, transformChildren(node.children, ctx));
576
+ case "tableCell":
577
+ return elementNode("td", void 0, transformChildren(node.children, ctx));
578
+ case "delete":
579
+ return elementNode("del", void 0, transformChildren(node.children, ctx));
580
+ default:
581
+ return null;
582
+ }
583
+ }
584
+ function transformJsxElement(node, ctx) {
585
+ const name = node.name;
586
+ if (!name) {
587
+ const children2 = transformChildren(node.children, ctx);
588
+ return wrapNodes(children2);
589
+ }
590
+ if (isCustomComponent(name)) {
591
+ const def = ctx.components[name];
592
+ if (!def) {
593
+ throw new Error(`Undefined component: ${name}`);
594
+ }
595
+ const props2 = {};
596
+ for (const attr of node.attributes) {
597
+ if (attr.type === "mdxJsxAttribute") {
598
+ props2[attr.name] = parseAttributeValue(attr);
599
+ }
600
+ }
601
+ const children2 = transformChildren(node.children, ctx);
602
+ return applyComponentView(def.view, props2, children2);
603
+ }
604
+ const props = {};
605
+ for (const attr of node.attributes) {
606
+ if (attr.type === "mdxJsxAttribute") {
607
+ props[attr.name] = parseAttributeValue(attr);
608
+ }
609
+ }
610
+ const children = transformChildren(node.children, ctx);
611
+ return elementNode(name, props, children);
612
+ }
613
+ function applyComponentView(view, props, children) {
614
+ return substituteInNode(view, props, children);
615
+ }
616
+ function substituteInNode(node, props, children) {
617
+ if (node.kind === "element") {
618
+ const elem = node;
619
+ const newProps = elem.props ? { ...elem.props } : {};
620
+ for (const [key, value] of Object.entries(props)) {
621
+ if (!(key in newProps)) {
622
+ newProps[key] = value;
623
+ }
624
+ }
625
+ let newChildren;
626
+ if (elem.children) {
627
+ newChildren = [];
628
+ for (const child of elem.children) {
629
+ if (child.kind === "slot") {
630
+ newChildren.push(...children);
631
+ } else {
632
+ newChildren.push(substituteInNode(child, props, children));
633
+ }
634
+ }
635
+ }
636
+ return elementNode(
637
+ elem.tag,
638
+ Object.keys(newProps).length > 0 ? newProps : void 0,
639
+ newChildren && newChildren.length > 0 ? newChildren : void 0
640
+ );
641
+ }
642
+ return node;
643
+ }
644
+ function transformChildren(children, ctx) {
645
+ const result = [];
646
+ for (const child of children) {
647
+ const transformed = transformNode(child, ctx);
648
+ if (transformed) {
649
+ if (Array.isArray(transformed)) {
650
+ result.push(...transformed);
651
+ } else {
652
+ result.push(transformed);
653
+ }
654
+ }
655
+ }
656
+ return result;
657
+ }
658
+ function transformRoot(root, ctx) {
659
+ const nodes = transformChildren(root.children, ctx);
660
+ return wrapNodes(nodes);
661
+ }
662
+ async function mdxToConstela(source, options) {
663
+ const { content, data: _frontmatter } = matter(source);
664
+ const processor = unified().use(remarkParse).use(remarkGfm).use(remarkMdx);
665
+ const tree = processor.parse(content);
666
+ const ctx = {
667
+ components: options?.components ?? {}
668
+ };
669
+ const view = transformRoot(tree, ctx);
670
+ return {
671
+ version: "1.0",
672
+ state: {},
673
+ actions: {},
674
+ view
675
+ };
676
+ }
677
+ async function mdxContentToNode(content, options) {
678
+ const processor = unified().use(remarkParse).use(remarkGfm).use(remarkMdx);
679
+ const tree = processor.parse(content);
680
+ const ctx = {
681
+ components: options?.components ?? {}
682
+ };
683
+ return transformRoot(tree, ctx);
684
+ }
685
+
686
+ // src/data/loader.ts
687
+ var mdxContentToNode2 = mdxContentToNode;
420
688
  function parseYaml(content) {
421
689
  const result = {};
422
690
  const lines = content.split("\n");
@@ -494,13 +762,46 @@ function parseValue(value) {
494
762
  }
495
763
  return trimmed;
496
764
  }
497
- function transformMdx(content) {
765
+ function loadComponentDefinitions(baseDir, componentsPath) {
766
+ const fullPath = join3(baseDir, componentsPath);
767
+ const resolvedBase = join3(baseDir, "");
768
+ const resolvedPath = join3(fullPath, "");
769
+ if (!resolvedPath.startsWith(resolvedBase)) {
770
+ throw new Error(`Invalid component path: path traversal detected`);
771
+ }
772
+ if (!existsSync2(fullPath)) {
773
+ throw new Error(`MDX components file not found: ${fullPath}`);
774
+ }
775
+ const content = readFileSync(fullPath, "utf-8");
776
+ try {
777
+ return JSON.parse(content);
778
+ } catch {
779
+ throw new Error(`Invalid JSON in MDX components file: ${fullPath}`);
780
+ }
781
+ }
782
+ async function transformMdx(content, file, options) {
498
783
  const match = content.match(/^---\n([\s\S]*?)\n---\n([\s\S]*)$/);
499
- if (!match) {
500
- return { frontmatter: {}, content: content.trim() };
784
+ let frontmatter = {};
785
+ let mdxContent;
786
+ if (match) {
787
+ frontmatter = parseYaml(match[1]);
788
+ mdxContent = match[2].trim();
789
+ } else {
790
+ mdxContent = content.trim();
501
791
  }
502
- const frontmatter = parseYaml(match[1]);
503
- return { frontmatter, content: match[2].trim() };
792
+ const compiledContent = await mdxContentToNode(
793
+ mdxContent,
794
+ options?.components ? { components: options.components } : void 0
795
+ );
796
+ const fmSlug = frontmatter["slug"];
797
+ const slug = typeof fmSlug === "string" ? fmSlug : basename2(file, extname(file));
798
+ return {
799
+ file,
800
+ raw: content,
801
+ frontmatter,
802
+ content: compiledContent,
803
+ slug
804
+ };
504
805
  }
505
806
  function transformYaml(content) {
506
807
  return parseYaml(content);
@@ -550,7 +851,7 @@ function applyTransform(content, transform, filename) {
550
851
  }
551
852
  switch (transform) {
552
853
  case "mdx":
553
- return transformMdx(content);
854
+ throw new Error("MDX transform for single files is not supported via loadFile. Use loadGlob instead.");
554
855
  case "yaml":
555
856
  return transformYaml(content);
556
857
  case "csv":
@@ -559,26 +860,26 @@ function applyTransform(content, transform, filename) {
559
860
  return content;
560
861
  }
561
862
  }
562
- async function loadGlob(baseDir, pattern, transform) {
863
+ async function loadGlob(baseDir, pattern, transform, options) {
563
864
  const files = await fg2(pattern, { cwd: baseDir });
865
+ if (transform === "mdx") {
866
+ const results2 = [];
867
+ for (const file of files) {
868
+ const fullPath = join3(baseDir, file);
869
+ const content = readFileSync(fullPath, "utf-8");
870
+ const transformed = await transformMdx(content, file, options);
871
+ results2.push(transformed);
872
+ }
873
+ return results2;
874
+ }
564
875
  const results = [];
565
876
  for (const file of files) {
566
877
  const fullPath = join3(baseDir, file);
567
878
  const content = readFileSync(fullPath, "utf-8");
568
- if (transform === "mdx") {
569
- const transformed = transformMdx(content);
570
- results.push({
571
- file,
572
- raw: content,
573
- frontmatter: transformed.frontmatter,
574
- content: transformed.content
575
- });
576
- } else {
577
- results.push({
578
- file,
579
- raw: content
580
- });
581
- }
879
+ results.push({
880
+ file,
881
+ raw: content
882
+ });
582
883
  }
583
884
  return results;
584
885
  }
@@ -652,24 +953,61 @@ async function generateStaticPaths(data, staticPathsDef) {
652
953
  }
653
954
  var DataLoader = class {
654
955
  cache = /* @__PURE__ */ new Map();
956
+ componentCache = /* @__PURE__ */ new Map();
655
957
  projectRoot;
656
958
  constructor(projectRoot) {
657
959
  this.projectRoot = projectRoot;
658
960
  }
961
+ /**
962
+ * Resolve components from string path or import reference
963
+ */
964
+ resolveComponents(ref, imports) {
965
+ if (typeof ref === "string") {
966
+ if (this.componentCache.has(ref)) {
967
+ return this.componentCache.get(ref);
968
+ }
969
+ const defs = loadComponentDefinitions(this.projectRoot, ref);
970
+ this.componentCache.set(ref, defs);
971
+ return defs;
972
+ }
973
+ if (ref.expr === "import") {
974
+ if (!imports) {
975
+ throw new Error(`Import context required for component reference "${ref.name}"`);
976
+ }
977
+ const imported = imports[ref.name];
978
+ if (!imported || typeof imported !== "object") {
979
+ throw new Error(`Component import "${ref.name}" not found or invalid`);
980
+ }
981
+ return imported;
982
+ }
983
+ return {};
984
+ }
659
985
  /**
660
986
  * Load a single data source
661
987
  */
662
- async loadDataSource(name, dataSource) {
988
+ async loadDataSource(name, dataSource, context) {
663
989
  if (this.cache.has(name)) {
664
990
  return this.cache.get(name);
665
991
  }
992
+ let componentDefs;
993
+ if (dataSource.transform === "mdx" && dataSource.components) {
994
+ componentDefs = this.resolveComponents(
995
+ dataSource.components,
996
+ context?.imports
997
+ );
998
+ }
666
999
  let data;
667
1000
  switch (dataSource.type) {
668
1001
  case "glob":
669
1002
  if (!dataSource.pattern) {
670
1003
  throw new Error(`Glob data source '${name}' requires pattern`);
671
1004
  }
672
- data = await loadGlob(this.projectRoot, dataSource.pattern, dataSource.transform);
1005
+ data = await loadGlob(
1006
+ this.projectRoot,
1007
+ dataSource.pattern,
1008
+ dataSource.transform,
1009
+ componentDefs ? { components: componentDefs } : void 0
1010
+ );
673
1011
  break;
674
1012
  case "file":
675
1013
  if (!dataSource.path) {
@@ -737,9 +1075,12 @@ export {
737
1075
  isPageExportFunction,
738
1076
  isPathSafe,
739
1077
  loadApi,
1078
+ loadComponentDefinitions,
740
1079
  loadFile,
741
1080
  loadGlob,
742
1081
  loadLayout,
1082
+ mdxContentToNode2 as mdxContentToNode,
1083
+ mdxToConstela,
743
1084
  resolveLayout,
744
1085
  resolvePageExport,
745
1086
  resolveStaticFile,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@constela/start",
3
- "version": "0.4.1",
3
+ "version": "1.0.0",
4
4
  "description": "Meta-framework for Constela applications",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -30,24 +30,25 @@
30
30
  "node": ">=20.0.0"
31
31
  },
32
32
  "dependencies": {
33
- "hono": "^4.0.0",
34
- "vite": "^6.0.0",
35
33
  "commander": "^12.0.0",
36
34
  "fast-glob": "^3.3.0",
37
- "unified": "^11.0.0",
38
- "remark-parse": "^11.0.0",
39
- "remark-mdx": "^3.0.0",
40
- "remark-gfm": "^4.0.0",
41
35
  "gray-matter": "^4.0.0",
42
- "@constela/core": "0.6.0",
36
+ "hono": "^4.0.0",
37
+ "remark-gfm": "^4.0.0",
38
+ "remark-mdx": "^3.0.0",
39
+ "remark-parse": "^11.0.0",
40
+ "unified": "^11.0.0",
41
+ "vite": "^6.0.0",
42
+ "@constela/compiler": "0.6.1",
43
+ "@constela/core": "0.7.0",
43
44
  "@constela/router": "6.0.0",
44
45
  "@constela/server": "2.0.0",
45
- "@constela/runtime": "0.9.0",
46
- "@constela/compiler": "0.6.0"
46
+ "@constela/runtime": "0.9.1"
47
47
  },
48
48
  "devDependencies": {
49
- "typescript": "^5.3.0",
49
+ "@types/mdast": "^4.0.4",
50
50
  "tsup": "^8.0.0",
51
+ "typescript": "^5.3.0",
51
52
  "vitest": "^2.0.0"
52
53
  },
53
54
  "license": "MIT",