Skip to content

Conversation

@nicomiguelino
Copy link
Contributor

@nicomiguelino nicomiguelino commented Dec 30, 2025

PR Type

Enhancement, Documentation


Description

  • Add centralized ESLint config and CLI

  • Introduce edge-apps-scripts lint command

  • Update apps to use shared lint script

  • Improve tests global handling and types


Diagram Walkthrough

flowchart LR
  A["edge-apps-library"] -- "adds eslint.config.ts" --> B["shared ESLint config"]
  A -- "adds scripts/cli.ts" --> C["edge-apps-scripts CLI"]
  A -- "adds bin entry" --> D["edge-apps-scripts binary"]
  C -- "runs eslint with shared config" --> B
  E["menu-board"] -- "use shared lint" --> D
  F["qr-code"] -- "use shared lint" --> D
  A -- "docs: README updates" --> G["CLI usage & linking"]
  A -- "test setup adjustments" --> H["stable global usage"]
Loading

File Walkthrough

Relevant files
Enhancement
7 files
edge-apps-scripts.ts
Add executable entry for edge-apps-scripts CLI                     
+9/-0     
eslint.config.ts
Provide shared ESLint base configuration                                 
+9/-0     
cli.ts
Implement CLI dispatcher with lint command                             
+86/-0   
utils.ts
Narrow getSetting type for menu items                                       
+3/-1     
package.json
Expose CLI binary and add ESLint deps                                       
+13/-3   
package.json
Use edge-apps-scripts for linting                                               
+1/-1     
package.json
Use edge-apps-scripts for linting                                               
+1/-1     
Tests
3 files
mock.test.ts
Use typed global reference in tests                                           
+11/-8   
mock.ts
Switch to typed global for screenly mock                                 
+4/-2     
setup.ts
Refine global window typing in test setup                               
+1/-4     
Documentation
1 files
README.md
Document local linking and new CLI usage                                 
+53/-0   

@github-actions
Copy link

github-actions bot commented Dec 30, 2025

PR Reviewer Guide 🔍

(Review updated until commit 49eef5f)

Here are some key observations to aid the review process:

⏱️ Estimated effort to review: 2 🔵🔵⚪⚪⚪
🧪 PR contains tests
🔒 No security concerns identified
⚡ Recommended focus areas for review

Cross-platform Path

Using node_modules/.bin/eslint and execSync with a quoted string may fail on Windows (needs .cmd) or if ESLint isn't installed at library root. Consider resolving the executable via npx or programmatic API or handling .cmd/.mjs cases and missing binary errors.

  const eslintBin = path.resolve(libraryRoot, 'node_modules', '.bin', 'eslint')

  // Build eslint command
  const eslintArgs = [
    '--config',
    path.resolve(libraryRoot, 'eslint.config.ts'),
    '.',
    ...args,
  ]

  execSync(`"${eslintBin}" ${eslintArgs.map((arg) => `"${arg}"`).join(' ')}`, {
    stdio: 'inherit',
    cwd: callerDir,
  })
} catch {
Config Composition

defineConfig is called with multiple separate configs; newer flat config typically expects an array. Verify this invocation actually merges configs as intended, or change to defineConfig([...]) to avoid misconfiguration at runtime.

export default defineConfig(
  eslint.configs.recommended,
  tseslint.configs.recommended,
  globalIgnores(['dist/', 'node_modules/', 'static/js/', 'build/']),
)
Bin TypeScript

The bin points to a .ts file with a Bun shebang. Ensure package consumers running via Node can execute it (transpile to dist/bin or document Bun requirement). Otherwise CLI may break outside Bun.

"bin": {
  "edge-apps-scripts": "./bin/edge-apps-scripts.ts"
},

@github-actions
Copy link

github-actions bot commented Dec 30, 2025

PR Code Suggestions ✨

Latest suggestions up to 49eef5f
Explore these optional code suggestions:

CategorySuggestion                                                                                                                                    Impact
Possible issue
Fix invalid ESLint config shape

The defineConfig helper expects a single flat config object or an array; passing
multiple arguments will be ignored or misinterpreted. Wrap the presets into an array
and include ignores as a separate config to ensure ESLint applies all settings
correctly.

edge-apps/edge-apps-library/eslint.config.ts [5-9]

-export default defineConfig(
-  eslint.configs.recommended,
-  tseslint.configs.recommended,
-  globalIgnores(['dist/', 'node_modules/', 'static/js/', 'build/']),
-)
+export default defineConfig([
+  ...eslint.configs.recommended,
+  ...tseslint.configs.recommended,
+  {
+    ignores: ['dist/', 'node_modules/', 'static/js/', 'build/'],
+  },
+])
Suggestion importance[1-10]: 8

__

Why: The current usage passes multiple args to defineConfig, which is incorrect for flat config; wrapping presets into an array and adding ignores as a separate config ensures ESLint applies settings properly and prevents misconfiguration.

Medium
Robust ESLint resolution and exit code

Avoid hard-coding the node_modules/.bin/eslint path, as it breaks in PnP/linked
environments or when using different package managers. Resolve the ESLint CLI via
Node's resolution and execute it directly, or fall back to npx if resolution fails.
Also propagate the original exit code for better CI diagnostics.

edge-apps/edge-apps-library/scripts/cli.ts [21-44]

 async function lintCommand(args: string[]) {
   try {
-    // Get the caller's directory (the app that invoked this script)
     const callerDir = process.cwd()
-    
-    // Get path to eslint binary in the library's node_modules
-    const eslintBin = path.resolve(libraryRoot, 'node_modules', '.bin', 'eslint')
 
-    // Build eslint command
+    // Try to resolve eslint CLI entry
+    let eslintCmd: string
+    try {
+      // eslint >=9 exposes bin via package "eslint/bin/eslint.js"
+      // Resolve relative to this library root to ensure consistent version
+      const eslintEntry = require.resolve('eslint/bin/eslint.js', { paths: [libraryRoot] })
+      eslintCmd = `"${process.execPath}" "${eslintEntry}"`
+    } catch {
+      // Fallback to npx if resolution fails (linked/pnp scenarios)
+      eslintCmd = 'npx --yes eslint'
+    }
+
     const eslintArgs = [
       '--config',
       path.resolve(libraryRoot, 'eslint.config.ts'),
       '.',
       ...args,
-    ]
+    ].map((arg) => `"${arg}"`).join(' ')
 
-    execSync(`"${eslintBin}" ${eslintArgs.map((arg) => `"${arg}"`).join(' ')}`, {
+    execSync(`${eslintCmd} ${eslintArgs}`, {
       stdio: 'inherit',
       cwd: callerDir,
     })
-  } catch {
-    process.exit(1)
+  } catch (err: any) {
+    // Propagate ESLint's exit code when available
+    const code = typeof err?.status === 'number' ? err.status : 1
+    process.exit(code)
   }
 }
Suggestion importance[1-10]: 7

__

Why: Avoiding a hard-coded path to the ESLint binary improves portability across package managers and linked workspaces, and propagating the exit code aids CI. The change is accurate and contextually relevant, though not critical.

Medium
General
Sync DOM globals for tests

Assigning global.window without syncing common window globals can cause tests to
fail due to missing properties like HTMLElement or requestAnimationFrame. Mirror key
DOM constructors onto the global to align the environment with browser expectations.

edge-apps/edge-apps-library/src/test/setup.ts [11-13]

 global.document = dom.window.document
 global.window = dom.window as unknown as Window & typeof globalThis
 global.navigator = dom.window.navigator
+// Sync common window globals to Node global for tests that expect them
+const propsToCopy = ['HTMLElement', 'Node', 'CustomEvent', 'Event', 'KeyboardEvent', 'MouseEvent', 'requestAnimationFrame', 'cancelAnimationFrame']
+for (const key of propsToCopy) {
+  // @ts-expect-error dynamic assignment for test env
+  if (global[key] === undefined && key in dom.window) {
+    // @ts-expect-error dynamic read from window
+    global[key] = (dom.window as any)[key]
+  }
+}
Suggestion importance[1-10]: 5

__

Why: Copying common DOM globals to Node's global can reduce test flakiness in browser-like code; it's a reasonable enhancement but not essential and may be environment-specific.

Low

Previous suggestions

Suggestions up to commit 1626df3
CategorySuggestion                                                                                                                                    Impact
Possible issue
Fix invalid config shape

defineConfig expects a single configuration object or an array, not multiple
arguments. Wrap the configs with a spread into a single object to avoid
runtime/config resolution errors. This fixes ESLint failing to load the config.

edge-apps/qr-code/eslint.config.ts [5-8]

-export default defineConfig(
-  eslint.configs.recommended,
-  tseslint.configs.recommended,
-);
+export default defineConfig({
+  ...eslint.configs.recommended,
+  ...tseslint.configs.recommended,
+});
Suggestion importance[1-10]: 8

__

Why: The current call passes multiple arguments to defineConfig, which expects a single config object/array; merging the recommended configs into one object prevents ESLint config loading errors and aligns with API expectations. This is a functional fix with high impact on tooling correctness.

Medium

- Fix linting issues in the `menu-board` app
- Configure ESLint configs in boths apps to ignore certain paths
- Move shared eslint.config.ts to edge-apps-library
- Create edge-apps-scripts CLI wrapper around ESLint and build tools
- Update apps to use edge-apps-scripts lint instead of direct eslint
- Remove duplicate ESLint dependencies from individual apps
- Update package.json to expose CLI binary and include scripts/bin in files
- Add @screenly/edge-apps bin entry pointing to edge-apps-scripts.ts
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

This PR introduces shared ESLint tooling infrastructure to the edge-apps-library, enabling consistent linting across edge apps via a new CLI tool. It also includes a type signature improvement in the menu-board app.

Key changes:

  • Creates a new edge-apps-scripts CLI tool with lint command support
  • Adds ESLint 9.x flat config with TypeScript support to edge-apps-library
  • Updates qr-code and menu-board apps to use the new shared linting tooling

Reviewed changes

Copilot reviewed 7 out of 9 changed files in this pull request and generated 8 comments.

Show a summary per file
File Description
edge-apps/edge-apps-library/bin/edge-apps-scripts.ts Entry point for the new CLI tool
edge-apps/edge-apps-library/scripts/cli.ts CLI command dispatcher with lint and format (stub) commands
edge-apps/edge-apps-library/eslint.config.ts Shared ESLint flat configuration with TypeScript support
edge-apps/edge-apps-library/package.json Adds ESLint dependencies, bin entry, and includes new files for distribution
edge-apps/edge-apps-library/README.md Documents bun link workflow for local development
edge-apps/qr-code/package.json Updates lint script to use edge-apps-scripts CLI
edge-apps/menu-board/package.json Updates lint script to use edge-apps-scripts CLI
edge-apps/menu-board/src/utils.ts Improves type specificity of getSetting parameter from any to string | undefined
edge-apps/edge-apps-library/bun.lock Lockfile updates for new ESLint and tooling dependencies

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

- Use fileURLToPath to derive __dirname from import.meta.url
- Define libraryRoot variable for consistent path resolution
- Replace path.dirname(__dirname) with libraryRoot variable
- Improves robustness when package is installed as dependency
@nicomiguelino nicomiguelino marked this pull request as ready for review December 30, 2025 21:23
@github-actions
Copy link

Persistent review updated to latest commit 49eef5f

@nicomiguelino nicomiguelino merged commit 0ad6fcd into master Dec 31, 2025
7 checks passed
@nicomiguelino nicomiguelino deleted the nicomiguelino/add-eslint-for-new-apps branch December 31, 2025 04:05
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants