Compare commits
5 Commits
test
...
ErrorBranc
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
af9e54deb6 | ||
|
|
5adb236aef | ||
|
|
bb5a0840fe | ||
|
|
4372bcd160 | ||
|
|
da8b69577e |
32
error.js
Normal file
32
error.js
Normal file
@@ -0,0 +1,32 @@
|
|||||||
|
import React, { useState } from 'react';
|
||||||
|
|
||||||
|
function Demo(props) {
|
||||||
|
const [count, setCount] = useState('0');
|
||||||
|
|
||||||
|
function unusedFunc() {
|
||||||
|
return 'unused';
|
||||||
|
}
|
||||||
|
|
||||||
|
const name = props.username;
|
||||||
|
|
||||||
|
const arr = [1,2,3];
|
||||||
|
const list = arr.map(item => <li>{item}</li>);
|
||||||
|
|
||||||
|
const style = { color: 'red', fontWeight: 500 };
|
||||||
|
|
||||||
|
let result = value + 1;
|
||||||
|
|
||||||
|
setCount(count++);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div style={style}>
|
||||||
|
<span>Test</span>
|
||||||
|
{list}
|
||||||
|
<button onClick={() => setCount('abc')}>Click</button>
|
||||||
|
<p>{name}</p>
|
||||||
|
</div>
|
||||||
|
<h1>Unwrapped</h1>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export { Demo };
|
||||||
32
error.jsx
Normal file
32
error.jsx
Normal file
@@ -0,0 +1,32 @@
|
|||||||
|
import React, { useState } from 'react';
|
||||||
|
|
||||||
|
function MyComponent(props) {
|
||||||
|
const [count, setCount] = useState('0');
|
||||||
|
|
||||||
|
function unusedFunc() {
|
||||||
|
return 'unused';
|
||||||
|
}
|
||||||
|
|
||||||
|
const name = props.username;
|
||||||
|
|
||||||
|
const arr = [1,2,3];
|
||||||
|
const list = arr.map(item => <li>{item}</li>);
|
||||||
|
|
||||||
|
const style = { color: 'red', fontWeight: 500 };
|
||||||
|
|
||||||
|
let result = value + 1;
|
||||||
|
|
||||||
|
setCount(count++);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div style={style}>
|
||||||
|
<span>Test</span>
|
||||||
|
{list}
|
||||||
|
<button onClick={() => setCount('abc')}>Click</button>
|
||||||
|
<p>{name}</p>
|
||||||
|
</div>
|
||||||
|
<h1>Unwrapped</h1>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export { MyComponent };
|
||||||
26
error.php
Normal file
26
error.php
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
use yii\base\Controller;
|
||||||
|
|
||||||
|
class SiteController extends Controller {
|
||||||
|
function actionIndex() {
|
||||||
|
echo $title;
|
||||||
|
|
||||||
|
$id = $_GET['id'];
|
||||||
|
$user = Yii::$app->db->createCommand("SELECT * FROM user WHERE id = $id")->queryOne();
|
||||||
|
|
||||||
|
echo $user['name'];
|
||||||
|
|
||||||
|
echo '<form method="post"><input name="test"></form>';
|
||||||
|
|
||||||
|
$model = new \app\models\User();
|
||||||
|
$model->name = $_POST['name'];
|
||||||
|
$model->save();
|
||||||
|
|
||||||
|
require_once('/var/www/html/config.php');
|
||||||
|
|
||||||
|
throw new Exception('Error!');
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
44
error.ts
Normal file
44
error.ts
Normal file
@@ -0,0 +1,44 @@
|
|||||||
|
function add(a: number, b: number): number {
|
||||||
|
return a + b
|
||||||
|
}
|
||||||
|
|
||||||
|
const result = add('1', 2);
|
||||||
|
console.log(result)
|
||||||
|
|
||||||
|
let unusedVar: string;
|
||||||
|
|
||||||
|
function getString(): number {
|
||||||
|
return "hello"
|
||||||
|
}
|
||||||
|
|
||||||
|
let neverUsed = 123;
|
||||||
|
|
||||||
|
let x: any = "abc";
|
||||||
|
let y: number = x as number;
|
||||||
|
|
||||||
|
let a = 5;
|
||||||
|
function shadow() {
|
||||||
|
let a = "shadowed";
|
||||||
|
return a;
|
||||||
|
}
|
||||||
|
|
||||||
|
function noReturnType() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface User {
|
||||||
|
name: string;
|
||||||
|
age: number;
|
||||||
|
}
|
||||||
|
const user: User = { name: "A", age: "20" };
|
||||||
|
|
||||||
|
const arr: number[] = [1, "2", 3];
|
||||||
|
|
||||||
|
function unreachable() {
|
||||||
|
return 1;
|
||||||
|
console.log("This will never run");
|
||||||
|
}
|
||||||
|
|
||||||
|
function useAny(a: any, b: any): any {
|
||||||
|
return a + b;
|
||||||
|
}
|
||||||
35
error.tsx
Normal file
35
error.tsx
Normal file
@@ -0,0 +1,35 @@
|
|||||||
|
import React, { useState } from 'react';
|
||||||
|
|
||||||
|
type Props = { title?: string };
|
||||||
|
function App(props: Props) {
|
||||||
|
const [count, setCount] = useState<string>(0);
|
||||||
|
|
||||||
|
function unusedFunc(): string {
|
||||||
|
return 'unused';
|
||||||
|
}
|
||||||
|
|
||||||
|
const name = props.username;
|
||||||
|
|
||||||
|
const arr = [1,2,3];
|
||||||
|
const list = arr.map(item => <li>{item}</li>);
|
||||||
|
|
||||||
|
const style = { color: 'red', fontWeight: 500 };
|
||||||
|
|
||||||
|
let result = value + 1;
|
||||||
|
|
||||||
|
setCount(count++);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div style={style}>
|
||||||
|
<span>Hello World</span>
|
||||||
|
{list}
|
||||||
|
<button onClick={() => setCount('abc')}>Click</button>
|
||||||
|
<p>{name}</p>
|
||||||
|
</div>
|
||||||
|
<h1>Unwrapped</h1>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export { App };
|
||||||
|
|
||||||
|
const unused = 123;
|
||||||
164
test.txt
164
test.txt
@@ -1,164 +0,0 @@
|
|||||||
import { IExpenseRequest, IExpenseResponse } from "../types";
|
|
||||||
import { API_BASE_URL, EXPENSE_WEBHOOK_ENDPOINT } from "../utils/constants";
|
|
||||||
import * as FileSystem from "expo-file-system";
|
|
||||||
|
|
||||||
export class ExpenseService {
|
|
||||||
private static readonly API_URL = `${API_BASE_URL}${EXPENSE_WEBHOOK_ENDPOINT}`;
|
|
||||||
|
|
||||||
static async sendExpenseData(
|
|
||||||
data: IExpenseRequest
|
|
||||||
): Promise<IExpenseResponse> {
|
|
||||||
try {
|
|
||||||
const response = await fetch(this.API_URL, {
|
|
||||||
method: "POST",
|
|
||||||
headers: {
|
|
||||||
"Content-Type": "application/json",
|
|
||||||
Accept: "application/json",
|
|
||||||
},
|
|
||||||
body: JSON.stringify(data),
|
|
||||||
});
|
|
||||||
|
|
||||||
if (!response.ok) {
|
|
||||||
throw new Error(`HTTP error! status: ${response.status}`);
|
|
||||||
}
|
|
||||||
|
|
||||||
const result = await response.json();
|
|
||||||
return result;
|
|
||||||
} catch (error) {
|
|
||||||
console.error("Error sending expense data:", error);
|
|
||||||
throw new Error(
|
|
||||||
error instanceof Error ? error.message : "Có lỗi xảy ra khi gửi dữ liệu"
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static async sendAudioExpense(audioUri: string): Promise<IExpenseResponse> {
|
|
||||||
try {
|
|
||||||
// Send audio file as multipart/form-data for n8n workflow
|
|
||||||
return await this.sendAudioToN8N(audioUri);
|
|
||||||
} catch (error) {
|
|
||||||
console.error("Error sending audio expense:", error);
|
|
||||||
throw error;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static async sendTextExpense(text: string): Promise<IExpenseResponse> {
|
|
||||||
try {
|
|
||||||
const requestData: IExpenseRequest = {
|
|
||||||
textInput: text,
|
|
||||||
timestamp: new Date().toISOString(),
|
|
||||||
};
|
|
||||||
|
|
||||||
return await this.sendExpenseData(requestData);
|
|
||||||
} catch (error) {
|
|
||||||
console.error("Error sending text expense:", error);
|
|
||||||
throw error;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private static async sendAudioToN8N(
|
|
||||||
audioUri: string
|
|
||||||
): Promise<IExpenseResponse> {
|
|
||||||
try {
|
|
||||||
const formData = new FormData();
|
|
||||||
|
|
||||||
// Get file info
|
|
||||||
const fileInfo = await FileSystem.getInfoAsync(audioUri);
|
|
||||||
if (!fileInfo.exists) {
|
|
||||||
throw new Error("File audio không tồn tại");
|
|
||||||
}
|
|
||||||
|
|
||||||
console.log("File info:", fileInfo);
|
|
||||||
console.log("Audio URI:", audioUri);
|
|
||||||
|
|
||||||
// Extract file name and extension
|
|
||||||
const fileName =
|
|
||||||
audioUri.split("/").pop() || `recording_${Date.now()}.m4a`;
|
|
||||||
const fileExtension = fileName.split(".").pop() || "m4a";
|
|
||||||
const mimeType = "audio/x-m4a";
|
|
||||||
const fileSizeBytes = fileInfo.size || 0;
|
|
||||||
const fileSizeMB = (fileSizeBytes / (1024 * 1024)).toFixed(2);
|
|
||||||
|
|
||||||
// Try different approaches for React Native file upload
|
|
||||||
let audioFile: any;
|
|
||||||
|
|
||||||
if (audioUri.startsWith("file://")) {
|
|
||||||
// For local files, create proper file object
|
|
||||||
audioFile = {
|
|
||||||
uri: audioUri,
|
|
||||||
type: mimeType,
|
|
||||||
name: fileName,
|
|
||||||
};
|
|
||||||
} else {
|
|
||||||
// Fallback: read as base64 and convert
|
|
||||||
const base64Data = await FileSystem.readAsStringAsync(audioUri, {
|
|
||||||
encoding: FileSystem.EncodingType.Base64,
|
|
||||||
});
|
|
||||||
|
|
||||||
audioFile = {
|
|
||||||
uri: `data:${mimeType};base64,${base64Data}`,
|
|
||||||
type: mimeType,
|
|
||||||
name: fileName,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
// Append audio file to form data (n8n sẽ nhận như binary data)
|
|
||||||
formData.append("audioFile", audioFile as any);
|
|
||||||
|
|
||||||
// Append metadata as separate fields
|
|
||||||
formData.append("timestamp", new Date().toISOString());
|
|
||||||
formData.append("fileName", fileName);
|
|
||||||
formData.append("fileExtension", fileExtension);
|
|
||||||
formData.append("mimeType", mimeType);
|
|
||||||
formData.append("fileSizeBytes", fileSizeBytes.toString());
|
|
||||||
formData.append("fileSizeMB", `${fileSizeMB} MB`);
|
|
||||||
|
|
||||||
console.log("File metadata:", {
|
|
||||||
fileName,
|
|
||||||
fileExtension,
|
|
||||||
mimeType,
|
|
||||||
fileSizeBytes,
|
|
||||||
fileSizeMB: `${fileSizeMB} MB`,
|
|
||||||
});
|
|
||||||
|
|
||||||
console.log("Sending FormData to:", this.API_URL);
|
|
||||||
|
|
||||||
const response = await fetch(this.API_URL, {
|
|
||||||
method: "POST",
|
|
||||||
// Không set Content-Type header - fetch sẽ tự động set với boundary
|
|
||||||
body: formData,
|
|
||||||
});
|
|
||||||
|
|
||||||
console.log("Response status:", response.status);
|
|
||||||
console.log("Response headers:", response.headers);
|
|
||||||
|
|
||||||
if (!response.ok) {
|
|
||||||
const errorText = await response.text();
|
|
||||||
console.error("Error response:", errorText);
|
|
||||||
throw new Error(
|
|
||||||
`HTTP error! status: ${response.status}, message: ${errorText}`
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
const result = await response.json();
|
|
||||||
return result;
|
|
||||||
} catch (error) {
|
|
||||||
console.error("Error sending audio to n8n:", error);
|
|
||||||
throw new Error(
|
|
||||||
error instanceof Error ? error.message : "Có lỗi xảy ra khi gửi audio"
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private static async convertAudioToBase64(audioUri: string): Promise<string> {
|
|
||||||
try {
|
|
||||||
const base64 = await FileSystem.readAsStringAsync(audioUri, {
|
|
||||||
encoding: FileSystem.EncodingType.Base64,
|
|
||||||
});
|
|
||||||
return base64;
|
|
||||||
} catch (error) {
|
|
||||||
console.error("Error converting audio to base64:", error);
|
|
||||||
throw new Error("Không thể chuyển đổi file audio");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Reference in New Issue
Block a user