Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 1 addition & 11 deletions packages/structure/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,17 +17,7 @@ export function getProject(projectRoot: string, host = new DefaultHost()) {
export async function printDiagnostics(
projectRoot: string,
opts?: { getSeverityLabel?: GetSeverityLabelFunction },
) {
const project = getProject(projectRoot)
const formatOpts = { cwd: projectRoot, ...opts }
try {
let warnings = 0
let errors = 0
for (const d of await project.collectDiagnostics()) {
const str = ExtendedDiagnostic_format(d, formatOpts)
console.log(`\n${str}`)
// counts number of warnings (2) and errors (1) encountered
if (d.diagnostic.severity === 2) {
) {fdf== 2) {

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The code block is malformed, likely due to accidental deletion or corruption. This will cause a syntax error.

Suggestion:

  const project = getProject(projectRoot);
  const formatOpts = { cwd: projectRoot, ...opts };
  try {
    let warnings = 0;
    let errors = 0;
    for (const d of await project.collectDiagnostics()) {
      const str = ExtendedDiagnostic_format(d, formatOpts);
      console.log(`\n${str}`);
      // counts number of warnings (2) and errors (1) encountered
      if (d.diagnostic.severity === 2) {
        warnings++;
      }
      if (d.diagnostic.severity === 1) {
        errors++;
      }
    }

warnings++
}
if (d.diagnostic.severity === 1) {
Expand Down
111 changes: 0 additions & 111 deletions packages/structure/src/model/RWCell.ts
Original file line number Diff line number Diff line change
@@ -1,111 +0,0 @@
import { Kind, parse as parseGraphQL } from 'graphql'
import * as tsm from 'ts-morph'
import { DiagnosticSeverity } from 'vscode-languageserver-types'

import { lazy } from '../x/decorators'
import { err, Range_fromNode } from '../x/vscode-languageserver-types'

import { RWComponent } from './RWComponent'

export class RWCell extends RWComponent {
/**
* A "Cell" is a component that ends in `Cell.{js, jsx, tsx}`, has no
* default export AND exports `QUERY`
**/
@lazy() get isCell() {
return !this.hasDefaultExport && this.exportedSymbols.has('QUERY')
}

// TODO: Move to RWCellQuery
@lazy() get queryStringNode() {
const i = this.sf.getVariableDeclaration('QUERY')?.getInitializer()
if (!i) {
return undefined
}
// TODO: do we allow other kinds of strings? or just tagged literals?
if (tsm.Node.isTaggedTemplateExpression(i)) {
const t = i.getTemplate()
if (tsm.Node.isNoSubstitutionTemplateLiteral(t)) {
return t
}
}
return undefined
}

// TODO: Move to RWCellQuery
@lazy() get queryString(): string | undefined {
return this.queryStringNode?.getLiteralText()
}

// TODO: Move to RWCellQuery
@lazy() get queryAst() {
const qs = this.queryString
if (!qs) {
return undefined
}

try {
return parseGraphQL(qs)
} catch (e) {
console.error("Can't parse the graphql query string in", this.filePath)
console.error(e)
return undefined
}
}

// TODO: Move to RWCellQuery
@lazy() get queryOperationName(): string | undefined {
const ast = this.queryAst
if (!ast) {
return undefined
}
for (const def of ast.definitions) {
if (def.kind == Kind.OPERATION_DEFINITION) {
return def?.name?.value
}
}
return undefined
}

*diagnostics() {
// check that QUERY and Success are exported
if (!this.exportedSymbols.has('QUERY')) {
yield err(
this.uri,
'Every Cell MUST export a QUERY variable (GraphQL query string)',
)
}

try {
if (!this.queryOperationName) {
yield {
uri: this.uri,
diagnostic: {
range: Range_fromNode(this.queryStringNode!),
message: 'We recommend that you name your query operation',
severity: DiagnosticSeverity.Warning,
},
}
}
} catch (e: any) {
// Maybe the AST has a syntax error...
yield {
uri: this.uri,
diagnostic: {
// TODO: Try to figure out if we can point directly to the syntax error.
range: Range_fromNode(this.sf.getVariableDeclaration('QUERY')!),
message: e.message,
severity: DiagnosticSeverity.Error,
},
}
}

// TODO: check that exported QUERY is semantically valid GraphQL (fields exist)
if (!this.exportedSymbols.has('Success')) {
yield err(
this.uri,
'Every Cell MUST export a Success variable (React Component)',
)
}
}
}
8 changes: 1 addition & 7 deletions packages/structure/src/model/RWLayout.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,4 @@ import type { RWProject } from './RWProject'
* layouts live in the src/layouts folder
*/
export class RWLayout extends FileNode {
constructor(
public filePath: string,
public parent: RWProject,
) {
super()
}
}
const

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The line 'const' is incomplete and causes a syntax error. It should be removed or completed with a valid declaration.

46 changes: 12 additions & 34 deletions packages/structure/src/model/RWProject.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,7 @@
import { join } from 'path'

import type { DMMF } from '@prisma/generator-helper'
import { getDMMF, getSchema } from '@prisma/internals'

import { getPaths, processPagesDir } from '@redwoodjs/project-config'

import type { Host } from '../hosts'
import { BaseNode } from '../ide'
import { lazy, memo } from '../x/decorators'
Expand All @@ -14,7 +11,6 @@ import {
isLayoutFileName,
} from '../x/path'
import { URL_file } from '../x/URL'

import { RWCell } from './RWCell'
import { RWComponent } from './RWComponent'
import { RWEnvHelper } from './RWEnvHelper'
Expand All @@ -41,6 +37,7 @@ export class RWProject extends BaseNode {
constructor(public opts: RWProjectOptions) {
super()
}

parent = undefined

get host() {
Expand Down Expand Up @@ -68,76 +65,66 @@ export class RWProject extends BaseNode {
]
}

/**
* Path constants that are relevant to a Redwood project.
*/
@lazy() get pathHelper() {
return getPaths(this.projectRoot)
}
/**
* Checks for the presence of a tsconfig.json at the root.
*/

@lazy() get isTypeScriptProject(): boolean {
return (
this.host.existsSync(join(this.pathHelper.web.base, 'tsconfig.json')) ||
this.host.existsSync(join(this.pathHelper.api.base, 'tsconfig.json'))
)
}
// TODO: do we move this to a separate node? (ex: RWDatabase)

@memo() async prismaDMMF(): Promise<DMMF.Document | undefined> {
try {
const datamodel = await getSchema(this.pathHelper.api.dbSchema)
// consider case where dmmf doesn't exist (or fails to parse)
return await getDMMF({ datamodel })
} catch {
return undefined
}
}

@memo() async prismaDMMFModelNames() {
const dmmf = await this.prismaDMMF()
if (!dmmf) {
return []
}
return dmmf.datamodel.models.map((m) => m.name)
return dmmf ? dmmf.datamodel.models.map((m) => m.name) : []
}

@lazy() get redwoodTOML(): RWTOML {
return new RWTOML(join(this.projectRoot, 'redwood.toml'), this)
}

@lazy() private get processPagesDir() {
try {
return processPagesDir(this.pathHelper.web.pages)
} catch {
return []
}
}

@lazy() get pages(): RWPage[] {
return this.processPagesDir.map(
(p) => new RWPage(p.constName, p.path, this),
)
return this.processPagesDir.map((p) => new RWPage(p.constName, p.path, this))
}

@lazy() get router() {
return this.getRouter()
}

getRouter = () => {
return new RWRouter(this.pathHelper.web.routes, this)
}

// TODO: move to path helper
servicesFilePath(name: string) {
// name = blog,posts
const ext = this.isTypeScriptProject ? '.ts' : '.js'
return join(this.pathHelper.api.services, name, name + ext)
}

// TODO: move to path helper
@lazy() get defaultNotFoundPageFilePath() {
const ext = this.isTypeScriptProject ? '.tsx' : '.jsx'
return join(this.pathHelper.web.pages, 'NotFoundPage', 'NotFoundPage' + ext)
}

@lazy() get services() {
// TODO: what is the official logic?
// TODO: Support both `/services/todos/todos.js` AND `/services/todos.js`
return this.host
.globSync(this.pathHelper.api.services + allFilesGlob)
.filter(followsDirNameConvention)
Expand All @@ -151,7 +138,6 @@ export class RWProject extends BaseNode {
}

@lazy() get layouts(): RWLayout[] {
// TODO: what is the official logic?
return this.host
.globSync(this.pathHelper.web.layouts + allFilesGlob)
.filter(followsDirNameConvention)
Expand All @@ -160,7 +146,6 @@ export class RWProject extends BaseNode {
}

@lazy() get functions(): RWFunction[] {
// TODO: what is the official logic?
return this.host
.globSync(this.pathHelper.api.functions + allFilesGlob)
.map((x) => new RWFunction(x, this))
Expand All @@ -172,9 +157,7 @@ export class RWProject extends BaseNode {
.map((file) => {
if (isCellFileName(file)) {
const possibleCell = new RWCell(file, this)
return possibleCell.isCell
? possibleCell
: new RWComponent(file, this)
return possibleCell.isCell ? possibleCell : new RWComponent(file, this)
}
return new RWComponent(file, this)
})
Expand All @@ -184,15 +167,10 @@ export class RWProject extends BaseNode {
return ['web', 'api']
}

// TODO: Wrap these in a real model.
@lazy() get mocks() {
return this.host.globSync(this.pathHelper.web.base + '/**/*.mock.{js,ts}')
}

/**
* A "Cell" is a component that ends in `Cell.{js, jsx, tsx}`, but does not
* have a default export AND does not export `QUERY`
**/
@lazy() get cells(): RWCell[] {
return this.host
.globSync(this.pathHelper.web.base + '/**/*Cell.{js,jsx,tsx}')
Expand Down
12 changes: 0 additions & 12 deletions packages/structure/src/model/RWRoute.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,19 +6,7 @@ import { Range } from 'vscode-languageserver-types'

import { RWError } from '../errors'
import type { Decoration, Definition, DocumentLinkX, HoverX } from '../ide'
import { BaseNode } from '../ide'
import { validateRoutePath } from '../util'
import { lazy } from '../x/decorators'
import {
err,
LocationLike_toHashLink,
LocationLike_toLocation,
Location_fromFilePath,
Location_fromNode,
Position_translate,
Range_fromNode,
} from '../x/vscode-languageserver-types'

import type { RWRouter } from './RWRouter'
import { advanced_path_parser } from './util/advanced_path_parser'

Expand Down
10 changes: 1 addition & 9 deletions packages/structure/src/model/RWRouter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,15 +14,7 @@ import { iter } from '../x/Array'
import { lazy, memo } from '../x/decorators'
import { URL_file } from '../x/URL'
import type { ExtendedDiagnostic } from '../x/vscode-languageserver-types'
import {
err,
LocationLike_toLocation,
Location_fromNode,
} from '../x/vscode-languageserver-types'

import type { RWProject } from './RWProject'
import { RWRoute } from './RWRoute'

imp

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The import statement on this line is incomplete and seems to be a mistake. It should be removed or completed.

/**
* one per Routes.js
*/
Expand Down
1 change: 0 additions & 1 deletion packages/structure/src/model/index.ts
Original file line number Diff line number Diff line change
@@ -1 +0,0 @@
export { RWProject } from './RWProject'
Loading