@cavulsqa/create 2.11.0 → 2.11.2

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.
@@ -37,13 +37,13 @@ export function pruneEngines(out, manifest, engine) {
37
37
  if (existsSync(file)) rmSync(file);
38
38
  }
39
39
 
40
- dropLines(join(out, "src/shared/database/candidates/types.ts"), (line) =>
40
+ dropListItems(join(out, "src/shared/database/candidates/types.ts"), (line) =>
41
41
  [...deadEngines].some((id) => line.trim() === `"${id}",`),
42
42
  );
43
43
  dropLines(join(out, "src/shared/database/candidates/index.ts"), (line) =>
44
44
  dropped.some(([, module]) => line.includes(`"./${basenameOf(module.file)}"`)),
45
45
  );
46
- dropLines(join(out, "src/app/storage.config.ts"), (line) =>
46
+ dropListItems(join(out, "src/app/storage.config.ts"), (line) =>
47
47
  [...deadExports].some((symbol) => line.trim() === `${symbol},`),
48
48
  );
49
49
 
@@ -71,6 +71,64 @@ function dropLines(path, matches) {
71
71
  writeFileSync(path, kept.join("\n"));
72
72
  }
73
73
 
74
+ /** oxfmt's default `printWidth`, which neither template overrides. */
75
+ const PRINT_WIDTH = 100;
76
+
77
+ const LIST_ITEM = /^\s+[^\s/*].*,\s*$/;
78
+
79
+ /**
80
+ * `dropLines` for the items of a bracketed list, leaving the list the way oxfmt would print it.
81
+ *
82
+ * oxfmt puts an array or an import's specifiers on one line whenever that line fits, so a list the
83
+ * template had to break can fit once engines leave it - and an app whose first `vp check` fails on
84
+ * code nobody in it wrote is a broken scaffold. Only a list that lost an item is rejoined, and only
85
+ * when every line left in it is a plain item, so a list carrying a comment is never touched.
86
+ */
87
+ function dropListItems(path, matches) {
88
+ if (!existsSync(path)) return;
89
+ const lines = [];
90
+ const cuts = new Set();
91
+ for (const line of readFileSync(path, "utf8").split("\n")) {
92
+ if (matches(line)) cuts.add(lines.length);
93
+ else lines.push(line);
94
+ }
95
+
96
+ const lists = new Map();
97
+ for (const cut of cuts) {
98
+ const list = enclosingList(lines, cut);
99
+ if (list) lists.set(list.open, list);
100
+ }
101
+
102
+ for (const { open, close } of [...lists.values()].sort((a, b) => b.open - a.open)) {
103
+ const joined = joinList(lines[open], lines.slice(open + 1, close), lines[close]);
104
+ if (joined.length <= PRINT_WIDTH) lines.splice(open, close - open + 1, joined);
105
+ }
106
+ writeFileSync(path, lines.join("\n"));
107
+ }
108
+
109
+ /** The opening and closing lines around the place an item was cut, or null if it was no list. */
110
+ function enclosingList(lines, cut) {
111
+ let open = cut - 1;
112
+ while (open >= 0 && LIST_ITEM.test(lines[open])) open--;
113
+ let close = cut;
114
+ while (close < lines.length && LIST_ITEM.test(lines[close])) close++;
115
+ if (open < 0 || close >= lines.length || close === open + 1) return null;
116
+
117
+ const opener = lines[open].trimEnd();
118
+ const closer = { "[": "]", "{": "}" }[opener.at(-1)];
119
+ const indent = opener.match(/^\s*/)[0];
120
+ if (!closer || !lines[close].startsWith(`${indent}${closer}`)) return null;
121
+ return { open, close };
122
+ }
123
+
124
+ /** `[a, b]` hugs its brackets and `{ a, b }` does not, as oxfmt prints them. */
125
+ function joinList(opener, items, closer) {
126
+ const head = opener.trimEnd();
127
+ const body = items.map((item) => item.trim().replace(/,$/, "")).join(", ");
128
+ const tail = closer.trim();
129
+ return head.endsWith("{") ? `${head} ${body} ${tail}` : `${head}${body}${tail}`;
130
+ }
131
+
74
132
  function rewriteLine(path, matches, replacement) {
75
133
  if (!existsSync(path)) return;
76
134
  const lines = readFileSync(path, "utf8")
package/lib/scaffold.mjs CHANGED
@@ -48,9 +48,13 @@ The app ships no update screen: drive it with \`useUpdater()\` from \`@capuchoo/
48
48
  `;
49
49
  }
50
50
 
51
+ /**
52
+ * The generated app's manifest. Overridden keys keep the template's order, which oxfmt already
53
+ * accepts: it sorts package.json, and dropping `private` to re-add it last failed `vp check`.
54
+ */
51
55
  function manifest(source, { name, appName, templateName }) {
52
56
  const pkg = JSON.parse(source);
53
- const { private: _private, cavulsqa: _cavulsqa, ...rest } = pkg;
57
+ const { cavulsqa: _cavulsqa, ...rest } = pkg;
54
58
  return `${JSON.stringify(
55
59
  {
56
60
  ...rest,
@@ -118,7 +122,7 @@ export function scaffold({ templateDir, out, name, appId, appName, engine, pragm
118
122
  writeFileSync(join(out, ".env"), `${lines.join("\n")}\n`);
119
123
  }
120
124
 
121
- if (updateUrl) addUpdates(out, { appId, appName, updateUrl });
125
+ if (updateUrl) addUpdates(out, { appId, appName, updateUrl, engine, pragmas });
122
126
 
123
127
  // pnpm will not finish an install while a dependency's build script is neither allowed nor
124
128
  // denied, and vite-plus pulls esbuild in. Without this every generated app fails its first
package/lib/updates.mjs CHANGED
@@ -133,7 +133,15 @@ export function wireEntry(text) {
133
133
  return lines.join("\n");
134
134
  }
135
135
 
136
- export function flavourFile({ env, idSuffix, nameSuffix }, { appId, appName, updateUrl }) {
136
+ /**
137
+ * One flavour's env file. The engine and PRAGMA profile are repeated from `.env` because `.env` is
138
+ * git-ignored: a flavour that left them out would build with whatever the deploying machine has,
139
+ * which `capuchoo deploy` warns about and refuses for prod.
140
+ */
141
+ export function flavourFile(
142
+ { env, idSuffix, nameSuffix },
143
+ { appId, appName, updateUrl, engine, pragmas },
144
+ ) {
137
145
  return [
138
146
  `# The ${env} flavour. The Capuchoo CLI exports these values when it builds ${env}; see .env.example.`,
139
147
  `VITE_APP_ID=${appId}${idSuffix}`,
@@ -141,6 +149,8 @@ export function flavourFile({ env, idSuffix, nameSuffix }, { appId, appName, upd
141
149
  `VITE_ENVIRONMENT=${env}`,
142
150
  `VITE_UPDATE_API_URL=${updateUrl}`,
143
151
  `VITE_UPDATE_CHANNEL=${env}`,
152
+ ...(engine ? [`VITE_STORAGE_ENGINE=${engine}`] : []),
153
+ ...(pragmas ? [`VITE_PRAGMA_PROFILE=${pragmas}`] : []),
144
154
  "",
145
155
  ].join("\n");
146
156
  }
@@ -158,7 +168,7 @@ const ENV_EXAMPLE_UPDATES = `
158
168
  * app, its channels, registering the flavour ids - is left to `capuchoo init`, which reports
159
169
  * everything written here as already satisfied.
160
170
  */
161
- export function addUpdates(out, { appId, appName, updateUrl }) {
171
+ export function addUpdates(out, { appId, appName, updateUrl, engine, pragmas }) {
162
172
  const packagePath = join(out, "package.json");
163
173
  const pkg = JSON.parse(readFileSync(packagePath, "utf8"));
164
174
  writeFileSync(packagePath, `${JSON.stringify(withUpdatePackages(pkg), null, 2)}\n`);
@@ -174,7 +184,7 @@ export function addUpdates(out, { appId, appName, updateUrl }) {
174
184
  mkdirSync(dir, { recursive: true });
175
185
  writeFileSync(
176
186
  join(dir, `.env.${flavour.env}`),
177
- flavourFile(flavour, { appId, appName, updateUrl }),
187
+ flavourFile(flavour, { appId, appName, updateUrl, engine, pragmas }),
178
188
  );
179
189
  }
180
190
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cavulsqa/create",
3
- "version": "2.11.0",
3
+ "version": "2.11.2",
4
4
  "description": "Create a Vue + Capacitor + SQLite app from the cavulsqa templates: Framework7 (iOS and Material) or Material 3 Expressive.",
5
5
  "keywords": [
6
6
  "capacitor",
@@ -60,7 +60,7 @@
60
60
  }
61
61
  ]
62
62
  },
63
- "templatesFingerprint": "sha256-eIGH2ix9joNhpsfimiVjXn35142qMIzl59n4E69AcYg=",
63
+ "templatesFingerprint": "sha256-kWiSBoDPXxEaZd1rE56lZ5473btBLtf2mZosmUur3cc=",
64
64
  "scripts": {
65
65
  "build": "node scripts/bundleTemplates.mjs",
66
66
  "check": "vp check",
@@ -22,10 +22,10 @@
22
22
  "@capacitor/share": "^8.0.0",
23
23
  "@capacitor/splash-screen": "^8.0.0",
24
24
  "@capacitor/status-bar": "^8.0.0",
25
- "@cavulsqa/mobile-db": "^1.4.0",
26
- "@cavulsqa/reactive-db": "^1.4.0",
27
- "@cavulsqa/reactive-vue": "^1.4.0",
28
- "@cavulsqa/recorder": "^1.4.0",
25
+ "@cavulsqa/mobile-db": "^1.4.1",
26
+ "@cavulsqa/reactive-db": "^1.4.1",
27
+ "@cavulsqa/reactive-vue": "^1.4.1",
28
+ "@cavulsqa/recorder": "^1.4.1",
29
29
  "@sqlite.org/sqlite-wasm": "3.53.0-build1",
30
30
  "@tailwindcss/vite": "^4.3.3",
31
31
  "@vueuse/core": "^14.4.0",
@@ -21,11 +21,11 @@
21
21
  "@capacitor/preferences": "^8.0.0",
22
22
  "@capacitor/splash-screen": "^8.0.0",
23
23
  "@capacitor/status-bar": "^8.0.0",
24
- "@cavulsqa/m3e": "^1.4.0",
25
- "@cavulsqa/m3e-vue": "^1.4.0",
26
- "@cavulsqa/mobile-db": "^1.4.0",
27
- "@cavulsqa/reactive-db": "^1.4.0",
28
- "@cavulsqa/reactive-vue": "^1.4.0",
24
+ "@cavulsqa/m3e": "^1.4.1",
25
+ "@cavulsqa/m3e-vue": "^1.4.1",
26
+ "@cavulsqa/mobile-db": "^1.4.1",
27
+ "@cavulsqa/reactive-db": "^1.4.1",
28
+ "@cavulsqa/reactive-vue": "^1.4.1",
29
29
  "@fontsource-variable/google-sans-flex": "^5.3.1",
30
30
  "@sqlite.org/sqlite-wasm": "3.53.0-build1",
31
31
  "@tailwindcss/vite": "^4.3.3",