@cedarjs/cli 2.5.1 → 2.5.2-next.16
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/dist/commands/lint.js +14 -17
- package/dist/commands/setup/realtime/addRealtimeToGraphql.js +68 -0
- package/dist/commands/setup/realtime/realtimeHandler.js +49 -7
- package/dist/commands/setup/realtime/templates/liveQueries/auctions/auctions.sdl.ts.template +0 -2
- package/dist/commands/setup/realtime/templates/liveQueries/auctions/auctions.ts.template +0 -1
- package/dist/commands/setup/realtime/templates/realtime.ts.template +8 -6
- package/dist/lib/exec.js +6 -2
- package/package.json +13 -11
package/dist/commands/lint.js
CHANGED
|
@@ -58,10 +58,10 @@ function showLegacyEslintDeprecationWarning(legacyFiles) {
|
|
|
58
58
|
console.warn(" See more here: https://github.com/cedarjs/cedar/pull/629");
|
|
59
59
|
console.warn("");
|
|
60
60
|
}
|
|
61
|
-
const command = "lint [
|
|
61
|
+
const command = "lint [paths..]";
|
|
62
62
|
const description = "Lint your files";
|
|
63
63
|
const builder = (yargs) => {
|
|
64
|
-
yargs.positional("
|
|
64
|
+
yargs.positional("paths", {
|
|
65
65
|
description: "Specify file(s) or directory(ies) to lint relative to project root",
|
|
66
66
|
type: "array"
|
|
67
67
|
}).option("fix", {
|
|
@@ -79,7 +79,7 @@ const builder = (yargs) => {
|
|
|
79
79
|
)}`
|
|
80
80
|
);
|
|
81
81
|
};
|
|
82
|
-
const handler = async ({
|
|
82
|
+
const handler = async ({ paths, fix, format }) => {
|
|
83
83
|
recordTelemetryAttributes({ command: "lint", fix, format });
|
|
84
84
|
const config = getConfig();
|
|
85
85
|
const legacyConfigFiles = detectLegacyEslintConfig();
|
|
@@ -87,21 +87,18 @@ const handler = async ({ path: path2, fix, format }) => {
|
|
|
87
87
|
showLegacyEslintDeprecationWarning(legacyConfigFiles);
|
|
88
88
|
}
|
|
89
89
|
try {
|
|
90
|
-
const pathString = path2?.join(" ");
|
|
91
90
|
const sbPath = getPaths().web.storybook;
|
|
92
|
-
const args = [
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
].filter(Boolean);
|
|
104
|
-
const result = await execa("yarn", args, {
|
|
91
|
+
const args = ["eslint", fix && "--fix", "--format", format, ...paths];
|
|
92
|
+
if (paths.length === 0) {
|
|
93
|
+
args.push(
|
|
94
|
+
fs.existsSync(getPaths().web.src) && "web/src",
|
|
95
|
+
fs.existsSync(getPaths().web.config) && "web/config",
|
|
96
|
+
fs.existsSync(sbPath) && "web/.storybook",
|
|
97
|
+
fs.existsSync(getPaths().scripts) && "scripts",
|
|
98
|
+
fs.existsSync(getPaths().api.src) && "api/src"
|
|
99
|
+
);
|
|
100
|
+
}
|
|
101
|
+
const result = await execa("yarn", args.filter(Boolean), {
|
|
105
102
|
cwd: getPaths().base,
|
|
106
103
|
stdio: "inherit"
|
|
107
104
|
});
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
import fs from "node:fs";
|
|
2
|
+
import path from "node:path";
|
|
3
|
+
import { isTypeScriptProject } from "@cedarjs/cli-helpers";
|
|
4
|
+
import { getPaths } from "@cedarjs/project-config";
|
|
5
|
+
function addRealtimeToGraphqlHandler(ctx, task, force) {
|
|
6
|
+
const graphqlHandlerPath = path.join(
|
|
7
|
+
getPaths().api.functions,
|
|
8
|
+
`graphql.${isTypeScriptProject() ? "ts" : "js"}`
|
|
9
|
+
);
|
|
10
|
+
if (!fs.existsSync(graphqlHandlerPath)) {
|
|
11
|
+
ctx.realtimeHandlerSkipped = true;
|
|
12
|
+
task.skip("GraphQL handler not found");
|
|
13
|
+
return;
|
|
14
|
+
}
|
|
15
|
+
const contentLines = fs.readFileSync(graphqlHandlerPath).toString().split("\n");
|
|
16
|
+
const importLineRegex = /^import {.*realtime.*} from ['"]src\/lib\/realtime['"];?$/;
|
|
17
|
+
const multilineImportRegex = /^} from ['"]src\/lib\/realtime['"];?$/;
|
|
18
|
+
const hasRealtimeImport = contentLines.some((line) => {
|
|
19
|
+
return importLineRegex.test(line) || multilineImportRegex.test(line);
|
|
20
|
+
});
|
|
21
|
+
if (hasRealtimeImport && !force) {
|
|
22
|
+
ctx.realtimeHandlerSkipped = true;
|
|
23
|
+
task.skip("Realtime import already exists");
|
|
24
|
+
return;
|
|
25
|
+
}
|
|
26
|
+
const handlerIndex = contentLines.findLastIndex(
|
|
27
|
+
(line) => line === "export const handler = createGraphQLHandler({"
|
|
28
|
+
);
|
|
29
|
+
if (handlerIndex === -1) {
|
|
30
|
+
ctx.realtimeHandlerSkipped = true;
|
|
31
|
+
task.skip("Unexpected syntax. Handler not found");
|
|
32
|
+
return;
|
|
33
|
+
}
|
|
34
|
+
const handlerLines = contentLines.slice(handlerIndex);
|
|
35
|
+
const hasRealtimeOption = handlerLines.some(
|
|
36
|
+
(line) => /^\s*realtime\b/.test(line)
|
|
37
|
+
);
|
|
38
|
+
if (hasRealtimeOption && !force) {
|
|
39
|
+
ctx.realtimeHandlerSkipped = true;
|
|
40
|
+
task.skip("Realtime option already exists");
|
|
41
|
+
return;
|
|
42
|
+
}
|
|
43
|
+
const lastImportIndex = contentLines.slice(0, handlerIndex).findLastIndex((line) => line.startsWith("import "));
|
|
44
|
+
if (lastImportIndex === -1) {
|
|
45
|
+
ctx.realtimeHandlerSkipped = true;
|
|
46
|
+
task.skip("Unexpected syntax. No imports found");
|
|
47
|
+
return;
|
|
48
|
+
}
|
|
49
|
+
contentLines.splice(
|
|
50
|
+
lastImportIndex + 1,
|
|
51
|
+
0,
|
|
52
|
+
"import { realtime } from 'src/lib/realtime'"
|
|
53
|
+
);
|
|
54
|
+
const handlerIndexAfterSplice = handlerIndex + 1;
|
|
55
|
+
const sdlsIndex = handlerLines.findLastIndex(
|
|
56
|
+
(line) => /^\s*sdls,$/.test(line)
|
|
57
|
+
);
|
|
58
|
+
if (sdlsIndex === -1) {
|
|
59
|
+
ctx.realtimeHandlerSkipped = true;
|
|
60
|
+
task.skip("Unexpected syntax. `sdls` option not found");
|
|
61
|
+
return;
|
|
62
|
+
}
|
|
63
|
+
contentLines.splice(handlerIndexAfterSplice + sdlsIndex, 0, " realtime,");
|
|
64
|
+
fs.writeFileSync(graphqlHandlerPath, contentLines.join("\n"));
|
|
65
|
+
}
|
|
66
|
+
export {
|
|
67
|
+
addRealtimeToGraphqlHandler
|
|
68
|
+
};
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import fs from "node:fs";
|
|
2
2
|
import path from "path";
|
|
3
|
+
import execa from "execa";
|
|
3
4
|
import { Listr } from "listr2";
|
|
4
5
|
import { addApiPackages } from "@cedarjs/cli-helpers";
|
|
5
6
|
import { generate as generateTypes } from "@cedarjs/internal/dist/generate/generate";
|
|
@@ -9,6 +10,7 @@ import c from "../../../lib/colors.js";
|
|
|
9
10
|
import { getPaths, transformTSToJS, writeFile } from "../../../lib/index.js";
|
|
10
11
|
import { isTypeScriptProject, serverFileExists } from "../../../lib/project.js";
|
|
11
12
|
import { setupServerFileTasks } from "../server-file/serverFileHandler.js";
|
|
13
|
+
import { addRealtimeToGraphqlHandler } from "./addRealtimeToGraphql.js";
|
|
12
14
|
const { version } = JSON.parse(
|
|
13
15
|
fs.readFileSync(
|
|
14
16
|
path.resolve(import.meta.dirname, "../../../../package.json"),
|
|
@@ -26,7 +28,7 @@ async function handler({ force, includeExamples, verbose }) {
|
|
|
26
28
|
[
|
|
27
29
|
addApiPackages(["ioredis@^5", `@cedarjs/realtime@${version}`]),
|
|
28
30
|
{
|
|
29
|
-
title: "Adding the realtime api lib
|
|
31
|
+
title: "Adding the realtime api lib...",
|
|
30
32
|
task: async () => {
|
|
31
33
|
const serverFileTemplateContent = fs.readFileSync(
|
|
32
34
|
path.resolve(
|
|
@@ -48,7 +50,13 @@ async function handler({ force, includeExamples, verbose }) {
|
|
|
48
50
|
}
|
|
49
51
|
},
|
|
50
52
|
{
|
|
51
|
-
title: "
|
|
53
|
+
title: "Enabling realtime support in the GraphQL handler...",
|
|
54
|
+
task: (ctx, task) => {
|
|
55
|
+
addRealtimeToGraphqlHandler(ctx, task, force);
|
|
56
|
+
}
|
|
57
|
+
},
|
|
58
|
+
{
|
|
59
|
+
title: "Adding Countdown example subscription...",
|
|
52
60
|
enabled: () => includeExamples,
|
|
53
61
|
task: async () => {
|
|
54
62
|
let exampleSubscriptionTemplateContent = fs.readFileSync(
|
|
@@ -84,7 +92,7 @@ async function handler({ force, includeExamples, verbose }) {
|
|
|
84
92
|
}
|
|
85
93
|
},
|
|
86
94
|
{
|
|
87
|
-
title: "Adding NewMessage example subscription
|
|
95
|
+
title: "Adding NewMessage example subscription...",
|
|
88
96
|
enabled: () => includeExamples,
|
|
89
97
|
task: async () => {
|
|
90
98
|
const exampleSdlTemplateContent = fs.readFileSync(
|
|
@@ -157,7 +165,7 @@ async function handler({ force, includeExamples, verbose }) {
|
|
|
157
165
|
}
|
|
158
166
|
},
|
|
159
167
|
{
|
|
160
|
-
title: "Adding Auctions example live query
|
|
168
|
+
title: "Adding Auctions example live query...",
|
|
161
169
|
enabled: () => includeExamples,
|
|
162
170
|
task: async () => {
|
|
163
171
|
const exampleSdlTemplateContent = fs.readFileSync(
|
|
@@ -202,7 +210,7 @@ async function handler({ force, includeExamples, verbose }) {
|
|
|
202
210
|
}
|
|
203
211
|
},
|
|
204
212
|
{
|
|
205
|
-
title: "Adding Defer example queries
|
|
213
|
+
title: "Adding Defer example queries...",
|
|
206
214
|
enabled: () => includeExamples,
|
|
207
215
|
task: async () => {
|
|
208
216
|
const exampleSdlTemplateContent = fs.readFileSync(
|
|
@@ -247,7 +255,7 @@ async function handler({ force, includeExamples, verbose }) {
|
|
|
247
255
|
}
|
|
248
256
|
},
|
|
249
257
|
{
|
|
250
|
-
title: "Adding Stream example queries
|
|
258
|
+
title: "Adding Stream example queries...",
|
|
251
259
|
enabled: () => includeExamples,
|
|
252
260
|
task: async () => {
|
|
253
261
|
const exampleSdlTemplateContent = fs.readFileSync(
|
|
@@ -292,13 +300,31 @@ async function handler({ force, includeExamples, verbose }) {
|
|
|
292
300
|
}
|
|
293
301
|
},
|
|
294
302
|
{
|
|
295
|
-
title: `Generating types
|
|
303
|
+
title: `Generating types...`,
|
|
296
304
|
task: async () => {
|
|
297
305
|
await generateTypes();
|
|
298
306
|
console.log(
|
|
299
307
|
"Note: You may need to manually restart GraphQL in VSCode to see the new types take effect.\n\n"
|
|
300
308
|
);
|
|
301
309
|
}
|
|
310
|
+
},
|
|
311
|
+
{
|
|
312
|
+
title: "Cleaning up...",
|
|
313
|
+
task: () => {
|
|
314
|
+
const graphqlHandlerPath = path.join(
|
|
315
|
+
getPaths().api.functions,
|
|
316
|
+
`graphql.${isTypeScriptProject() ? "ts" : "js"}`
|
|
317
|
+
);
|
|
318
|
+
execa.sync(
|
|
319
|
+
"yarn",
|
|
320
|
+
["cedar", "lint", "--fix", graphqlHandlerPath, realtimeLibFilePath],
|
|
321
|
+
{
|
|
322
|
+
cwd: getPaths().base,
|
|
323
|
+
// Silently ignore errors
|
|
324
|
+
reject: false
|
|
325
|
+
}
|
|
326
|
+
);
|
|
327
|
+
}
|
|
302
328
|
}
|
|
303
329
|
],
|
|
304
330
|
{
|
|
@@ -311,6 +337,22 @@ async function handler({ force, includeExamples, verbose }) {
|
|
|
311
337
|
tasks.add(setupServerFileTasks({ force }));
|
|
312
338
|
}
|
|
313
339
|
await tasks.run();
|
|
340
|
+
if (tasks.ctx?.realtimeHandlerSkipped) {
|
|
341
|
+
const graphqlHandlerPath = path.join(
|
|
342
|
+
getPaths().api.functions,
|
|
343
|
+
`graphql.${isTypeScriptProject() ? "ts" : "js"}`
|
|
344
|
+
);
|
|
345
|
+
const relativePath = path.relative(getPaths().base, graphqlHandlerPath);
|
|
346
|
+
console.log();
|
|
347
|
+
console.log(
|
|
348
|
+
c.warning(
|
|
349
|
+
`Note: The setup command skipped adding realtime to your GraphQL handler. Please review ${relativePath}, and manually add it if needed.`
|
|
350
|
+
)
|
|
351
|
+
);
|
|
352
|
+
console.log(
|
|
353
|
+
"You want to make sure you have an import like `import { realtime } from '@cedarjs/realtime'`, and that you pass `realtime` to the call to `createGraphQLHandler`."
|
|
354
|
+
);
|
|
355
|
+
}
|
|
314
356
|
} catch (e) {
|
|
315
357
|
errorTelemetry(process.argv, e.message);
|
|
316
358
|
console.error(c.error(e.message));
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { CedarRealtimeOptions } from '@cedarjs/realtime'
|
|
2
2
|
|
|
3
3
|
import subscriptions from 'src/subscriptions/**/*.{js,ts}'
|
|
4
4
|
|
|
@@ -14,21 +14,23 @@ import subscriptions from 'src/subscriptions/**/*.{js,ts}'
|
|
|
14
14
|
*
|
|
15
15
|
* Realtime supports Live Queries and Subscriptions over GraphQL SSE.
|
|
16
16
|
*
|
|
17
|
-
* Live Queries are GraphQL queries that are automatically re-run when the data
|
|
17
|
+
* Live Queries are GraphQL queries that are automatically re-run when the data
|
|
18
|
+
* they depend on changes.
|
|
18
19
|
*
|
|
19
|
-
* Subscriptions are GraphQL queries that are run when a client subscribes to a
|
|
20
|
+
* Subscriptions are GraphQL queries that are run when a client subscribes to a
|
|
21
|
+
* channel.
|
|
20
22
|
*
|
|
21
23
|
* CedarJS Realtime
|
|
22
24
|
* - uses a publish/subscribe model to broadcast data to clients.
|
|
23
25
|
* - uses a store to persist Live Query and Subscription data.
|
|
24
|
-
* - and enable defer and stream directives to improve latency
|
|
25
|
-
*
|
|
26
|
+
* - and enable defer and stream directives to improve latency for clients by
|
|
27
|
+
* sending data the most important data as soon as it's ready.
|
|
26
28
|
*
|
|
27
29
|
* CedarJS Realtime supports in-memory and Redis stores:
|
|
28
30
|
* - In-memory stores are useful for development and testing.
|
|
29
31
|
* - Redis stores are useful for production.
|
|
30
32
|
*/
|
|
31
|
-
export const realtime:
|
|
33
|
+
export const realtime: CedarRealtimeOptions = {
|
|
32
34
|
subscriptions: {
|
|
33
35
|
subscriptions,
|
|
34
36
|
store: 'in-memory',
|
package/dist/lib/exec.js
CHANGED
|
@@ -8,7 +8,9 @@ import {
|
|
|
8
8
|
cedarCellTransform,
|
|
9
9
|
cedarjsDirectoryNamedImportPlugin,
|
|
10
10
|
cedarjsJobPathInjectorPlugin,
|
|
11
|
-
cedarSwapApolloProvider
|
|
11
|
+
cedarSwapApolloProvider,
|
|
12
|
+
cedarImportDirPlugin,
|
|
13
|
+
cedarAutoImportsPlugin
|
|
12
14
|
} from "@cedarjs/vite";
|
|
13
15
|
async function runScriptFunction({
|
|
14
16
|
path: scriptPath,
|
|
@@ -72,7 +74,9 @@ async function runScriptFunction({
|
|
|
72
74
|
cedarjsDirectoryNamedImportPlugin(),
|
|
73
75
|
cedarCellTransform(),
|
|
74
76
|
cedarjsJobPathInjectorPlugin(),
|
|
75
|
-
cedarSwapApolloProvider()
|
|
77
|
+
cedarSwapApolloProvider(),
|
|
78
|
+
cedarImportDirPlugin(),
|
|
79
|
+
cedarAutoImportsPlugin()
|
|
76
80
|
]
|
|
77
81
|
});
|
|
78
82
|
if (Number(viteVersion.split(".")[0]) < 6) {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@cedarjs/cli",
|
|
3
|
-
"version": "2.5.
|
|
3
|
+
"version": "2.5.2-next.16+a27a893fb",
|
|
4
4
|
"description": "The CedarJS Command Line",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -31,17 +31,18 @@
|
|
|
31
31
|
"test:watch": "vitest watch"
|
|
32
32
|
},
|
|
33
33
|
"dependencies": {
|
|
34
|
+
"@babel/parser": "7.29.0",
|
|
34
35
|
"@babel/preset-typescript": "7.28.5",
|
|
35
36
|
"@babel/runtime-corejs3": "7.29.0",
|
|
36
|
-
"@cedarjs/api-server": "2.5.
|
|
37
|
-
"@cedarjs/cli-helpers": "2.5.
|
|
38
|
-
"@cedarjs/fastify-web": "2.5.
|
|
39
|
-
"@cedarjs/internal": "2.5.
|
|
40
|
-
"@cedarjs/prerender": "2.5.
|
|
41
|
-
"@cedarjs/project-config": "2.5.
|
|
42
|
-
"@cedarjs/structure": "2.5.
|
|
43
|
-
"@cedarjs/telemetry": "2.5.
|
|
44
|
-
"@cedarjs/web-server": "2.5.
|
|
37
|
+
"@cedarjs/api-server": "2.5.2-next.16+a27a893fb",
|
|
38
|
+
"@cedarjs/cli-helpers": "2.5.2-next.16+a27a893fb",
|
|
39
|
+
"@cedarjs/fastify-web": "2.5.2-next.16+a27a893fb",
|
|
40
|
+
"@cedarjs/internal": "2.5.2-next.16+a27a893fb",
|
|
41
|
+
"@cedarjs/prerender": "2.5.2-next.16+a27a893fb",
|
|
42
|
+
"@cedarjs/project-config": "2.5.2-next.16+a27a893fb",
|
|
43
|
+
"@cedarjs/structure": "2.5.2-next.16+a27a893fb",
|
|
44
|
+
"@cedarjs/telemetry": "2.5.2-next.16+a27a893fb",
|
|
45
|
+
"@cedarjs/web-server": "2.5.2-next.16+a27a893fb",
|
|
45
46
|
"@listr2/prompt-adapter-enquirer": "2.0.16",
|
|
46
47
|
"@opentelemetry/api": "1.9.0",
|
|
47
48
|
"@opentelemetry/core": "1.30.1",
|
|
@@ -78,6 +79,7 @@
|
|
|
78
79
|
"prettier": "3.8.1",
|
|
79
80
|
"prisma": "6.19.2",
|
|
80
81
|
"prompts": "2.4.2",
|
|
82
|
+
"recast": "0.23.11",
|
|
81
83
|
"rimraf": "6.1.2",
|
|
82
84
|
"semver": "7.7.3",
|
|
83
85
|
"smol-toml": "1.6.0",
|
|
@@ -104,5 +106,5 @@
|
|
|
104
106
|
"publishConfig": {
|
|
105
107
|
"access": "public"
|
|
106
108
|
},
|
|
107
|
-
"gitHead": "
|
|
109
|
+
"gitHead": "a27a893fb8f6883f3bf121dad4d3edf7696484fe"
|
|
108
110
|
}
|