Skip to content

Commit

Permalink
3.7.2 (#532)
Browse files Browse the repository at this point in the history
  • Loading branch information
JensAstrup authored Nov 30, 2024
2 parents 2286f7b + 95aeaac commit 3b0fbb9
Show file tree
Hide file tree
Showing 25 changed files with 519 additions and 320 deletions.
2 changes: 1 addition & 1 deletion .env
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
VERSION=3.7.1
VERSION=3.7.2
CHANGELOG_VERSION=3.0.1
GOOGLE_MEASUREMENT_ID="G-SN6JNMXND2"
PROXY_URL=https://monkfish-app-4bylm.ondigitalocean.app
Expand Down
53 changes: 0 additions & 53 deletions .eslintrc.cjs

This file was deleted.

1 change: 1 addition & 0 deletions .github/FUNDING.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
github: [JensAstrup]
151 changes: 151 additions & 0 deletions eslint.config.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,151 @@
import path from 'node:path'
import { fileURLToPath } from 'node:url'

import { fixupConfigRules, fixupPluginRules } from '@eslint/compat'
import { FlatCompat } from '@eslint/eslintrc'
import js from '@eslint/js'
import stylistic from '@stylistic/eslint-plugin'
import typescriptEslint from '@typescript-eslint/eslint-plugin'
import tsParser from '@typescript-eslint/parser'
import _import from 'eslint-plugin-import'
import jest from 'eslint-plugin-jest'
import perfectionist from 'eslint-plugin-perfectionist'
import yenz from 'eslint-plugin-yenz'
import globals from 'globals'


const __filename = fileURLToPath(import.meta.url)
const __dirname = path.dirname(__filename)
const compat = new FlatCompat({
baseDirectory: __dirname,
recommendedConfig: js.configs.recommended,
allConfig: js.configs.all
})

export default [...fixupConfigRules(compat.extends(
'eslint:recommended',
'plugin:@typescript-eslint/recommended',
'plugin:@typescript-eslint/recommended-type-checked',
'plugin:import/warnings',
'plugin:import/typescript',
'plugin:jest/recommended',
'plugin:@stylistic/recommended-extends',
)), {
plugins: {
'@typescript-eslint': fixupPluginRules(typescriptEslint),
'@stylistic': fixupPluginRules(stylistic),
'perfectionist': fixupPluginRules(perfectionist),
'import': fixupPluginRules(_import),
yenz,
'jest': fixupPluginRules(jest),
},

languageOptions: {
globals: {
...globals.jest,
...globals.node,
...globals.browser,
...globals.webextensions,
},

parser: tsParser,
ecmaVersion: 2020,
sourceType: 'module',

parserOptions: {
project: './tsconfig.json',
},
},

rules: {
'yenz/type-ordering': 'error',
'yenz/no-loops': 'error',
'dot-notation': 'error',
'indent': ['error', 2],
'linebreak-style': ['error', 'unix'],
'no-case-declarations': 'off',

'no-console': ['error', {
allow: ['error', 'warn'],
}],

'no-magic-numbers': ['error', {
ignoreArrayIndexes: true,
ignore: [-1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10],
}],

'no-use-before-define': 'off',
'quotes': ['error', 'single'],
'semi': ['error', 'never'],
'brace-style': ['error', 'stroustrup'],
'perfectionist/sort-enums': 'off',
'perfectionist/sort-imports': 'off',
'perfectionist/sort-named-exports': 'off',
'perfectionist/sort-named-imports': 'off',
'perfectionist/sort-union-types': 'off',
'perfectionist/sort-classes': 'off',
'perfectionist/sort-interfaces': 'off',
'perfectionist/sort-objects': 'off',
'perfectionist/sort-object-types': 'off',
'@typescript-eslint/explicit-function-return-type': 'error',
'@typescript-eslint/explicit-member-accessibility': 'off',
'@typescript-eslint/no-confusing-void-expression': 'error',
'@typescript-eslint/no-unnecessary-condition': 'error',
'@typescript-eslint/prefer-find': 'error',
'@typescript-eslint/no-floating-promises': 'off',
'@typescript-eslint/no-misused-promises': 'off',
'@typescript-eslint/unbound-method': 'off',
'@stylistic/no-multiple-empty-lines': 'off',
'@stylistic/comma-dangle': 'off',
'@stylistic/indent': 'off',
'@typescript-eslint/no-unsafe-call': 'off',
'@typescript-eslint/no-unsafe-member-access': 'off',
'@typescript-eslint/no-unsafe-assignment': 'off',
'@typescript-eslint/no-unsafe-return': 'off',
'@typescript-eslint/no-unsafe-argument': 'off',

'@typescript-eslint/no-unused-vars': ['error', {
varsIgnorePattern: '^_$',
argsIgnorePattern: '^_$',
}],

'padding-line-between-statements': ['error', {
blankLine: 'always',
prev: 'function',
next: '*',
}, {
blankLine: 'always',
prev: '*',
next: 'function',
}],

'import/no-named-as-default': 'off',

'import/order': ['error', {
'groups': ['builtin', 'external', 'internal', 'parent', 'sibling', 'index'],

'pathGroups': [{
pattern: '@sx/**',
group: 'internal',
}],

'pathGroupsExcludedImportTypes': ['builtin'],
'newlines-between': 'always',

'alphabetize': {
order: 'asc',
caseInsensitive: true,
},
}],

'import/newline-after-import': ['error', {
count: 2,
}],
},
}, {
files: ['**/*.test.*'],

rules: {
'no-magic-numbers': 'off',
},
}]
16 changes: 10 additions & 6 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
"build-css": "postcss src/styles/index.css -o src/styles/output.css",
"test": "TZ='UTC' jest --config jest.config.js",
"test-coverage": "TZ='UTC' jest --coverage --config jest.config.js",
"lint": "eslint --ext .ts src",
"lint": "eslint src",
"lint-fix": "eslint --ext .ts src --fix",
"build": "ts-node src/build-manifest.ts",
"dist": "npx webpack && cp -r node_modules build/ && cd build && zip -r ../dist/dist.zip . -x \"coverage*\" \"*/*.test.js\""
Expand All @@ -18,8 +18,11 @@
"@babel/core": "^7.25.2",
"@babel/preset-env": "^7.25.4",
"@babel/preset-typescript": "^7.24.6",
"@eslint/compat": "^1.2.3",
"@eslint/eslintrc": "^3.2.0",
"@eslint/js": "^9.16.0",
"@tailwindcss/typography": "0.5.15",
"@types/chrome": "^0.0.268",
"@types/chrome": "^0.0.287",
"@types/jest": "^29.5.13",
"@types/lodash": "^4.17.13",
"@types/node": "^20.12.12",
Expand All @@ -33,20 +36,21 @@
"daisyui": "4.12.10",
"dotenv": "16.4.5",
"eslint": "^8.57.0",
"eslint-config-yenz": "^5.3.0",
"eslint-plugin-import": "^2.29.1",
"eslint-config-yenz": "^8.0.0",
"eslint-plugin-import": "^2.31.0",
"eslint-plugin-jest": "^28.8.3",
"eslint-plugin-perfectionist": "^2.10.0",
"globals": "^15.12.0",
"jest": "^29.7.0",
"jest-chrome": "^0.8.0",
"jest-environment-jsdom": "29.7.0",
"postcss": "8.4.45",
"postcss-cli": "11.0.0",
"postcss-import": "16.1.0",
"tailwindcss": "3.4.4",
"tailwindcss": "3.4.15",
"ts-loader": "^9.5.1",
"typescript": "^5.5.2",
"webpack": "^5.94.0",
"webpack": "^5.96.1",
"webpack-cli": "^5.1.4"
},
"dependencies": {
Expand Down
12 changes: 6 additions & 6 deletions src/js/ai/prompt.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
const PROMPT = 'You help make sure that tickets are ready for development. What sorts of technical questions should I ask before beginning development. The basic fundamentals of our application are already setup and not open questions (database, etc). Do not ask questions about the following: 1. Unit Testing 2. Basic Architecture Setup (Database, etc) 3. Deadlines 4) Concurrency\n' +
'\n' +
'Examples of good questions: - Are there performance or scalability requirements or considerations for the feature?\' - What user roles and permissions need to be accounted for within this feature? - What new monitoring or alerting should be put in place? - Should we consider implementing a feature flag\' - Have all instances where the deprecated model is used been identified\n' +
'Examples of bad questions: - What are the technical and business requirements for the feature?(too broad) - How will the system access and query the Customers database?(implementation already known) - What are the specific user story requirements and how do they align with the broader application requirements? (too broad)\n' +
'\n' +
'Give the top 5 questions in a concise manner, just state the questions without any intro. '
const PROMPT = 'You help make sure that tickets are ready for development. What sorts of technical questions should I ask before beginning development. The basic fundamentals of our application are already setup and not open questions (database, etc). Do not ask questions about the following: 1. Unit Testing 2. Basic Architecture Setup (Database, etc) 3. Deadlines 4) Concurrency\n'
+ '\n'
+ 'Examples of good questions: - Are there performance or scalability requirements or considerations for the feature?\' - What user roles and permissions need to be accounted for within this feature? - What new monitoring or alerting should be put in place? - Should we consider implementing a feature flag\' - Have all instances where the deprecated model is used been identified\n'
+ 'Examples of bad questions: - What are the technical and business requirements for the feature?(too broad) - How will the system access and query the Customers database?(implementation already known) - What are the specific user story requirements and how do they align with the broader application requirements? (too broad)\n'
+ '\n'
+ 'Give the top 5 questions in a concise manner, just state the questions without any intro. '

export default PROMPT
4 changes: 2 additions & 2 deletions src/js/analytics/client-id.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
import {v4 as uuidv4} from 'uuid'
import { v4 as uuidv4 } from 'uuid'


export async function getOrCreateClientId(): Promise<string> {
const result = await chrome.storage.sync.get('clientId')
let clientId: string = result.clientId
if (!clientId) {
clientId = uuidv4()
await chrome.storage.sync.set({clientId})
await chrome.storage.sync.set({ clientId })
}
return clientId
}
2 changes: 1 addition & 1 deletion src/js/analytics/config.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
export const GA_ENDPOINT = 'https://www.google-analytics.com/mp/collect'
export const MEASUREMENT_ID = process.env.GOOGLE_MEASUREMENT_ID
export const GOOGLE_ANALYTICS_API_SECRET = process.env.GOOGLE_ANALYTICS_API_SECRET
export const DEFAULT_ENGAGEMENT_TIME_IN_MSEC = 100
export const DEFAULT_ENGAGEMENT_TIME_IN_MSEC = 100
6 changes: 3 additions & 3 deletions src/js/analytics/session-id.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
const SESSION_EXPIRATION_IN_MIN = 30

export async function getOrCreateSessionId(): Promise<string> {
let {sessionData} = await chrome.storage.session.get('sessionData')
let { sessionData } = await chrome.storage.session.get('sessionData')
// Check if session exists and is still valid
const currentTimeInMs = Date.now()
if (sessionData && sessionData.timestamp) {
Expand All @@ -16,7 +16,7 @@ export async function getOrCreateSessionId(): Promise<string> {
else {
// Update timestamp to keep session alive
sessionData.timestamp = currentTimeInMs
await chrome.storage.session.set({sessionData})
await chrome.storage.session.set({ sessionData })
}
}
if (!sessionData) {
Expand All @@ -25,7 +25,7 @@ export async function getOrCreateSessionId(): Promise<string> {
session_id: currentTimeInMs.toString(),
timestamp: currentTimeInMs.toString(),
}
await chrome.storage.session.set({sessionData})
await chrome.storage.session.set({ sessionData })
}
return sessionData.session_id
}
6 changes: 3 additions & 3 deletions src/js/analyze/analyze-story-description.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
import {Story} from '@sx/utils/story'
import { Story } from '@sx/utils/story'


export async function analyzeStoryDescription(activeTabUrl: string) {
export async function analyzeStoryDescription(activeTabUrl: string): Promise<void> {
if (activeTabUrl.includes('story')) {
const description = Story.description
await chrome.runtime.sendMessage({
action: 'callOpenAI',
data: {prompt: description}
data: { prompt: description }
})
}
}
13 changes: 6 additions & 7 deletions src/js/cycle-time/cycle-time.ts
Original file line number Diff line number Diff line change
@@ -1,21 +1,20 @@
import {max} from 'lodash'
import { max } from 'lodash'

import {hoursBetweenExcludingWeekends} from '@sx/utils/hours-between-excluding-weekends'
import { hoursBetweenExcludingWeekends } from '@sx/utils/hours-between-excluding-weekends'
import sleep from '@sx/utils/sleep'
import {Story} from '@sx/utils/story'
import { Story } from '@sx/utils/story'
import Workspace from '@sx/workspace/workspace'


export class CycleTime {

static clear() {
static clear(): void {
const cycleTimeDiv = document.querySelector('.story-date-cycle-time')
if (cycleTimeDiv) {
cycleTimeDiv.remove()
}
}

static async set() {
static async set(): Promise<void> {
await Story.isReady()
const WAIT_TIME = 300
await sleep(WAIT_TIME)
Expand All @@ -26,7 +25,7 @@ export class CycleTime {
}
const states = await Workspace.states()
const createdDiv = document.querySelector('.story-date-created')
const inDevelopmentDates: Array<string | null> = states.Started.map((state) => Story.getDateInState(state))
const inDevelopmentDates: Array<string | null> = states.Started.map(state => Story.getDateInState(state))
const inDevelopmentDateString: string | undefined | null = max(inDevelopmentDates)
const completedDiv = document.querySelector('.story-date-completed')
const completedValue = completedDiv?.querySelector('.value')
Expand Down
Original file line number Diff line number Diff line change
@@ -1,16 +1,16 @@
export function findFirstMatchingElementForState(state: string) {
export function findFirstMatchingElementForState(state: string): Record<string, Element | undefined> | null {
// Get all elements with the class 'value'
const elementsWithValueClass = Array.from(document.querySelectorAll('.value'))

// Find the first element where a child element contains the text 'In Development'
const foundElement = elementsWithValueClass.find(element => {
const foundElement = elementsWithValueClass.find((element) => {
const child = Array.from(element.children).find(child => child.innerHTML === state)
return Boolean(child)
})

if (foundElement) {
const child = Array.from(foundElement.children).find(child => child.innerHTML === state)
return {element: foundElement, child}
return { element: foundElement, child }
}

return null
Expand Down
Loading

0 comments on commit 3b0fbb9

Please sign in to comment.