Squashed commit message
Some checks failed
Telegram Mini App Shop Builder / Compute version metadata (push) Has been cancelled
Telegram Mini App Shop Builder / Run Frontend tests (push) Has been cancelled
Telegram Mini App Shop Builder / Run Backend tests (push) Has been cancelled
Telegram Mini App Shop Builder / Run PHP_CodeSniffer (push) Has been cancelled
Telegram Mini App Shop Builder / Build module. (push) Has been cancelled
Telegram Mini App Shop Builder / release (push) Has been cancelled
Some checks failed
Telegram Mini App Shop Builder / Compute version metadata (push) Has been cancelled
Telegram Mini App Shop Builder / Run Frontend tests (push) Has been cancelled
Telegram Mini App Shop Builder / Run Backend tests (push) Has been cancelled
Telegram Mini App Shop Builder / Run PHP_CodeSniffer (push) Has been cancelled
Telegram Mini App Shop Builder / Build module. (push) Has been cancelled
Telegram Mini App Shop Builder / release (push) Has been cancelled
This commit is contained in:
332
.cursor/rules/javascript.md
Normal file
332
.cursor/rules/javascript.md
Normal file
@@ -0,0 +1,332 @@
|
||||
# JavaScript/TypeScript Code Style Rules
|
||||
|
||||
## JavaScript Version
|
||||
|
||||
- ES2020+ features
|
||||
- Modern async/await
|
||||
- Optional chaining (`?.`)
|
||||
- Nullish coalescing (`??`)
|
||||
- Template literals
|
||||
|
||||
## Code Style
|
||||
|
||||
### Variable Declarations
|
||||
|
||||
```javascript
|
||||
// ✅ Use const by default
|
||||
const customers = [];
|
||||
const totalRecords = 0;
|
||||
|
||||
// ✅ Use let only when reassignment is needed
|
||||
let currentPage = 1;
|
||||
currentPage = 2;
|
||||
|
||||
// ❌ Do not use var
|
||||
var oldVariable = 'bad';
|
||||
```
|
||||
|
||||
### Arrow Functions
|
||||
|
||||
```javascript
|
||||
// ✅ Preferred for short functions
|
||||
const filtered = items.filter(item => item.isActive);
|
||||
|
||||
// ✅ For object methods
|
||||
const api = {
|
||||
get: async (url) => {
|
||||
return await fetch(url);
|
||||
}
|
||||
};
|
||||
|
||||
// ✅ For complex logic – use regular functions
|
||||
function complexCalculation(data) {
|
||||
// many lines of code
|
||||
return result;
|
||||
}
|
||||
```
|
||||
|
||||
### Template Literals
|
||||
|
||||
```javascript
|
||||
// ✅ Preferred
|
||||
const message = `User ${userId} not found`;
|
||||
const url = `${baseUrl}/api/${endpoint}`;
|
||||
|
||||
// ❌ Do not use concatenation
|
||||
const message = 'User ' + userId + ' not found';
|
||||
```
|
||||
|
||||
### Optional Chaining
|
||||
|
||||
```javascript
|
||||
// ✅ Use optional chaining
|
||||
const name = user?.profile?.name;
|
||||
const count = data?.items?.length ?? 0;
|
||||
|
||||
// ❌ Avoid long nested checks
|
||||
const name = user && user.profile && user.profile.name;
|
||||
```
|
||||
|
||||
### Nullish Coalescing
|
||||
|
||||
```javascript
|
||||
// ✅ Use ?? for default values
|
||||
const page = params.page ?? 1;
|
||||
const name = user.name ?? 'Unknown';
|
||||
|
||||
// ❌ Do not use || for numbers/booleans
|
||||
const page = params.page || 1; // 0 will be replaced with 1
|
||||
```
|
||||
|
||||
### Destructuring
|
||||
|
||||
```javascript
|
||||
// ✅ Use destructuring
|
||||
const { data, totalRecords } = response.data;
|
||||
const [first, second] = items;
|
||||
|
||||
// ✅ In function parameters
|
||||
function processUser({ id, name, email }) {
|
||||
// ...
|
||||
}
|
||||
|
||||
// ✅ With default values
|
||||
const { page = 1, limit = 20 } = params;
|
||||
```
|
||||
|
||||
### Async/Await
|
||||
|
||||
```javascript
|
||||
// ✅ Preferred
|
||||
async function loadCustomers() {
|
||||
try {
|
||||
const response = await apiGet('getCustomers', params);
|
||||
return response.data;
|
||||
} catch (error) {
|
||||
console.error('Error:', error);
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
// ❌ Avoid .then() chains
|
||||
function loadCustomers() {
|
||||
return apiGet('getCustomers', params)
|
||||
.then(response => response.data)
|
||||
.catch(error => console.error(error));
|
||||
}
|
||||
```
|
||||
|
||||
## Vue.js 3 Composition API
|
||||
|
||||
### Script Setup
|
||||
|
||||
```vue
|
||||
<script setup>
|
||||
// ✅ Use <script setup>
|
||||
import { ref, computed, onMounted } from 'vue';
|
||||
import { apiGet } from '@/utils/http.js';
|
||||
|
||||
const customers = ref([]);
|
||||
const loading = ref(false);
|
||||
|
||||
const totalRecords = computed(() => customers.value.length);
|
||||
|
||||
async function loadCustomers() {
|
||||
loading.value = true;
|
||||
try {
|
||||
const result = await apiGet('getCustomers');
|
||||
customers.value = result.data || [];
|
||||
} finally {
|
||||
loading.value = false;
|
||||
}
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
loadCustomers();
|
||||
});
|
||||
</script>
|
||||
```
|
||||
|
||||
### Reactive State
|
||||
|
||||
```javascript
|
||||
// ✅ Use ref for primitives
|
||||
const count = ref(0);
|
||||
const name = ref('');
|
||||
|
||||
// ✅ Use reactive for objects
|
||||
import { reactive } from 'vue';
|
||||
const state = reactive({
|
||||
customers: [],
|
||||
loading: false
|
||||
});
|
||||
|
||||
// ✅ Or ref for objects (preferred)
|
||||
const state = ref({
|
||||
customers: [],
|
||||
loading: false
|
||||
});
|
||||
```
|
||||
|
||||
### Computed Properties
|
||||
|
||||
```javascript
|
||||
// ✅ Use computed for derived values
|
||||
const filteredCustomers = computed(() => {
|
||||
return customers.value.filter(c => c.isActive);
|
||||
});
|
||||
|
||||
// ❌ Do not use methods for derived values
|
||||
function filteredCustomers() {
|
||||
return customers.value.filter(c => c.isActive);
|
||||
}
|
||||
```
|
||||
|
||||
### Props
|
||||
|
||||
```vue
|
||||
<script setup>
|
||||
// ✅ Define props with types
|
||||
const props = defineProps({
|
||||
customerId: {
|
||||
type: Number,
|
||||
required: true
|
||||
},
|
||||
showDetails: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
}
|
||||
});
|
||||
</script>
|
||||
```
|
||||
|
||||
### Emits
|
||||
|
||||
```vue
|
||||
<script setup>
|
||||
// ✅ Define emits
|
||||
const emit = defineEmits(['update', 'delete']);
|
||||
|
||||
function handleUpdate() {
|
||||
emit('update', data);
|
||||
}
|
||||
</script>
|
||||
```
|
||||
|
||||
## Pinia Stores
|
||||
|
||||
```javascript
|
||||
// ✅ Use setup stores
|
||||
import { defineStore } from 'pinia';
|
||||
import { ref, computed } from 'vue';
|
||||
|
||||
export const useCustomersStore = defineStore('customers', () => {
|
||||
const customers = ref([]);
|
||||
const loading = ref(false);
|
||||
|
||||
const totalRecords = computed(() => customers.value.length);
|
||||
|
||||
async function loadCustomers() {
|
||||
loading.value = true;
|
||||
try {
|
||||
const result = await apiGet('getCustomers');
|
||||
customers.value = result.data || [];
|
||||
} finally {
|
||||
loading.value = false;
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
customers,
|
||||
loading,
|
||||
totalRecords,
|
||||
loadCustomers
|
||||
};
|
||||
});
|
||||
```
|
||||
|
||||
## Error Handling
|
||||
|
||||
```javascript
|
||||
// ✅ Always handle errors
|
||||
async function loadData() {
|
||||
try {
|
||||
const result = await apiGet('endpoint');
|
||||
if (result.success) {
|
||||
return result.data;
|
||||
} else {
|
||||
throw new Error(result.error);
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Failed to load data:', error);
|
||||
toast.error('Failed to load data');
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Naming Conventions
|
||||
|
||||
### Variables and Functions
|
||||
|
||||
```javascript
|
||||
// ✅ camelCase
|
||||
const customerData = {};
|
||||
const totalRecords = 0;
|
||||
function loadCustomers() {}
|
||||
|
||||
// ✅ Constants in UPPER_SNAKE_CASE
|
||||
const MAX_RETRIES = 3;
|
||||
const API_BASE_URL = '/api';
|
||||
```
|
||||
|
||||
### Components
|
||||
|
||||
```vue
|
||||
<!-- ✅ PascalCase for components -->
|
||||
<CustomerCard />
|
||||
<ProductsList />
|
||||
```
|
||||
|
||||
### Files
|
||||
|
||||
```javascript
|
||||
// ✅ Use kebab-case for files
|
||||
// customers-view.vue
|
||||
// http-utils.js
|
||||
// customer-service.js
|
||||
```
|
||||
|
||||
## Imports
|
||||
|
||||
```javascript
|
||||
// ✅ Group imports
|
||||
// 1. Vue core
|
||||
import { ref, computed, onMounted } from 'vue';
|
||||
|
||||
// 2. Third-party
|
||||
import { apiGet } from '@/utils/http.js';
|
||||
import { useToast } from 'primevue';
|
||||
|
||||
// 3. Local components
|
||||
import CustomerCard from '@/components/CustomerCard.vue';
|
||||
|
||||
// 4. Types (if using TypeScript)
|
||||
import type { Customer } from '@/types';
|
||||
```
|
||||
|
||||
## TypeScript (where used)
|
||||
|
||||
```typescript
|
||||
// ✅ Use types
|
||||
interface Customer {
|
||||
id: number;
|
||||
name: string;
|
||||
email?: string;
|
||||
}
|
||||
|
||||
function getCustomer(id: number): Promise<Customer> {
|
||||
return apiGet(`customers/${id}`);
|
||||
}
|
||||
```
|
||||
|
||||
Reference in New Issue
Block a user