diff --git a/packages/babel-config/dist.test.ts b/packages/babel-config/dist.test.ts index b4a6b0551e58..09e3ed657629 100644 --- a/packages/babel-config/dist.test.ts +++ b/packages/babel-config/dist.test.ts @@ -13,10 +13,10 @@ describe('dist', () => { "proposals": true, "version": 3, }, - "version": "7.22.10", + "version": "7.22.11", }, "CORE_JS_VERSION": "3.32", - "RUNTIME_CORE_JS_VERSION": "7.22.10", + "RUNTIME_CORE_JS_VERSION": "7.22.11", "TARGETS_NODE": "18.16", "getApiSideBabelConfigPath": [Function], "getApiSideBabelPlugins": [Function], diff --git a/packages/babel-config/package.json b/packages/babel-config/package.json index a4d536b4487c..bc2e09a1042a 100644 --- a/packages/babel-config/package.json +++ b/packages/babel-config/package.json @@ -22,6 +22,7 @@ }, "dependencies": { "@babel/core": "7.22.11", + "@babel/parser": "7.22.13", "@babel/plugin-transform-class-properties": "7.22.5", "@babel/plugin-transform-private-methods": "7.22.5", "@babel/plugin-transform-private-property-in-object": "7.22.11", @@ -31,13 +32,14 @@ "@babel/preset-typescript": "7.22.11", "@babel/register": "7.22.5", "@babel/runtime-corejs3": "7.22.11", + "@babel/traverse": "7.22.11", "@redwoodjs/project-config": "6.1.0", - "@redwoodjs/structure": "6.1.0", "babel-plugin-auto-import": "1.1.0", "babel-plugin-graphql-tag": "3.3.0", "babel-plugin-module-resolver": "5.0.0", "core-js": "3.32.0", - "fast-glob": "3.3.1" + "fast-glob": "3.3.1", + "graphql": "16.8.0" }, "devDependencies": { "@types/babel-plugin-tester": "9.0.5", diff --git a/packages/babel-config/src/plugins/__tests__/babel-plugin-redwood-mock-cell-data.test.ts b/packages/babel-config/src/plugins/__tests__/babel-plugin-redwood-mock-cell-data.test.ts index 4bb60f535960..1a63e132f863 100644 --- a/packages/babel-config/src/plugins/__tests__/babel-plugin-redwood-mock-cell-data.test.ts +++ b/packages/babel-config/src/plugins/__tests__/babel-plugin-redwood-mock-cell-data.test.ts @@ -6,6 +6,7 @@ import plugin from '../babel-plugin-redwood-mock-cell-data' describe('babel plugin redwood mock cell data', () => { const __fixtures__ = path.resolve(__dirname, '../../../../../__fixtures__') + process.env.RWJS_CWD = path.join(__fixtures__, 'example-todo-main') pluginTester({ plugin, diff --git a/packages/babel-config/src/plugins/babel-plugin-redwood-mock-cell-data.ts b/packages/babel-config/src/plugins/babel-plugin-redwood-mock-cell-data.ts index e24700943254..51ea30fd19e9 100644 --- a/packages/babel-config/src/plugins/babel-plugin-redwood-mock-cell-data.ts +++ b/packages/babel-config/src/plugins/babel-plugin-redwood-mock-cell-data.ts @@ -1,10 +1,13 @@ +import fs from 'fs' import path from 'path' -// TODO: Figure out why Wallaby doesn't work with a normal import. -import type { PluginObj, types } from '@babel/core' - -import { getBaseDirFromFile } from '@redwoodjs/project-config' -import { getProject, URL_file } from '@redwoodjs/structure' +import { types } from '@babel/core' +import type { PluginObj } from '@babel/core' +import { parse as babelParse } from '@babel/parser' +import type { ParserPlugin } from '@babel/parser' +import traverse from '@babel/traverse' +import fg from 'fast-glob' +import { parse as graphqlParse } from 'graphql' export default function ({ types: t }: { types: typeof types }): PluginObj { let nodesToRemove: any[] = [] @@ -49,7 +52,6 @@ export default function ({ types: t }: { types: typeof types }): PluginObj { // 4. The Cell has a operation name for the QUERY export. const d = p.node.declaration - const filename = state.file.opts.filename let mockFunction @@ -107,24 +109,29 @@ export default function ({ types: t }: { types: typeof types }): PluginObj { } // Find the model of the Cell that is in the same directory. - const dir = URL_file(path.dirname(state.file.opts.filename)) - const project = getProject(getBaseDirFromFile(filename)) - const cell = project.cells.find((path: { uri: string }) => { - return path.uri.startsWith(dir) + const dirname = path.dirname(state.file.opts.filename) + const cellName = path.basename(dirname) + + const [cellPath] = fg.sync(`${cellName}.{js,jsx,ts,tsx}`, { + cwd: dirname, + absolute: true, + ignore: ['node_modules'], }) - if (!cell || !cell?.filePath) { + if (!cellPath) { return } - if (!cell.queryOperationName) { + const cellMetadata = getCellMetadata(cellPath) + + if (cellMetadata.hasDefaultExport || !cellMetadata.hasQueryExport) { return } // mockGraphQLQuery(, ) const mockGraphQLCall = t.callExpression( t.identifier('mockGraphQLQuery'), - [t.stringLiteral(cell.queryOperationName), mockFunction] + [t.stringLiteral(cellMetadata.operationName), mockFunction] ) // Delete original "export const standard" @@ -132,7 +139,7 @@ export default function ({ types: t }: { types: typeof types }): PluginObj { // + import { afterQuery } from './${cellFileName}' // + export const standard = () => afterQuery(...) - if (cell.exportedSymbols.has('afterQuery')) { + if (cellMetadata.hasAfterQueryExport) { const importAfterQuery = t.importDeclaration( [ t.importSpecifier( @@ -140,7 +147,7 @@ export default function ({ types: t }: { types: typeof types }): PluginObj { t.identifier('afterQuery') ), ], - t.stringLiteral(`./${path.basename(cell.filePath)}`) + t.stringLiteral(`./${path.basename(cellPath)}`) ) nodesToInsert = [ @@ -166,3 +173,113 @@ export default function ({ types: t }: { types: typeof types }): PluginObj { }, } } + +export const getCellMetadata = (p: string) => { + const ast = getCellAst(p) + + let hasDefaultExport = false + const namedExports: NamedExports[] = [] + let operation + + traverse(ast, { + ExportDefaultDeclaration() { + hasDefaultExport = true + return + }, + ExportNamedDeclaration(path) { + // Re-exports from other modules + // Eg: export { a, b } from './module' + const specifiers = path.node?.specifiers + + if (specifiers.length) { + for (const s of specifiers) { + const id = s.exported as types.Identifier + namedExports.push({ + name: id.name, + type: 're-export', + }) + } + return + } + + const declaration = path.node.declaration + + if (!declaration) { + return + } + + if (declaration.type === 'VariableDeclaration') { + const id = declaration.declarations[0].id as types.Identifier + + namedExports.push({ + name: id.name as string, + type: 'variable', + }) + } else if (declaration.type === 'FunctionDeclaration') { + namedExports.push({ + name: declaration?.id?.name as string, + type: 'function', + }) + } else if (declaration.type === 'ClassDeclaration') { + namedExports.push({ + name: declaration?.id?.name, + type: 'class', + }) + } + }, + TaggedTemplateExpression(path) { + // @ts-expect-error wip + if (path.parent?.id?.name !== 'QUERY') { + return + } + + operation = path.node.quasi.quasis[0].value.raw + }, + }) + + const hasQueryExport = namedExports.find(({ name }) => name === 'QUERY') + const hasAfterQueryExport = namedExports.find( + ({ name }) => name === 'afterQuery' + ) + + let operationName = '' + + if (operation) { + const document = graphqlParse(operation) + + for (const definition of document.definitions) { + if (definition.kind === 'OperationDefinition' && definition.name?.value) { + operationName = definition.name.value + } + } + } + + return { + hasDefaultExport, + namedExports, + hasQueryExport, + hasAfterQueryExport, + operationName, + } +} + +function getCellAst(filePath: string): types.Node { + const code = fs.readFileSync(filePath, 'utf-8') + const plugins = ['typescript', 'jsx'].filter(Boolean) as ParserPlugin[] + + try { + return babelParse(code, { + sourceType: 'module', + plugins, + }) + } catch (e: any) { + console.error(`Error parsing: ${filePath}`) + console.error(e) + throw new Error(e?.message) // we throw, so typescript doesn't complain about returning + } +} + +interface NamedExports { + name: string + type: 're-export' | 'variable' | 'function' | 'class' +} diff --git a/packages/babel-config/tsconfig.json b/packages/babel-config/tsconfig.json index 0055a57611e2..8365ab8e0cee 100644 --- a/packages/babel-config/tsconfig.json +++ b/packages/babel-config/tsconfig.json @@ -8,7 +8,6 @@ }, "include": ["src"], "references": [ - { "path": "../project-config" }, - { "path": "../structure" } + { "path": "../project-config" } ] } diff --git a/packages/cli-packages/dataMigrate/package.json b/packages/cli-packages/dataMigrate/package.json index d08c3f6ac021..24c7b622b258 100644 --- a/packages/cli-packages/dataMigrate/package.json +++ b/packages/cli-packages/dataMigrate/package.json @@ -25,9 +25,7 @@ }, "dependencies": { "@redwoodjs/babel-config": "6.1.0", - "@redwoodjs/cli-helpers": "6.1.0", "@redwoodjs/project-config": "6.1.0", - "@redwoodjs/telemetry": "6.1.0", "chalk": "4.1.2", "dotenv-defaults": "5.0.2", "execa": "5.1.1", diff --git a/packages/cli-packages/dataMigrate/src/__tests__/install.test.ts b/packages/cli-packages/dataMigrate/src/__tests__/install.test.ts index ba5266e83715..e7eb5165d42c 100644 --- a/packages/cli-packages/dataMigrate/src/__tests__/install.test.ts +++ b/packages/cli-packages/dataMigrate/src/__tests__/install.test.ts @@ -1,9 +1,6 @@ -import { recordTelemetryAttributes } from '@redwoodjs/cli-helpers' - import * as installCommand from '../commands/install' import { handler as dataMigrateInstallHandler } from '../commands/installHandler.js' -jest.mock('@redwoodjs/cli-helpers') jest.mock( '../commands/installHandler.js', () => ({ @@ -36,14 +33,6 @@ describe('install', () => { ) }) - it('`handler` records telemetry attributes', async () => { - await installCommand.handler() - - expect(recordTelemetryAttributes).toHaveBeenCalledWith({ - command: 'data-migrate install', - }) - }) - it('`handler` proxies to `./installHandler.js`', async () => { await installCommand.handler() expect(dataMigrateInstallHandler).toHaveBeenCalled() diff --git a/packages/cli-packages/dataMigrate/src/__tests__/up.test.ts b/packages/cli-packages/dataMigrate/src/__tests__/up.test.ts index bc986de63c8c..06ad05baa883 100644 --- a/packages/cli-packages/dataMigrate/src/__tests__/up.test.ts +++ b/packages/cli-packages/dataMigrate/src/__tests__/up.test.ts @@ -1,14 +1,12 @@ import { vol } from 'memfs' import yargs from 'yargs/yargs' -import { recordTelemetryAttributes } from '@redwoodjs/cli-helpers' import { getPaths } from '@redwoodjs/project-config' import * as upCommand from '../commands/up' import { handler as dataMigrateUpHandler } from '../commands/upHandler.js' jest.mock('fs', () => require('memfs').fs) -jest.mock('@redwoodjs/cli-helpers') jest.mock( '../commands/upHandler.js', () => ({ @@ -47,14 +45,6 @@ describe('up', () => { expect(argv).toHaveProperty('dist-path', getPaths().api.dist) }) - it('`handler` records telemetry attributes', async () => { - await upCommand.handler({}) - - expect(recordTelemetryAttributes).toHaveBeenCalledWith({ - command: 'data-migrate up', - }) - }) - it('`handler` proxies to `./upHandler.js`', async () => { await upCommand.handler({}) expect(dataMigrateUpHandler).toHaveBeenCalled() diff --git a/packages/cli-packages/dataMigrate/src/commands/install.ts b/packages/cli-packages/dataMigrate/src/commands/install.ts index 13e47e07bf61..001245a3406d 100644 --- a/packages/cli-packages/dataMigrate/src/commands/install.ts +++ b/packages/cli-packages/dataMigrate/src/commands/install.ts @@ -1,8 +1,6 @@ import terminalLink from 'terminal-link' import type { Argv } from 'yargs' -import { recordTelemetryAttributes } from '@redwoodjs/cli-helpers' - export const command = 'install' export const description = 'Add the RW_DataMigration model to your schema' @@ -16,10 +14,6 @@ export function builder(yargs: Argv): Argv { } export async function handler(): Promise { - recordTelemetryAttributes({ - command: 'data-migrate install', - }) - const { handler: dataMigrateInstallHandler } = await import( './installHandler.js' ) diff --git a/packages/cli-packages/dataMigrate/src/commands/installHandler.ts b/packages/cli-packages/dataMigrate/src/commands/installHandler.ts index 165eece0abc6..5bdda934716a 100644 --- a/packages/cli-packages/dataMigrate/src/commands/installHandler.ts +++ b/packages/cli-packages/dataMigrate/src/commands/installHandler.ts @@ -5,7 +5,6 @@ import fs from 'fs-extra' import { Listr } from 'listr2' import { getPaths } from '@redwoodjs/project-config' -import { errorTelemetry } from '@redwoodjs/telemetry' import c from '../lib/colors' @@ -59,7 +58,6 @@ export async function handler() { } catch (e) { process.exitCode = 1 console.error(c.error((e as Error).message)) - errorTelemetry(process.argv, (e as Error).message) } } diff --git a/packages/cli-packages/dataMigrate/src/commands/up.ts b/packages/cli-packages/dataMigrate/src/commands/up.ts index 5f966fd53c1f..efe1a5f68a3f 100644 --- a/packages/cli-packages/dataMigrate/src/commands/up.ts +++ b/packages/cli-packages/dataMigrate/src/commands/up.ts @@ -1,7 +1,6 @@ import terminalLink from 'terminal-link' import type { Argv } from 'yargs' -import { recordTelemetryAttributes } from '@redwoodjs/cli-helpers' import { getPaths } from '@redwoodjs/project-config' import { DataMigrateUpOptions } from '../types' @@ -33,11 +32,6 @@ export function builder(yargs: Argv): Argv { } export async function handler(options: DataMigrateUpOptions): Promise { - recordTelemetryAttributes({ - command: 'data-migrate up', - dbFromDist: options.importDbClientFromDist, - }) - const { handler: dataMigrateUpHandler } = await import('./upHandler.js') await dataMigrateUpHandler(options) } diff --git a/packages/cli-packages/dataMigrate/src/commands/upHandler.ts b/packages/cli-packages/dataMigrate/src/commands/upHandler.ts index 1d2da7dc50dd..732648ec4257 100644 --- a/packages/cli-packages/dataMigrate/src/commands/upHandler.ts +++ b/packages/cli-packages/dataMigrate/src/commands/upHandler.ts @@ -6,7 +6,6 @@ import { Listr } from 'listr2' import { registerApiSideBabelHook } from '@redwoodjs/babel-config' import { getPaths } from '@redwoodjs/project-config' -import { errorTelemetry } from '@redwoodjs/telemetry' import c from '../lib/colors' import type { DataMigrateUpOptions, DataMigration } from '../types' @@ -120,8 +119,6 @@ export async function handler({ console.log() reportDataMigrations(counters) console.log() - - errorTelemetry(process.argv, (e as Error).message) } } diff --git a/packages/cli-packages/dataMigrate/tsconfig.json b/packages/cli-packages/dataMigrate/tsconfig.json index 6a58783dcba6..24d99065db57 100644 --- a/packages/cli-packages/dataMigrate/tsconfig.json +++ b/packages/cli-packages/dataMigrate/tsconfig.json @@ -4,13 +4,11 @@ "baseUrl": ".", "rootDir": "src", "tsBuildInfoFile": "dist/tsconfig.tsbuildinfo", - "outDir": "dist", + "outDir": "dist" }, "include": ["src"], "references": [ { "path": "../../babel-config" }, - { "path": "../../cli-helpers" }, - { "path": "../../project-config" }, - { "path": "../../telemetry" }, + { "path": "../../project-config" } ] } diff --git a/yarn.lock b/yarn.lock index 58f9ce63e47d..008731613b5e 100644 --- a/yarn.lock +++ b/yarn.lock @@ -7868,6 +7868,7 @@ __metadata: resolution: "@redwoodjs/babel-config@workspace:packages/babel-config" dependencies: "@babel/core": 7.22.11 + "@babel/parser": 7.22.13 "@babel/plugin-transform-class-properties": 7.22.5 "@babel/plugin-transform-private-methods": 7.22.5 "@babel/plugin-transform-private-property-in-object": 7.22.11 @@ -7877,8 +7878,8 @@ __metadata: "@babel/preset-typescript": 7.22.11 "@babel/register": 7.22.5 "@babel/runtime-corejs3": 7.22.11 + "@babel/traverse": 7.22.11 "@redwoodjs/project-config": 6.1.0 - "@redwoodjs/structure": 6.1.0 "@types/babel-plugin-tester": 9.0.5 "@types/babel__core": 7.20.1 babel-plugin-auto-import: 1.1.0 @@ -7888,6 +7889,7 @@ __metadata: core-js: 3.32.0 esbuild: 0.18.19 fast-glob: 3.3.1 + graphql: 16.8.0 jest: 29.6.4 typescript: 5.1.6 languageName: unknown @@ -7899,9 +7901,7 @@ __metadata: dependencies: "@prisma/client": 5.2.0 "@redwoodjs/babel-config": 6.1.0 - "@redwoodjs/cli-helpers": 6.1.0 "@redwoodjs/project-config": 6.1.0 - "@redwoodjs/telemetry": 6.1.0 "@types/fs-extra": 11.0.1 "@types/yargs": 17.0.24 chalk: 4.1.2