@jay-framework/wix-deploy 0.19.6 → 0.20.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.
@@ -8,15 +8,16 @@ function makeItemId(version, relativePath) {
8
8
  class WixDataArtifactStore {
9
9
  collectionId;
10
10
  version;
11
+ distDir;
11
12
  cacheDir;
12
13
  dataClient;
13
14
  moduleRegistry;
14
15
  manifestCache;
15
- moduleCache = /* @__PURE__ */ new Map();
16
16
  fetchPromises = /* @__PURE__ */ new Map();
17
17
  constructor(options) {
18
18
  this.collectionId = options.collectionId;
19
19
  this.version = options.version;
20
+ this.distDir = options.distDir;
20
21
  this.cacheDir = options.cacheDir;
21
22
  this.dataClient = options.wixClient.use({ items });
22
23
  this.moduleRegistry = options.moduleRegistry || {};
@@ -54,16 +55,9 @@ class WixDataArtifactStore {
54
55
  if (this.moduleRegistry[modulePath]) {
55
56
  return this.moduleRegistry[modulePath];
56
57
  }
57
- const cached = this.moduleCache.get(modulePath);
58
- if (cached) return cached;
59
- await this.ensureFile(modulePath);
60
- const fullPath = path.join(this.cacheDir, modulePath);
61
- const mod = await import(
62
- /* @vite-ignore */
63
- fullPath
58
+ throw new Error(
59
+ `Module not found in registry: ${modulePath}. All JS modules must be bundled in entry.mjs.`
64
60
  );
65
- this.moduleCache.set(modulePath, mod);
66
- return mod;
67
61
  }
68
62
  getAssetPath(relativePath) {
69
63
  return path.join(this.cacheDir, relativePath);
@@ -72,33 +66,8 @@ class WixDataArtifactStore {
72
66
  return this.cacheDir;
73
67
  }
74
68
  // ========================================================================
75
- // Eager loading (cold start)
76
- // ========================================================================
77
- async loadEagerFiles() {
78
- console.log(
79
- `[WixDataArtifactStore] Loading eager files v${this.version} from "${this.collectionId}"...`
80
- );
81
- let totalLoaded = 0;
82
- let hasMore = true;
83
- let offset = 0;
84
- const limit = 50;
85
- while (hasMore) {
86
- const result = await this.dataClient.items.query(this.collectionId).eq("category", "eager").eq("version", this.version).skip(offset).limit(limit).find();
87
- for (const item of result.items) {
88
- this.writeToCache(item.path, item.content);
89
- totalLoaded++;
90
- }
91
- hasMore = result.items.length === limit;
92
- offset += limit;
93
- }
94
- console.log(`[WixDataArtifactStore] Loaded ${totalLoaded} eager files`);
95
- }
96
- // ========================================================================
97
69
  // Writes (for upload-backend and renderer)
98
70
  // ========================================================================
99
- /**
100
- * Write a single file to the data collection.
101
- */
102
71
  async writeFile(relativePath, content, category) {
103
72
  const ext = path.extname(relativePath).slice(1);
104
73
  const item = {
@@ -112,10 +81,6 @@ class WixDataArtifactStore {
112
81
  };
113
82
  await this.dataClient.items.save(this.collectionId, item);
114
83
  }
115
- /**
116
- * Write a batch of files to the data collection.
117
- * Returns the number of successfully written files.
118
- */
119
84
  async writeFiles(files) {
120
85
  const dataItems = files.map((f) => ({
121
86
  _id: makeItemId(this.version, f.path),
@@ -142,12 +107,18 @@ class WixDataArtifactStore {
142
107
  }
143
108
  }
144
109
  // ========================================================================
145
- // Internal: lazy file fetching
110
+ // Internal: file resolution
146
111
  // ========================================================================
147
112
  async ensureFile(relativePath) {
148
- const fullPath = path.join(this.cacheDir, relativePath);
149
- if (fs.existsSync(fullPath)) {
150
- return fs.readFileSync(fullPath, "utf8");
113
+ if (this.distDir) {
114
+ const distPath = path.join(this.distDir, relativePath);
115
+ if (fs.existsSync(distPath)) {
116
+ return fs.readFileSync(distPath, "utf8");
117
+ }
118
+ }
119
+ const cachePath = path.join(this.cacheDir, relativePath);
120
+ if (fs.existsSync(cachePath)) {
121
+ return fs.readFileSync(cachePath, "utf8");
151
122
  }
152
123
  const existing = this.fetchPromises.get(relativePath);
153
124
  if (existing) return existing;
package/dist/index.d.ts CHANGED
@@ -7,13 +7,17 @@ import { WixClientService } from '@jay-framework/wix-server-client';
7
7
  /**
8
8
  * WixDataArtifactStore — implements ArtifactStore for Wix BaaS deployments.
9
9
  *
10
- * Manages both reads (for serving) and writes (for upload/renderer) of
11
- * backend build artifacts in a Wix data collection. All items are versioned
12
- * so that a new version can be uploaded while the current version serves.
10
+ * Reads eager files (route-manifest.json, build-metadata.json) from the dist
11
+ * directory alongside entry.mjs. Fetches lazy JSON files (page-parts, cache
12
+ * data) from a Wix data collection on demand and caches them to disk.
13
+ * All JS modules are resolved from the bundled MODULE_REGISTRY — no disk
14
+ * loading of JS files.
15
+ *
16
+ * Also supports writes (for upload-backend) to the data collection.
13
17
  *
14
18
  * Data collection schema:
15
- * _id: string — "{version}__{path}" (unique key)
16
- * version: string — build version (semver)
19
+ * _id: string — sha256("{version}/{path}") truncated to 32 chars
20
+ * version: string — deploy version (e.g. "0.0.1-d849685dc3de")
17
21
  * path: string — relative file path within backend dir
18
22
  * content: string — file content (text)
19
23
  * fileType: string — extension (js, json)
@@ -24,18 +28,21 @@ import { WixClientService } from '@jay-framework/wix-server-client';
24
28
  interface WixDataArtifactStoreOptions {
25
29
  wixClient: WixClient;
26
30
  collectionId: string;
27
- cacheDir: string;
28
31
  version: string;
32
+ /** Directory containing entry.mjs and eager files (route-manifest.json, build-metadata.json). Required for reads. */
33
+ distDir?: string;
34
+ /** Directory for caching lazy files fetched from the data collection */
35
+ cacheDir: string;
29
36
  moduleRegistry?: Record<string, any>;
30
37
  }
31
38
  declare class WixDataArtifactStore implements ArtifactStore {
32
39
  readonly collectionId: string;
33
40
  readonly version: string;
41
+ private readonly distDir;
34
42
  private readonly cacheDir;
35
43
  private readonly dataClient;
36
44
  private readonly moduleRegistry;
37
45
  private manifestCache?;
38
- private moduleCache;
39
46
  private fetchPromises;
40
47
  constructor(options: WixDataArtifactStoreOptions);
41
48
  readManifest(): Promise<RouteManifest>;
@@ -45,15 +52,7 @@ declare class WixDataArtifactStore implements ArtifactStore {
45
52
  loadModule(modulePath: string, _local?: boolean): Promise<any>;
46
53
  getAssetPath(relativePath: string): string;
47
54
  getBuildDir(): string;
48
- loadEagerFiles(): Promise<void>;
49
- /**
50
- * Write a single file to the data collection.
51
- */
52
55
  writeFile(relativePath: string, content: string, category: 'eager' | 'lazy'): Promise<void>;
53
- /**
54
- * Write a batch of files to the data collection.
55
- * Returns the number of successfully written files.
56
- */
57
56
  writeFiles(files: Array<{
58
57
  path: string;
59
58
  content: string;
package/dist/index.js CHANGED
@@ -21,7 +21,26 @@ import { getService } from "@jay-framework/stack-server-runtime";
21
21
  import { items } from "@wix/data";
22
22
  const DEFAULT_COLLECTION_ID = "jay-backend-files";
23
23
  const DEFAULT_CACHE_DIR = "/tmp/jay-backend";
24
+ function getDeployVersion(metadata) {
25
+ const version2 = metadata.version || "0.0.0";
26
+ const hash = metadata.sourceHash || "";
27
+ if (!hash) return version2;
28
+ return `${version2}-${hash}`;
29
+ }
24
30
  const DEFAULT_EXCLUDE_PLUGINS = ["aiditor", "ui-kit", "wix-deploy"];
31
+ function scanPagePartsFiles(dir, fs2, path2) {
32
+ const results = [];
33
+ if (!fs2.existsSync(dir)) return results;
34
+ for (const entry of fs2.readdirSync(dir, { withFileTypes: true })) {
35
+ const fullPath = path2.join(dir, entry.name);
36
+ if (entry.isDirectory()) {
37
+ results.push(...scanPagePartsFiles(fullPath, fs2, path2));
38
+ } else if (entry.name === "page-parts.json") {
39
+ results.push(fullPath);
40
+ }
41
+ }
42
+ return results;
43
+ }
25
44
  function sortPluginsByDeps(plugins) {
26
45
  const priorityPackages = ["@jay-framework/wix-server-client"];
27
46
  const sorted = [];
@@ -170,11 +189,11 @@ ${actionsArray.join("\n")}
170
189
  wixClient: wixClientService,
171
190
  collectionId: COLLECTION_ID,
172
191
  version: VERSION,
192
+ distDir: entryDir,
173
193
  cacheDir: '${DEFAULT_CACHE_DIR}',
174
194
  moduleRegistry: MODULE_REGISTRY,
175
195
  });
176
- console.log('[BaaS] Loading eager files...');
177
- await artifacts.loadEagerFiles();
196
+ console.log('[BaaS] Artifact store ready (eager files from dist/, lazy from collection)');
178
197
  }
179
198
 
180
199
  initialized = true;
@@ -257,8 +276,8 @@ function generateServeSource(frontendDir, backendDir) {
257
276
  'import { Readable } from "node:stream";',
258
277
  "",
259
278
  'process.env.STATIC_BASE_URL = process.env.STATIC_BASE_URL || "/";',
260
- `process.env.JAY_BACKEND_DIR = process.env.JAY_BACKEND_DIR || "${backendDir}";`,
261
- 'const entry = await import("./entry.mjs");',
279
+ `process.env.JAY_BACKEND_DIR = process.env.JAY_BACKEND_DIR || "";`,
280
+ 'const entry = await import("./dist/entry.mjs");',
262
281
  "const handler = entry.default?.fetch || entry.fetch;",
263
282
  'const PORT = parseInt(process.env.PORT || "4000", 10);',
264
283
  `const FRONTEND_DIR = "${frontendDir}";`,
@@ -326,10 +345,10 @@ const buildEntry = makeCliCommand("build-entry").withServices(CONSOLE_CONTEXT).w
326
345
  }
327
346
  const manifest = JSON.parse(fs2.readFileSync(manifestPath, "utf8"));
328
347
  const metadataPath = path2.join(buildDir, "build-metadata.json");
329
- let version2 = "1.0.0";
348
+ let version2 = "0.0.0";
330
349
  if (fs2.existsSync(metadataPath)) {
331
350
  const metadata = JSON.parse(fs2.readFileSync(metadataPath, "utf8"));
332
- version2 = String(metadata.version || "1.0.0");
351
+ version2 = getDeployVersion(metadata);
333
352
  }
334
353
  const filteredPlugins = manifest.plugins.filter(
335
354
  (p) => !excludePlugins.includes(p.name) && !excludePlugins.includes(p.packageName)
@@ -337,18 +356,35 @@ const buildEntry = makeCliCommand("build-entry").withServices(CONSOLE_CONTEXT).w
337
356
  const plugins = sortPluginsByDeps(filteredPlugins);
338
357
  const pluginPackages = new Set(plugins.map((p) => p.packageName));
339
358
  const actionPackages = manifest.actions.filter((a) => a.isPlugin && a.packageName && pluginPackages.has(a.packageName)).map((a) => a.packageName).filter((v, i, arr) => arr.indexOf(v) === i);
340
- const seSet = /* @__PURE__ */ new Set();
359
+ const localModuleSet = /* @__PURE__ */ new Set();
341
360
  for (const route of manifest.routes) {
342
- if (route.serverElementPath) seSet.add(route.serverElementPath);
361
+ if (route.serverElementPath) localModuleSet.add(route.serverElementPath);
362
+ if (route.serverModule) localModuleSet.add(route.serverModule);
343
363
  }
344
- const serverElements = [...seSet].map((rel) => ({
364
+ const pagePartsFiles = scanPagePartsFiles(buildDir, fs2, path2);
365
+ for (const ppFile of pagePartsFiles) {
366
+ try {
367
+ const config = JSON.parse(fs2.readFileSync(ppFile, "utf8"));
368
+ const collectLocal = (entries) => {
369
+ for (const entry of entries) {
370
+ if (entry.source === "local" && entry.modulePath) {
371
+ localModuleSet.add(entry.modulePath);
372
+ }
373
+ }
374
+ };
375
+ if (config.parts) collectLocal(config.parts);
376
+ if (config.instanceComponents) collectLocal(config.instanceComponents);
377
+ } catch {
378
+ }
379
+ }
380
+ const serverElements = [...localModuleSet].map((rel) => ({
345
381
  relativePath: rel,
346
382
  absolutePath: path2.join(buildDir, rel)
347
383
  }));
348
384
  ctx.log(`Version: ${version2}`);
349
385
  ctx.log(`Plugins: ${plugins.map((p) => p.name).join(", ")}`);
350
386
  ctx.log(`Action packages: ${actionPackages.join(", ")}`);
351
- ctx.log(`Server elements: ${serverElements.length} routes`);
387
+ ctx.log(`Local modules: ${serverElements.length} (${[...localModuleSet].join(", ")})`);
352
388
  const entrySource = generateEntrySource(
353
389
  plugins,
354
390
  actionPackages,
@@ -445,6 +481,13 @@ const buildEntry = makeCliCommand("build-entry").withServices(CONSOLE_CONTEXT).w
445
481
  JSON.stringify(result.metafile)
446
482
  );
447
483
  }
484
+ for (const name of ["route-manifest.json", "build-metadata.json"]) {
485
+ const src2 = path2.join(buildDir, name);
486
+ if (fs2.existsSync(src2)) {
487
+ fs2.copyFileSync(src2, path2.join(entryDir, name));
488
+ }
489
+ }
490
+ ctx.log("Copied route-manifest.json + build-metadata.json to dist/");
448
491
  const wixConfigSrc = path2.join(ctx.projectRoot, "config", ".wix.yaml");
449
492
  if (fs2.existsSync(wixConfigSrc)) {
450
493
  const configDir = path2.join(entryDir, "config");
@@ -458,16 +501,24 @@ const buildEntry = makeCliCommand("build-entry").withServices(CONSOLE_CONTEXT).w
458
501
  );
459
502
  }
460
503
  const serveFile = path2.join(ctx.projectRoot, "serve.mjs");
461
- fs2.writeFileSync(serveFile, generateServeSource(ctx.build.frontend, buildDir));
504
+ fs2.writeFileSync(serveFile, generateServeSource(ctx.build.frontend));
462
505
  ctx.log(`Generated ${serveFile} — run with: node serve.mjs`);
463
506
  return { success: true, outFile, sizeMB };
464
507
  });
465
- const SKIP_EXTENSIONS = /* @__PURE__ */ new Set([".png", ".jpg", ".jpeg", ".gif", ".svg", ".webp", ".jay-html"]);
508
+ const SKIP_EXTENSIONS = /* @__PURE__ */ new Set([
509
+ ".js",
510
+ ".png",
511
+ ".jpg",
512
+ ".jpeg",
513
+ ".gif",
514
+ ".svg",
515
+ ".webp",
516
+ ".jay-html"
517
+ ]);
466
518
  const MAX_BATCH_BYTES = 4e5;
467
519
  function categorize(relativePath) {
468
520
  if (relativePath === "route-manifest.json") return "eager";
469
521
  if (relativePath === "build-metadata.json") return "eager";
470
- if (relativePath.startsWith("server/")) return "eager";
471
522
  return "lazy";
472
523
  }
473
524
  function scanFileEntries(dir, base, fs2, path2) {
@@ -515,10 +566,10 @@ const uploadBackend = makeCliCommand("upload-backend").withServices(WIX_CLIENT_S
515
566
  const collectionId = input.collectionId || DEFAULT_COLLECTION_ID;
516
567
  const dryRun = input.dryRun || false;
517
568
  const metadataPath = path2.join(buildDir, "build-metadata.json");
518
- let version2 = "1.0.0";
569
+ let version2 = "0.0.0";
519
570
  if (fs2.existsSync(metadataPath)) {
520
571
  const metadata = JSON.parse(fs2.readFileSync(metadataPath, "utf8"));
521
- version2 = String(metadata.version || "1.0.0");
572
+ version2 = getDeployVersion(metadata);
522
573
  }
523
574
  if (dryRun) ctx.log("DRY RUN — no uploads");
524
575
  if (!fs2.existsSync(buildDir)) {
@@ -7203,14 +7254,6 @@ function prefixCtx(ctx, prefix) {
7203
7254
  return { ...ctx, log: (msg) => ctx.log(`[deploy] ${prefix} ${msg}`), warn: () => {
7204
7255
  } };
7205
7256
  }
7206
- function bumpPatch(version2) {
7207
- const parts = version2.split(".");
7208
- if (parts.length === 3) {
7209
- parts[2] = String(parseInt(parts[2], 10) + 1);
7210
- return parts.join(".");
7211
- }
7212
- return version2 + ".1";
7213
- }
7214
7257
  const deploy = makeCliCommand("deploy").withServices(WIX_CLIENT_SERVICE, CONSOLE_CONTEXT).withHandler(async (input, wixClient, ctx) => {
7215
7258
  const fs2 = await import("node:fs");
7216
7259
  const path2 = await import("node:path");
@@ -7222,11 +7265,8 @@ const deploy = makeCliCommand("deploy").withServices(WIX_CLIENT_SERVICE, CONSOLE
7222
7265
  return { success: false };
7223
7266
  }
7224
7267
  const metadata = JSON.parse(fs2.readFileSync(metadataPath, "utf8"));
7225
- const buildVersion = String(metadata.version || "1.0.0");
7226
- const deployVersion = bumpPatch(buildVersion);
7227
- metadata.version = deployVersion;
7228
- fs2.writeFileSync(metadataPath, JSON.stringify(metadata, null, 2));
7229
- ctx.log(`[deploy] Version: ${buildVersion} → ${deployVersion}`);
7268
+ const deployVersion = getDeployVersion(metadata);
7269
+ ctx.log(`[deploy] Version: ${deployVersion}`);
7230
7270
  ctx.log("[deploy] Bundling entry.mjs...");
7231
7271
  const buildResult = await buildEntry.handler(
7232
7272
  {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@jay-framework/wix-deploy",
3
- "version": "0.19.6",
3
+ "version": "0.20.0",
4
4
  "type": "module",
5
5
  "description": "Wix BaaS deployment adapter for Jay Framework — WixDataArtifactStore and entry builder",
6
6
  "license": "Apache-2.0",
@@ -25,10 +25,10 @@
25
25
  "test": ":"
26
26
  },
27
27
  "dependencies": {
28
- "@jay-framework/fullstack-component": "^0.19.6",
29
- "@jay-framework/production-server": "^0.19.6",
30
- "@jay-framework/stack-server-runtime": "^0.19.6",
31
- "@jay-framework/wix-server-client": "^0.19.6",
28
+ "@jay-framework/fullstack-component": "^0.20.0",
29
+ "@jay-framework/production-server": "^0.20.0",
30
+ "@jay-framework/stack-server-runtime": "^0.20.0",
31
+ "@jay-framework/wix-server-client": "^0.20.0",
32
32
  "@wix/data": "^1.0.433",
33
33
  "@wix/sdk": "^1.21.5",
34
34
  "esbuild": "^0.21.0",