@navita/vite-plugin 1.0.0 → 2.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.
package/index.cjs CHANGED
@@ -4,94 +4,72 @@ var fs = require('node:fs');
4
4
  var createRenderer = require('@navita/core/createRenderer');
5
5
  var css = require('@navita/css');
6
6
 
7
- function _interopNamespaceDefault(e) {
8
- var n = Object.create(null);
9
- if (e) {
10
- Object.keys(e).forEach(function (k) {
11
- if (k !== 'default') {
12
- var d = Object.getOwnPropertyDescriptor(e, k);
13
- Object.defineProperty(n, k, d.get ? d : {
14
- enumerable: true,
15
- get: function () { return e[k]; }
16
- });
17
- }
18
- });
19
- }
20
- n.default = e;
21
- return Object.freeze(n);
22
- }
23
-
24
- var fs__namespace = /*#__PURE__*/_interopNamespaceDefault(fs);
25
-
26
- let renderer;
27
- /*
28
- Some information for anyone wondering why we have duplicate css for the initial load
29
- during development in remix.
30
- https://github.com/remix-run/remix/discussions/8070#discussioncomment-7625870
31
- */ const VIRTUAL_CSS_NAME = '\0virtual:navita.css';
7
+ const VIRTUAL_MODULE_ID = 'virtual:navita.css';
8
+ const RESOLVED_VIRTUAL_MODULE_ID = '\0' + VIRTUAL_MODULE_ID.replace(/.css$/, '');
32
9
  function navita(options) {
33
10
  const importMap = [
34
11
  ...css.importMap,
35
12
  ...options?.importMap || []
36
13
  ];
37
14
  let server;
38
- let lastCssContent;
39
- let context;
40
- let isSSR = false;
15
+ let config;
16
+ let updateTimer = null;
17
+ let cssEmitted = false;
18
+ let isProduction = false;
41
19
  return {
42
- name: "navita",
43
- enforce: "pre",
44
- config () {
45
- return {
46
- ssr: {
47
- external: [
48
- '@navita/css',
49
- '@navita/adapter'
50
- ]
51
- }
52
- };
53
- },
54
- configResolved (config) {
55
- context = config.root;
56
- isSSR = !!config.build.ssr;
20
+ enforce: 'pre',
21
+ name: 'navita',
22
+ configResolved (_resolvedConfig) {
23
+ config = _resolvedConfig;
24
+ isProduction = config.mode === 'production';
57
25
  },
58
26
  configureServer (_server) {
59
- lastCssContent = undefined;
60
27
  server = _server;
61
28
  },
62
- async buildStart () {
63
- const defaultEngineOptions = {
64
- enableSourceMaps: !!server,
65
- enableDebugIdentifiers: !!server,
66
- ...options?.engineOptions || {}
67
- };
68
- renderer = createRenderer.createRenderer({
69
- context,
29
+ buildStart () {
30
+ if (getRenderer()) {
31
+ return;
32
+ }
33
+ setRenderer(createRenderer.createRenderer({
34
+ context: config.root,
35
+ engineOptions: {
36
+ enableSourceMaps: !isProduction,
37
+ enableDebugIdentifiers: !isProduction,
38
+ ...options?.engineOptions || {}
39
+ },
70
40
  importMap,
71
- engineOptions: defaultEngineOptions,
72
41
  resolver: async (filepath, request)=>{
73
42
  const resolved = await this.resolve(request, filepath);
74
43
  return resolved?.id || null;
75
44
  },
76
45
  readFile: (path)=>{
77
- return fs__namespace.promises.readFile(path, 'utf-8');
46
+ return fs.promises.readFile(path, 'utf-8');
78
47
  }
79
- });
48
+ }));
80
49
  },
81
- async resolveId (id) {
82
- if (id === VIRTUAL_CSS_NAME) {
83
- return VIRTUAL_CSS_NAME;
50
+ resolveId (source) {
51
+ const [id] = source.split('?');
52
+ if (id.endsWith(VIRTUAL_MODULE_ID)) {
53
+ return RESOLVED_VIRTUAL_MODULE_ID;
84
54
  }
85
- return;
86
55
  },
87
- async load (id) {
88
- if (id === VIRTUAL_CSS_NAME) {
89
- return lastCssContent;
56
+ async load (source) {
57
+ const [id] = source.split('?');
58
+ if (id === RESOLVED_VIRTUAL_MODULE_ID) {
59
+ const css = getRenderer()?.engine.renderCssToString() || '';
60
+ return {
61
+ code: css,
62
+ map: {
63
+ mappings: ''
64
+ }
65
+ };
90
66
  }
91
- return;
92
67
  },
93
68
  async transform (code, id) {
94
- // Bail as early as we can
69
+ const renderer = getRenderer();
70
+ if (!renderer || id.includes('node_modules')) {
71
+ return null;
72
+ }
95
73
  if (!importMap.map((x)=>x.source).some((value)=>code.indexOf(value) !== -1)) {
96
74
  renderer.clearCache(id);
97
75
  return null;
@@ -100,53 +78,81 @@ function navita(options) {
100
78
  content: code,
101
79
  filePath: id
102
80
  });
103
- const newCssContent = renderer.engine.renderCssToString();
104
- if (lastCssContent !== newCssContent) {
105
- invalidateModule(VIRTUAL_CSS_NAME);
106
- this.addWatchFile(VIRTUAL_CSS_NAME);
107
- lastCssContent = newCssContent;
108
- for (const file of dependencies){
109
- if (!file.includes('node_modules')) {
110
- this.addWatchFile(file);
111
- }
112
- invalidateModule(file);
81
+ if (!isProduction) {
82
+ for (const dependency of dependencies){
83
+ this.addWatchFile(dependency);
113
84
  }
85
+ updateNavitaCSS();
114
86
  }
115
87
  return {
116
- code: `${result} import "${VIRTUAL_CSS_NAME}";`,
88
+ code: result,
117
89
  map: sourceMap
118
90
  };
119
91
  },
120
- renderChunk (_, chunk, third) {
121
- if (isSSR) {
122
- return;
123
- }
124
- for (const id of Object.keys(chunk.modules)){
125
- if (id.startsWith(VIRTUAL_CSS_NAME)) {
126
- delete chunk.modules[id];
92
+ transformIndexHtml: {
93
+ handler: async ()=>{
94
+ // If we're building, we don't want to inject the CSS into the HTML.
95
+ // We'll do this in the `renderChunk` hook instead.
96
+ if (isProduction) {
97
+ return [];
127
98
  }
99
+ return [
100
+ {
101
+ tag: 'link',
102
+ injectTo: 'head',
103
+ attrs: {
104
+ rel: 'stylesheet',
105
+ href: `/${VIRTUAL_MODULE_ID}`
106
+ }
107
+ }
108
+ ];
109
+ }
110
+ },
111
+ renderChunk (_, chunk) {
112
+ if (cssEmitted) {
113
+ return;
128
114
  }
129
115
  chunk.viteMetadata.importedCss.add(this.getFileName(this.emitFile({
130
- name: "navita.css",
131
- type: "asset",
132
- source: renderer.engine.renderCssToString()
116
+ name: 'navita.css',
117
+ type: 'asset',
118
+ source: getRenderer()?.engine.renderCssToString()
133
119
  })));
120
+ cssEmitted = true;
134
121
  }
135
122
  };
136
- function invalidateModule(absoluteId) {
123
+ function updateNavitaCSS() {
137
124
  if (!server) {
138
125
  return;
139
126
  }
140
- const { moduleGraph } = server;
141
- const modules = moduleGraph.getModulesByFile(absoluteId);
142
- if (modules) {
143
- for (const module of modules){
144
- moduleGraph.invalidateModule(module);
145
- // Vite uses this timestamp to add `?t=` query string automatically for HMR.
146
- module.lastHMRTimestamp = module.lastInvalidationTimestamp || Date.now();
127
+ clearTimeout(updateTimer);
128
+ updateTimer = setTimeout(()=>{
129
+ const { moduleGraph , ws } = server;
130
+ const mod = moduleGraph.getModuleById(RESOLVED_VIRTUAL_MODULE_ID);
131
+ if (mod) {
132
+ moduleGraph.invalidateModule(mod);
133
+ ws.send({
134
+ type: 'update',
135
+ updates: [
136
+ {
137
+ type: 'css-update',
138
+ path: `/${VIRTUAL_MODULE_ID}`,
139
+ acceptedPath: `/${VIRTUAL_MODULE_ID}`,
140
+ timestamp: Date.now()
141
+ }
142
+ ]
143
+ });
147
144
  }
148
- }
145
+ }, 20);
149
146
  }
150
147
  }
148
+ const globalNavitaRendererKey = '__navita_renderer';
149
+ function setRenderer(renderer) {
150
+ globalThis[globalNavitaRendererKey] = renderer;
151
+ }
152
+ function getRenderer() {
153
+ return globalThis[globalNavitaRendererKey];
154
+ }
151
155
 
156
+ exports.VIRTUAL_MODULE_ID = VIRTUAL_MODULE_ID;
157
+ exports.getRenderer = getRenderer;
152
158
  exports.navita = navita;
package/index.d.ts CHANGED
@@ -1,10 +1,12 @@
1
- import { ImportMap, EngineOptions } from '@navita/core/createRenderer';
1
+ import { ImportMap, EngineOptions, Renderer } from '@navita/core/createRenderer';
2
2
  import { Plugin } from 'vite';
3
3
 
4
+ declare const VIRTUAL_MODULE_ID = "virtual:navita.css";
4
5
  interface Options {
5
6
  importMap?: ImportMap;
6
7
  engineOptions?: EngineOptions;
7
8
  }
8
9
  declare function navita(options?: Options): Plugin;
10
+ declare function getRenderer(): Renderer | undefined;
9
11
 
10
- export { navita };
12
+ export { Options, VIRTUAL_MODULE_ID, getRenderer, navita };
package/index.mjs CHANGED
@@ -1,53 +1,41 @@
1
- import * as fs from 'node:fs';
1
+ import fs from 'node:fs';
2
2
  import { createRenderer } from '@navita/core/createRenderer';
3
3
  import { importMap } from '@navita/css';
4
4
 
5
- let renderer;
6
- /*
7
- Some information for anyone wondering why we have duplicate css for the initial load
8
- during development in remix.
9
- https://github.com/remix-run/remix/discussions/8070#discussioncomment-7625870
10
- */ const VIRTUAL_CSS_NAME = '\0virtual:navita.css';
5
+ const VIRTUAL_MODULE_ID = 'virtual:navita.css';
6
+ const RESOLVED_VIRTUAL_MODULE_ID = '\0' + VIRTUAL_MODULE_ID.replace(/.css$/, '');
11
7
  function navita(options) {
12
8
  const importMap$1 = [
13
9
  ...importMap,
14
10
  ...options?.importMap || []
15
11
  ];
16
12
  let server;
17
- let lastCssContent;
18
- let context;
19
- let isSSR = false;
13
+ let config;
14
+ let updateTimer = null;
15
+ let cssEmitted = false;
16
+ let isProduction = false;
20
17
  return {
21
- name: "navita",
22
- enforce: "pre",
23
- config () {
24
- return {
25
- ssr: {
26
- external: [
27
- '@navita/css',
28
- '@navita/adapter'
29
- ]
30
- }
31
- };
32
- },
33
- configResolved (config) {
34
- context = config.root;
35
- isSSR = !!config.build.ssr;
18
+ enforce: 'pre',
19
+ name: 'navita',
20
+ configResolved (_resolvedConfig) {
21
+ config = _resolvedConfig;
22
+ isProduction = config.mode === 'production';
36
23
  },
37
24
  configureServer (_server) {
38
- lastCssContent = undefined;
39
25
  server = _server;
40
26
  },
41
- async buildStart () {
42
- const defaultEngineOptions = {
43
- enableSourceMaps: !!server,
44
- enableDebugIdentifiers: !!server,
45
- ...options?.engineOptions || {}
46
- };
47
- renderer = createRenderer({
48
- context,
27
+ buildStart () {
28
+ if (getRenderer()) {
29
+ return;
30
+ }
31
+ setRenderer(createRenderer({
32
+ context: config.root,
33
+ engineOptions: {
34
+ enableSourceMaps: !isProduction,
35
+ enableDebugIdentifiers: !isProduction,
36
+ ...options?.engineOptions || {}
37
+ },
49
38
  importMap: importMap$1,
50
- engineOptions: defaultEngineOptions,
51
39
  resolver: async (filepath, request)=>{
52
40
  const resolved = await this.resolve(request, filepath);
53
41
  return resolved?.id || null;
@@ -55,22 +43,31 @@ function navita(options) {
55
43
  readFile: (path)=>{
56
44
  return fs.promises.readFile(path, 'utf-8');
57
45
  }
58
- });
46
+ }));
59
47
  },
60
- async resolveId (id) {
61
- if (id === VIRTUAL_CSS_NAME) {
62
- return VIRTUAL_CSS_NAME;
48
+ resolveId (source) {
49
+ const [id] = source.split('?');
50
+ if (id.endsWith(VIRTUAL_MODULE_ID)) {
51
+ return RESOLVED_VIRTUAL_MODULE_ID;
63
52
  }
64
- return;
65
53
  },
66
- async load (id) {
67
- if (id === VIRTUAL_CSS_NAME) {
68
- return lastCssContent;
54
+ async load (source) {
55
+ const [id] = source.split('?');
56
+ if (id === RESOLVED_VIRTUAL_MODULE_ID) {
57
+ const css = getRenderer()?.engine.renderCssToString() || '';
58
+ return {
59
+ code: css,
60
+ map: {
61
+ mappings: ''
62
+ }
63
+ };
69
64
  }
70
- return;
71
65
  },
72
66
  async transform (code, id) {
73
- // Bail as early as we can
67
+ const renderer = getRenderer();
68
+ if (!renderer || id.includes('node_modules')) {
69
+ return null;
70
+ }
74
71
  if (!importMap$1.map((x)=>x.source).some((value)=>code.indexOf(value) !== -1)) {
75
72
  renderer.clearCache(id);
76
73
  return null;
@@ -79,53 +76,79 @@ function navita(options) {
79
76
  content: code,
80
77
  filePath: id
81
78
  });
82
- const newCssContent = renderer.engine.renderCssToString();
83
- if (lastCssContent !== newCssContent) {
84
- invalidateModule(VIRTUAL_CSS_NAME);
85
- this.addWatchFile(VIRTUAL_CSS_NAME);
86
- lastCssContent = newCssContent;
87
- for (const file of dependencies){
88
- if (!file.includes('node_modules')) {
89
- this.addWatchFile(file);
90
- }
91
- invalidateModule(file);
79
+ if (!isProduction) {
80
+ for (const dependency of dependencies){
81
+ this.addWatchFile(dependency);
92
82
  }
83
+ updateNavitaCSS();
93
84
  }
94
85
  return {
95
- code: `${result} import "${VIRTUAL_CSS_NAME}";`,
86
+ code: result,
96
87
  map: sourceMap
97
88
  };
98
89
  },
99
- renderChunk (_, chunk, third) {
100
- if (isSSR) {
101
- return;
102
- }
103
- for (const id of Object.keys(chunk.modules)){
104
- if (id.startsWith(VIRTUAL_CSS_NAME)) {
105
- delete chunk.modules[id];
90
+ transformIndexHtml: {
91
+ handler: async ()=>{
92
+ // If we're building, we don't want to inject the CSS into the HTML.
93
+ // We'll do this in the `renderChunk` hook instead.
94
+ if (isProduction) {
95
+ return [];
106
96
  }
97
+ return [
98
+ {
99
+ tag: 'link',
100
+ injectTo: 'head',
101
+ attrs: {
102
+ rel: 'stylesheet',
103
+ href: `/${VIRTUAL_MODULE_ID}`
104
+ }
105
+ }
106
+ ];
107
+ }
108
+ },
109
+ renderChunk (_, chunk) {
110
+ if (cssEmitted) {
111
+ return;
107
112
  }
108
113
  chunk.viteMetadata.importedCss.add(this.getFileName(this.emitFile({
109
- name: "navita.css",
110
- type: "asset",
111
- source: renderer.engine.renderCssToString()
114
+ name: 'navita.css',
115
+ type: 'asset',
116
+ source: getRenderer()?.engine.renderCssToString()
112
117
  })));
118
+ cssEmitted = true;
113
119
  }
114
120
  };
115
- function invalidateModule(absoluteId) {
121
+ function updateNavitaCSS() {
116
122
  if (!server) {
117
123
  return;
118
124
  }
119
- const { moduleGraph } = server;
120
- const modules = moduleGraph.getModulesByFile(absoluteId);
121
- if (modules) {
122
- for (const module of modules){
123
- moduleGraph.invalidateModule(module);
124
- // Vite uses this timestamp to add `?t=` query string automatically for HMR.
125
- module.lastHMRTimestamp = module.lastInvalidationTimestamp || Date.now();
125
+ clearTimeout(updateTimer);
126
+ updateTimer = setTimeout(()=>{
127
+ const { moduleGraph , ws } = server;
128
+ const mod = moduleGraph.getModuleById(RESOLVED_VIRTUAL_MODULE_ID);
129
+ if (mod) {
130
+ moduleGraph.invalidateModule(mod);
131
+ ws.send({
132
+ type: 'update',
133
+ updates: [
134
+ {
135
+ type: 'css-update',
136
+ path: `/${VIRTUAL_MODULE_ID}`,
137
+ acceptedPath: `/${VIRTUAL_MODULE_ID}`,
138
+ timestamp: Date.now()
139
+ }
140
+ ]
141
+ });
126
142
  }
127
- }
143
+ }, 20);
128
144
  }
129
145
  }
146
+ const globalNavitaRendererKey = '__navita_renderer';
147
+ function setRenderer(renderer) {
148
+ globalThis[globalNavitaRendererKey] = renderer;
149
+ }
150
+ function getRenderer() {
151
+ return globalThis[globalNavitaRendererKey];
152
+ }
130
153
 
131
- export { navita };
154
+ export { VIRTUAL_MODULE_ID, getRenderer, navita };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@navita/vite-plugin",
3
- "version": "1.0.0",
3
+ "version": "2.0.0",
4
4
  "description": "Navita Vite Plugin",
5
5
  "keywords": [
6
6
  "vite",
@@ -14,11 +14,16 @@
14
14
  "import": "./index.mjs",
15
15
  "require": "./index.cjs",
16
16
  "types": "./index.d.ts"
17
+ },
18
+ "./remix": {
19
+ "import": "./remix.mjs",
20
+ "require": "./remix.cjs",
21
+ "types": "./remix.d.ts"
17
22
  }
18
23
  },
19
24
  "dependencies": {
20
- "@navita/css": "0.2.0",
21
- "@navita/core": "1.0.0"
25
+ "@navita/core": "1.0.0",
26
+ "@navita/css": "0.2.0"
22
27
  },
23
28
  "license": "MIT",
24
29
  "author": "Eagerpatch",
package/remix.cjs ADDED
@@ -0,0 +1,84 @@
1
+ 'use strict';
2
+
3
+ var crypto = require('node:crypto');
4
+ var index = require('./index.cjs');
5
+
6
+ function _interopNamespaceDefault(e) {
7
+ var n = Object.create(null);
8
+ if (e) {
9
+ Object.keys(e).forEach(function (k) {
10
+ if (k !== 'default') {
11
+ var d = Object.getOwnPropertyDescriptor(e, k);
12
+ Object.defineProperty(n, k, d.get ? d : {
13
+ enumerable: true,
14
+ get: function () { return e[k]; }
15
+ });
16
+ }
17
+ });
18
+ }
19
+ n.default = e;
20
+ return Object.freeze(n);
21
+ }
22
+
23
+ var crypto__namespace = /*#__PURE__*/_interopNamespaceDefault(crypto);
24
+
25
+ let cssFileName;
26
+ function navitaRemix(options) {
27
+ let server;
28
+ const { renderChunk , ...navitaVite } = index.navita(options);
29
+ return [
30
+ navitaVite,
31
+ {
32
+ name: 'navita-remix',
33
+ configureServer (_server) {
34
+ server = _server;
35
+ server.middlewares.use(async function middleware(_req, _res, next) {
36
+ try {
37
+ const build = await server.ssrLoadModule('virtual:remix/server-build');
38
+ const { module } = build.routes.root;
39
+ // We modify the root module, to automatically include the CSS
40
+ // when running the dev server.
41
+ build.routes.root.module = {
42
+ ...module,
43
+ links: ()=>[
44
+ ...module.links(),
45
+ {
46
+ rel: 'stylesheet',
47
+ href: `/${index.VIRTUAL_MODULE_ID}`
48
+ }
49
+ ]
50
+ };
51
+ } catch (e) {
52
+ console.error(e);
53
+ }
54
+ next();
55
+ });
56
+ },
57
+ renderChunk (_, chunk) {
58
+ if (chunk.name === "root") {
59
+ // Generate a random name for the CSS file.
60
+ // Vite uses a file hash as the name, but since the client build will finish before
61
+ // the server build, we need to generate a random name for the CSS file.
62
+ // Ideally we could use a hash, but since the server might contain more styles than the client, we need to do it like this.
63
+ const random = crypto__namespace.randomBytes(30).toString("base64").replace(/[^a-zA-Z0-9]/g, "").slice(0, 8);
64
+ cssFileName = `assets/navita-${random}.css`;
65
+ // Attach the file to the root chunk so that it's included in the client build.
66
+ chunk.viteMetadata?.importedCss.add(cssFileName);
67
+ return;
68
+ }
69
+ if (chunk.name === 'server-build') {
70
+ // In the server-build, we'll generate the CSS and emit it as an asset.
71
+ // Remix will then move it to the client assets.
72
+ this.emitFile({
73
+ fileName: cssFileName,
74
+ name: 'navita.css',
75
+ type: 'asset',
76
+ source: index.getRenderer()?.engine.renderCssToString()
77
+ });
78
+ }
79
+ }
80
+ }
81
+ ];
82
+ }
83
+
84
+ exports.navitaRemix = navitaRemix;
package/remix.d.ts ADDED
@@ -0,0 +1,7 @@
1
+ import { Plugin } from 'vite';
2
+ import { Options } from './index.js';
3
+ import '@navita/core/createRenderer';
4
+
5
+ declare function navitaRemix(options?: Options): Plugin[];
6
+
7
+ export { navitaRemix };
package/remix.mjs ADDED
@@ -0,0 +1,63 @@
1
+ import * as crypto from 'node:crypto';
2
+ import { navita, VIRTUAL_MODULE_ID, getRenderer } from './index.mjs';
3
+
4
+ let cssFileName;
5
+ function navitaRemix(options) {
6
+ let server;
7
+ const { renderChunk , ...navitaVite } = navita(options);
8
+ return [
9
+ navitaVite,
10
+ {
11
+ name: 'navita-remix',
12
+ configureServer (_server) {
13
+ server = _server;
14
+ server.middlewares.use(async function middleware(_req, _res, next) {
15
+ try {
16
+ const build = await server.ssrLoadModule('virtual:remix/server-build');
17
+ const { module } = build.routes.root;
18
+ // We modify the root module, to automatically include the CSS
19
+ // when running the dev server.
20
+ build.routes.root.module = {
21
+ ...module,
22
+ links: ()=>[
23
+ ...module.links(),
24
+ {
25
+ rel: 'stylesheet',
26
+ href: `/${VIRTUAL_MODULE_ID}`
27
+ }
28
+ ]
29
+ };
30
+ } catch (e) {
31
+ console.error(e);
32
+ }
33
+ next();
34
+ });
35
+ },
36
+ renderChunk (_, chunk) {
37
+ if (chunk.name === "root") {
38
+ // Generate a random name for the CSS file.
39
+ // Vite uses a file hash as the name, but since the client build will finish before
40
+ // the server build, we need to generate a random name for the CSS file.
41
+ // Ideally we could use a hash, but since the server might contain more styles than the client, we need to do it like this.
42
+ const random = crypto.randomBytes(30).toString("base64").replace(/[^a-zA-Z0-9]/g, "").slice(0, 8);
43
+ cssFileName = `assets/navita-${random}.css`;
44
+ // Attach the file to the root chunk so that it's included in the client build.
45
+ chunk.viteMetadata?.importedCss.add(cssFileName);
46
+ return;
47
+ }
48
+ if (chunk.name === 'server-build') {
49
+ // In the server-build, we'll generate the CSS and emit it as an asset.
50
+ // Remix will then move it to the client assets.
51
+ this.emitFile({
52
+ fileName: cssFileName,
53
+ name: 'navita.css',
54
+ type: 'asset',
55
+ source: getRenderer()?.engine.renderCssToString()
56
+ });
57
+ }
58
+ }
59
+ }
60
+ ];
61
+ }
62
+
63
+ export { navitaRemix };