@cedarjs/cli 6.0.3-next.227 → 6.0.3-next.296

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.
@@ -1,7 +1,7 @@
1
1
  import fs from "node:fs";
2
2
  import path from "node:path";
3
3
  import { Listr } from "listr2";
4
- import { coerce, isGreaterOrEqual } from "verkit";
4
+ import { coerce, isGreaterThanOrEqual } from "verkit";
5
5
  import { colors as c } from "@cedarjs/cli-helpers/colors";
6
6
  import {
7
7
  addRootPackages,
@@ -40,7 +40,7 @@ const handler = async (options) => {
40
40
  );
41
41
  const reactVersion = webPkgJson["dependencies"]["react"];
42
42
  const coercedReactVersion = coerce(reactVersion);
43
- if (!coercedReactVersion || !isGreaterOrEqual(coercedReactVersion, "19.0.0")) {
43
+ if (!coercedReactVersion || !isGreaterThanOrEqual(coercedReactVersion, "19.0.0")) {
44
44
  throw new Error(
45
45
  "You need to be using at least React version 19 to enable the React Compiler"
46
46
  );
@@ -13,7 +13,7 @@ import {
13
13
  } from "@cedarjs/cli-helpers/packageManager/packages";
14
14
  import { recordTelemetryAttributes } from "@cedarjs/cli-helpers/telemetry";
15
15
  import { generate as generateTypes } from "@cedarjs/internal/dist/generate/generate";
16
- import { getConfig } from "@cedarjs/project-config";
16
+ import { getConfig, getParsedScalars } from "@cedarjs/project-config";
17
17
  import { pluralize, singularize } from "@cedarjs/utils/cedarPluralize";
18
18
  import {
19
19
  generateTemplate,
@@ -190,6 +190,7 @@ const assetFiles = async (name, tailwind) => {
190
190
  }
191
191
  return fileList;
192
192
  };
193
+ const isDateTimeParsed = () => getParsedScalars().DateTime === "Date";
193
194
  const formatters = async (name, isTypescript) => {
194
195
  const outputPath = path.join(
195
196
  getPaths().web.src,
@@ -211,7 +212,8 @@ const formatters = async (name, isTypescript) => {
211
212
  templatePath: path.join("lib", "formatters.tsx.template")
212
213
  }),
213
214
  {
214
- name
215
+ name,
216
+ parsedDateTime: isDateTimeParsed()
215
217
  }
216
218
  );
217
219
  const templateTest = await generateTemplate(
@@ -221,7 +223,8 @@ const formatters = async (name, isTypescript) => {
221
223
  templatePath: path.join("lib", "formatters.test.tsx.template")
222
224
  }),
223
225
  {
224
- name
226
+ name,
227
+ parsedDateTime: isDateTimeParsed()
225
228
  }
226
229
  );
227
230
  return {
@@ -341,7 +344,8 @@ const modelRelatedVariables = (model) => {
341
344
  fieldsToImport,
342
345
  editableColumns,
343
346
  listFormattersImports,
344
- formattersImports
347
+ formattersImports,
348
+ parsedDateTime: isDateTimeParsed()
345
349
  };
346
350
  };
347
351
  const layoutFiles = async (name, force, generateTypescript, templateStrings) => {
@@ -11,10 +11,36 @@ import {
11
11
  } from '@cedarjs/forms'
12
12
 
13
13
  <% if (fieldsToImport.includes('DatetimeLocalField')) { %>
14
- const formatDatetime = (value) => {
15
- if (value) {
16
- return value.replace(/:\d{2}\.\d{3}\w/, '')
14
+ /**
15
+ * Formats a DateTime <%= parsedDateTime ? 'Date object' : 'string' %> from the API, which is a UTC timestamp, for use as
16
+ * the value of a `datetime-local` input. The input takes `YYYY-MM-DDTHH:mm` in
17
+ * the user's local time, with no seconds, milliseconds or timezone, and the
18
+ * form reads its value back as local time when it is submitted.
19
+ */
20
+ function formatDatetime(value: <%= parsedDateTime ? 'Date' : 'string' %> | undefined | null) {
21
+ if (!value) {
22
+ return undefined
17
23
  }
24
+
25
+ const date = <%= parsedDateTime ? 'value' : 'new Date(value)' %>
26
+
27
+ if (Number.isNaN(date.getTime())) {
28
+ return undefined
29
+ }
30
+
31
+ const pad = (n: number) => String(n).padStart(2, '0')
32
+
33
+ return (
34
+ date.getFullYear() +
35
+ '-' +
36
+ pad(date.getMonth() + 1) +
37
+ '-' +
38
+ pad(date.getDate()) +
39
+ 'T' +
40
+ pad(date.getHours()) +
41
+ ':' +
42
+ pad(date.getMinutes())
43
+ )
18
44
  }
19
45
  <% } %>
20
46
 
@@ -30,6 +56,19 @@ interface ${singularPascalName}FormProps {
30
56
  const ${singularPascalName}Form = (props: ${singularPascalName}FormProps) => {
31
57
  const onSubmit = (data: Form${singularPascalName}) => {
32
58
  <% editableColumns.forEach(column => { %>
59
+ <% if (column.type === 'DateTime' && !column.isList) { %>
60
+ // The input only holds minutes, so an untouched field is sent back as the
61
+ // stored value, keeping its seconds, milliseconds and, when daylight
62
+ // saving time ends, which of the two repeated hours it was in
63
+ if (
64
+ data.${column.name} &&
65
+ props.${singularCamelName}?.${column.name} &&
66
+ formatDatetime(data.${column.name}) ===
67
+ formatDatetime(props.${singularCamelName}.${column.name})
68
+ ) {
69
+ data.${column.name} = props.${singularCamelName}.${column.name}
70
+ }
71
+ <% } %>
33
72
  <% if (column.isEnum && !column.isList && !column.isRequired) { %>
34
73
  if (data.${column.name} === '') {
35
74
  data.${column.name} = null
@@ -83,14 +83,25 @@ describe('jsonTruncate', () => {
83
83
 
84
84
  describe('timeTag', () => {
85
85
  it('renders a date', async () => {
86
+ <% if (parsedDateTime) { %>
87
+ render(<div>{timeTag(new Date('1970-08-20'))}</div>)
88
+ <% } else { %>
86
89
  render(<div>{timeTag(new Date('1970-08-20').toUTCString())}</div>)
90
+ <% } %>
87
91
 
88
92
  await waitFor(() => screen.getByText(/1970.*00:00:00/))
89
93
  })
90
94
 
95
+ <% if (parsedDateTime) { %>
96
+ it('can take an empty input', async () => {
97
+ expect(timeTag(null)).toEqual('')
98
+ expect(timeTag(undefined)).toEqual('')
99
+ })
100
+ <% } else { %>
91
101
  it('can take an empty input string', async () => {
92
102
  expect(timeTag('')).toEqual('')
93
103
  })
104
+ <% } %>
94
105
  })
95
106
 
96
107
  describe('jsonDisplay', () => {
@@ -39,15 +39,27 @@ export const jsonTruncate = (obj: unknown) => {
39
39
  return truncate(JSON.stringify(obj, null, 2))
40
40
  }
41
41
 
42
- export const timeTag = (dateTime?: string) => {
42
+ export function timeTag(dateTime: <%= parsedDateTime ? 'Date' : 'string' %> | undefined | null) {
43
43
  let output: string | React.JSX.Element = ''
44
44
 
45
45
  if (dateTime) {
46
+ <% if (parsedDateTime) { %>
47
+ if (!Number.isNaN(dateTime.getTime())) {
48
+ const isoString = dateTime.toISOString()
49
+
50
+ output = (
51
+ <time dateTime={isoString} title={isoString}>
52
+ {dateTime.toUTCString()}
53
+ </time>
54
+ )
55
+ }
56
+ <% } else { %>
46
57
  output = (
47
58
  <time dateTime={dateTime} title={dateTime}>
48
59
  {new Date(dateTime).toUTCString()}
49
60
  </time>
50
61
  )
62
+ <% } %>
51
63
  }
52
64
 
53
65
  return output
@@ -4,7 +4,7 @@ import { Listr } from "listr2";
4
4
  import { colors as c } from "@cedarjs/cli-helpers/colors";
5
5
  import { formatCedarCommand } from "@cedarjs/cli-helpers/packageManager/display";
6
6
  import { recordTelemetryAttributes } from "@cedarjs/cli-helpers/telemetry";
7
- import { getConfig, getPaths } from "@cedarjs/project-config";
7
+ import { getConfig, getParsedScalars, getPaths } from "@cedarjs/project-config";
8
8
  import { errorTelemetry } from "@cedarjs/telemetry";
9
9
  import { runScriptFunction } from "../lib/exec.js";
10
10
  import { configureBabel } from "../lib/execBabel.js";
@@ -106,6 +106,12 @@ const getTasks = async (dryrun, routerPathFilter = null) => {
106
106
  );
107
107
  return [];
108
108
  }
109
+ const parsedScalars = Object.keys(getParsedScalars());
110
+ if (parsedScalars.length > 0) {
111
+ throw new Error(
112
+ "Prerendering does not support `graphql.parsedScalars` yet. A prerendered Cell gets the raw GraphQL response, so " + parsedScalars.join(", ") + " would be a string when prerendering and parsed in the browser. Either remove the `prerender` prop from your routes, or remove `graphql.parsedScalars` from cedar.toml."
113
+ );
114
+ }
109
115
  const indexHtmlPath = path.join(getPaths().web.dist, "index.html");
110
116
  if (!fs.existsSync(indexHtmlPath)) {
111
117
  console.error(
@@ -1,5 +1,5 @@
1
1
  import enq from "enquirer";
2
- import { isGreaterOrEqual, isLess, tryParse } from "verkit";
2
+ import { isGreaterThanOrEqual, isLessThan, tryParse } from "verkit";
3
3
  import { dlx } from "@cedarjs/cli-helpers/packageManager/exec";
4
4
  import { getCompatibilityData } from "@cedarjs/cli-helpers/version";
5
5
  import { getPaths } from "@cedarjs/project-config";
@@ -16,7 +16,7 @@ async function handler({
16
16
  console.log(
17
17
  "No compatibility check will be performed because you used the --force flag."
18
18
  );
19
- if (tryParse(packageVersion) !== null && isLess(packageVersion, "1.0.0")) {
19
+ if (tryParse(packageVersion) !== null && isLessThan(packageVersion, "1.0.0")) {
20
20
  console.log(
21
21
  "Be aware that this package is under version 1.0.0 and so should be considered experimental."
22
22
  );
@@ -86,7 +86,7 @@ The latest version compatible with your project is ${latestCompatibleVersionText
86
86
  await runPackage(packageName, versionToUse, additionalOptionsToForward);
87
87
  }
88
88
  async function showExperimentalWarning(version) {
89
- if (version === void 0 || tryParse(version) === null || isGreaterOrEqual(version, "1.0.0")) {
89
+ if (version === void 0 || tryParse(version) === null || isGreaterThanOrEqual(version, "1.0.0")) {
90
90
  return;
91
91
  }
92
92
  const decision = await promptWithChoices(
@@ -3,7 +3,7 @@ import path from "path";
3
3
  import ansis from "ansis";
4
4
  import boxen from "boxen";
5
5
  import latestVersion from "latest-version";
6
- import { isGreater, isValid } from "verkit";
6
+ import { isGreaterThan, isValid } from "verkit";
7
7
  import { formatCedarCommand } from "@cedarjs/cli-helpers/packageManager/display";
8
8
  import { getNodeRunnerArgs } from "@cedarjs/cli-helpers/packageManager/exec";
9
9
  import { getConfig } from "@cedarjs/project-config";
@@ -106,7 +106,7 @@ function shouldShow() {
106
106
  const data = readUpdateDataFile();
107
107
  let newerVersion = false;
108
108
  data.remoteVersions.forEach((version) => {
109
- newerVersion ||= isGreater(version, localVersion);
109
+ newerVersion ||= isGreaterThan(version, localVersion);
110
110
  });
111
111
  return data.shownAt < (/* @__PURE__ */ new Date()).getTime() - SHOW_PERIOD && newerVersion;
112
112
  }
@@ -120,7 +120,7 @@ function getUpdateMessage() {
120
120
  let updateCount = 0;
121
121
  let message = ` New updates to Cedar are available via \`${formatCedarCommand(["upgrade#REPLACEME#"])}\` `;
122
122
  data.remoteVersions.forEach((version, tag) => {
123
- if (isGreater(version, data.localVersion)) {
123
+ if (isGreaterThan(version, data.localVersion)) {
124
124
  updateCount += 1;
125
125
  if (tag === localTag) {
126
126
  message += `
@@ -1,4 +1,4 @@
1
- import { clean, isGreaterOrEqual } from "verkit";
1
+ import { clean, isGreaterThanOrEqual } from "verkit";
2
2
  import { colors as c } from "@cedarjs/cli-helpers/colors";
3
3
  function checkNodeVersion() {
4
4
  const checks = { ok: true };
@@ -10,7 +10,7 @@ function checkNodeVersion() {
10
10
  checks.message = `Invalid Node.js version: ${pVersion}`;
11
11
  return checks;
12
12
  }
13
- if (isGreaterOrEqual(pVersionC, LOWER_BOUND)) {
13
+ if (isGreaterThanOrEqual(pVersionC, LOWER_BOUND)) {
14
14
  return checks;
15
15
  }
16
16
  checks.ok = false;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cedarjs/cli",
3
- "version": "6.0.3-next.227",
3
+ "version": "6.0.3-next.296",
4
4
  "description": "The CedarJS Command Line",
5
5
  "repository": {
6
6
  "type": "git",
@@ -32,21 +32,21 @@
32
32
  },
33
33
  "dependencies": {
34
34
  "@babel/core": "^7.26.10",
35
- "@babel/parser": "7.29.8",
35
+ "@babel/parser": "7.29.9",
36
36
  "@babel/preset-typescript": "7.29.7",
37
37
  "@babel/traverse": "7.29.8",
38
38
  "@babel/types": "7.29.8",
39
- "@cedarjs/api-server": "6.0.3-next.227",
40
- "@cedarjs/babel-config": "6.0.3-next.227",
41
- "@cedarjs/cli-helpers": "6.0.3-next.227",
42
- "@cedarjs/internal": "6.0.3-next.227",
43
- "@cedarjs/prerender": "6.0.3-next.227",
44
- "@cedarjs/project-config": "6.0.3-next.227",
45
- "@cedarjs/structure": "6.0.3-next.227",
46
- "@cedarjs/telemetry": "6.0.3-next.227",
47
- "@cedarjs/utils": "6.0.3-next.227",
48
- "@cedarjs/vite": "6.0.3-next.227",
49
- "@cedarjs/web-server": "6.0.3-next.227",
39
+ "@cedarjs/api-server": "6.0.3-next.296",
40
+ "@cedarjs/babel-config": "6.0.3-next.296",
41
+ "@cedarjs/cli-helpers": "6.0.3-next.296",
42
+ "@cedarjs/internal": "6.0.3-next.296",
43
+ "@cedarjs/prerender": "6.0.3-next.296",
44
+ "@cedarjs/project-config": "6.0.3-next.296",
45
+ "@cedarjs/structure": "6.0.3-next.296",
46
+ "@cedarjs/telemetry": "6.0.3-next.296",
47
+ "@cedarjs/utils": "6.0.3-next.296",
48
+ "@cedarjs/vite": "6.0.3-next.296",
49
+ "@cedarjs/web-server": "6.0.3-next.296",
50
50
  "@listr2/prompt-adapter-enquirer": "4.3.2",
51
51
  "@opentelemetry/api": "1.9.1",
52
52
  "@opentelemetry/core": "2.11.0",
@@ -55,7 +55,7 @@
55
55
  "@opentelemetry/sdk-trace-node": "2.11.0",
56
56
  "@opentelemetry/semantic-conventions": "1.43.0",
57
57
  "@prisma/internals": "7.10.0",
58
- "ansis": "4.3.1",
58
+ "ansis": "4.4.0",
59
59
  "archiver": "7.0.1",
60
60
  "boxen": "5.1.2",
61
61
  "camel-case": "4.1.2",
@@ -79,25 +79,25 @@
79
79
  "pascalcase": "1.0.0",
80
80
  "pluralize": "8.0.0",
81
81
  "portfinder": "1.0.38",
82
- "prettier": "3.9.6",
82
+ "prettier": "3.9.8",
83
83
  "prisma": "7.10.0",
84
84
  "prompts": "2.4.2",
85
85
  "smol-toml": "1.8.0",
86
86
  "srvx": "0.12.8",
87
87
  "string-env-interpolation": "1.0.1",
88
- "systeminformation": "5.33.10",
88
+ "systeminformation": "5.33.13",
89
89
  "termi-link": "1.1.0",
90
90
  "title-case": "3.0.3",
91
91
  "unionfs": "4.6.0",
92
92
  "uuid": "11.1.1",
93
- "verkit": "0.4.0",
93
+ "verkit": "0.5.0",
94
94
  "yargs": "17.7.3"
95
95
  },
96
96
  "devDependencies": {
97
- "@cedarjs/framework-tools": "6.0.3-next.227",
97
+ "@cedarjs/framework-tools": "6.0.3-next.296",
98
98
  "@prisma/dmmf": "7.10.0",
99
99
  "@types/archiver": "^7.0.0",
100
- "memfs": "4.76.0",
100
+ "memfs": "4.79.0",
101
101
  "node-ssh": "13.2.1",
102
102
  "ts-dedent": "2.3.0",
103
103
  "typescript": "5.9.3",