@flow-js/garmin-connect

中文文档
1.6.25发布于 2026/11/03MITTypeScriptCommonJS构建来源已验证近 30 天下载 4163

让与 Garmin Connect 接口以获取或设置任何数据点变得简单

中文使用文档
文档目录28 节
  1. 目录
  2. 认证
  3. 构造器
  4. 登录
  5. 多功能认证( MFA)
  6. 会话管理
  7. 用户数据
  8. 用户配置
  9. 用户设置
  10. 活 动
  11. 获取活动
  12. 个人活动业务
  13. 活动文件
  14. 劳动
  15. 管理工作
  16. 工作时间安排
  17. 导出为间隔. icu
  18. 卫生数据
  19. 步骤
  20. 睡觉
  21. 重量
  22. 水分
  23. 心率
  24. 高尔夫
  25. 齿轮
  26. GPX 和课程
  27. 日历
  28. 自定义请求

Garmin 连接

这是叉子 https://github.com/Pythe1337N/garmin-connect (中文(简体) ) 灵感来自 https://github.com/matin/garth (中文(简体) )。非常感谢捐助者.


一个 JavaScript 库,用于访问和管理您的 Garmin 连接数据 。 它有方法 获取和设置信息 在您的 Garmin 账户, 也支持 自定义请求 使用 GET, (中文(简体) ), POST,以及 PUT 这样你就可以满足额外的需要.

该文件详细介绍了《公约》第19条第1款(a)项和(b)项所规定的公共公共宣传工具 @flow-js/garmin-connect 图书馆.

目录

认证

构造器

创建 Garmin 连接客户端的新实例 .

const { GarminConnect } = require('@flow-js/garmin-connect');

// Create a new Garmin Connect Client with credentials
const GCClient = new GarminConnect({
    username: '[email protected]',
    password: 'MySecretPassword'
});

// Alternatively, create a client using credentials from garmin.config.json
const GCClient = new GarminConnect();

您也可以提供名为配置文件 garmin.config.json 在您的工程根 :

{
    "username": "[email protected]",
    "password": "MySecretPassword"
}

登录

/**
 * Login to Garmin Connect with provided credentials or those set during construction
 * @param username - Optional username to override the one in credentials
 * @param password - Optional password to override the one in credentials
 * @param options - Optional login options (see MFA below)
 * @returns The GarminConnect instance for chaining
 */
async
login(
    username ? : string,
    password ? : string,
    options ? : LoginOptions
)
:
Promise < GarminConnect >

示例

await GCClient.login();
// Or with specific credentials
await GCClient.login('[email protected]', 'MySecretPassword');

完整实例 : examples/example.js

多功能认证( MFA)

如果您的 Garmin 账户已启用 2FA / MFA , 登录将会失败, 除非您提供 mfaHandler 调用。 当加明回应 MFA_REQUIRED图书馆给你的管理员打电话,等着 验证码(email或认证器app),并完成登录.

/**
 * @property mfaHandler - Async function that resolves to the MFA verification code.
 *   Required for accounts with 2FA enabled. If MFA is required and this is omitted,
 *   login throws: "MFA required but no mfaHandler provided".
 */
interface LoginOptions {
    mfaHandler?: () => Promise<string>;
}

示例( 在节点. js CLI 中的代码提示):

const readline = require('readline');
const { GarminConnect } = require('@flow-js/garmin-connect');

const promptMfaCode = () =>
    new Promise((resolve) => {
        const rl = readline.createInterface({
            input: process.stdin,
            output: process.stdout
        });
        rl.question('Enter MFA code: ', (code) => {
            rl.close();
            resolve(code);
        });
    });

const GCClient = new GarminConnect({
    username: '[email protected]',
    password: 'MySecretPassword'
});

await GCClient.login(undefined, undefined, {
    mfaHandler: promptMfaCode
});

您也可通过全权证书和外交部主管:

await GCClient.login('[email protected]', 'MySecretPassword', {
    mfaHandler: async () => {
        // Fetch or prompt for the code (email / authenticator app)
        return '123456';
    }
});

在外交部成功登录后,导出 OAuth 令牌(见 会话管理(中文(简体) ) 并重新使用它们 loadToken 编号 : loadTokenByFile 以后的运行,所以你不需要每次输入 MFA 代码. 通过外交部获得的托币可包括: mfa_token 财务报告和审定财务报表 mfa_expiration_timestamp 在 OAuth1 标记上; 这些保存到 exportToken() 编号 : loadToken() 圆通相通.

会话管理

导出托肯

/**
 * Exports OAuth tokens to files in the specified directory
 * @param dirPath - Directory path where token files will be saved
 */
exportTokenToFile(dirPath: string): void

示例

GCClient.exportTokenToFile('/path/to/save/tokens');
// Creates oauth1_token.json and oauth2_token.json in the specified directory

从文件装入鼠标

/**
 * Loads OAuth tokens from files in the specified directory
 * @param dirPath - Directory path where token files are stored
 * @throws Error if directory not found
 */
loadTokenByFile(dirPath: string): void

示例

GCClient.loadTokenByFile('/path/to/save/tokens');

导出托肯为对象

/**
 * Exports OAuth tokens as an object
 * @returns Object containing OAuth1 and OAuth2 tokens
 * @throws Error if tokens are not found
 */
exportToken(): IGarminTokens

从对象装入托盘

/**
 * Loads OAuth tokens from provided token objects (e.g., from DB or localStorage)
 * @param oauth1 - OAuth1 token object
 * @param oauth2 - OAuth2 token object
 */
loadToken(oauth1: IOauth1Token, oauth2: IOauth2Token): void

示例

const oauth1 = GCClient.client.oauth1Token;
const oauth2 = GCClient.client.oauth2Token;
// Later, use these to restore the session
GCClient.loadToken(oauth1, oauth2);

用户数据

用户配置

/**
 * Retrieves the user's social profile from Garmin Connect
 * @returns User's social profile data
 */
async getUserProfile(): Promise<ISocialProfile>

示例

const userProfile = await GCClient.getUserProfile();
console.log(userProfile.userName); // Verify login was successful

用户设置

/**
 * Retrieves the user's settings from Garmin Connect
 * @returns User settings data
 */
async getUserSettings(): Promise<IUserSettings>

完整实例 : examples/example.js

活 动

获取活动

/**
 * Retrieves a list of activities matching the specified criteria
 * @param start - Optional starting index for pagination
 * @param limit - Optional limit for pagination
 * @param activityType - Optional activity type filter
 * @param subActivityType - Optional activity subtype filter
 * @returns Array of activities matching the criteria
 */
async getActivities(
    start?: number,
    limit?: number,
    activityType?: ActivityType,
    subActivityType?: ActivitySubType
): Promise<IActivity[]>

示例

const activities = await GCClient.getActivities(
    0,
    10,
    ActivityType.Running,
    ActivitySubType.Outdoor
);
/**
 * Counts lifetime activities
 * @returns Activity statistics including counts by type
 */
async countActivities(): Promise<ICountActivities>

个人活动业务

/**
 * Retrieves a specific activity by its ID
 * @param activity - Object containing activityId
 * @returns Details of the specified activity
 * @throws Error if activityId is missing
 */
async getActivity(activity: {
    activityId: GCActivityId;
}): Promise<IActivity>

示例

const activityDetails = await GCClient.getActivity({
    activityId: 'exampleActivityId'
});
/**
 * Deletes an activity by activityId
 * @param activity - with activityId
 * @returns void
 *
 */
async deleteActivity(activity: {
    activityId: GCActivityId;
}): Promise<void>
/**
 * Renames an activity with the given activityId to the newName.
 * @param activityId
 * @param newName
 */
async renameActivity(
    activityId: GCActivityId,
    newName: string
): Promise<void>

活动文件

/**
 * Download activity original data file
 *
 * Use the activityId to download the original activity data. Usually this is supplied as a .zip file.
 *
 * @example
 * ```js
 * const [activity] = await GCClient.getActivities(0, 1);
 * // Directory path is optional and defaults to the current working directory.
 * // Downloads filename will be supplied by Garmin.
 * GCClient.downloadOriginalActivityData(activity, './some/path/that/exists');
 * ```
 *
 * @param activity - with activityId
 * @param dir - directory to save the file
 * @param type - 'zip' | 'gpx' | 'tcx' | 'kml' (default: 'zip')
 */
async downloadOriginalActivityData(
    activity: { activityId: GCActivityId },
    dir: string,
    type: ExportFileTypeValue = 'zip'
): Promise<void>
/**
 * Uploads an activity file
 *
 * Uploads an activity file as a new Activity. The file can be a 'gpx', 'tcx', or 'fit' file.
 * If the activity already exists, the result will have a status code of 409.
 * Note: Garmin changed the upload API in v1.4.4, the response `detailedImportResult` no longer contains the new activityId.
 *
 * @param file - Path to the activity file
 * @param format - 'fit' | 'gpx' | 'tcx'
 * @returns Response from the upload operation
 */
async uploadActivity(
    file: string,
    format: UploadFileTypeTypeValue = 'fit'
)

示例

const upload = await GCClient.uploadActivity('./some/path/to/file.fit');
// Note: Garmin changed the upload API in v1.4.4
// const activityId = upload.detailedImportResult.successes[0].internalId; // Not working
// const uploadId = upload.detailedImportResult.uploadId;
/**
 * Uploads a photo to an activity
 * @param activityId - The ID of the activity to attach the photo to
 * @param filePath - Path to the image file to upload
 * @returns Response from the photo upload operation
 */
async uploadActivityPhoto(
    activityId: GCActivityId,
    filePath: string
): Promise<unknown>

示例

await GCClient.uploadActivityPhoto(12345678, './my-run-photo.jpg');

完整实例 : examples/example-image.js

劳动

管理工作

/**
 * Gets the list of workouts
 * @param start
 * @param limit
 */
async getWorkouts(start: number, limit: number): Promise<IWorkout[]>

完整实例 : examples/example-intervals-icu.js

/**
 * Gets the workout detail by workoutId
 * @param workout
 * @returns workout detail - IWorkoutDetail
 */
async getWorkoutDetail(workout: {
    workoutId: string;
}): Promise<IWorkoutDetail>

完整实例 : examples/example-intervals-icu.js

/**
 * Creates a new workout
 *
 * Use workoutBuilder to create the workout object. See the example in [examples/example-workout.js](examples/example-workout.js) for more complex workouts.
 *
 * @param workout - workout detail
 * @returns Response from the workout creation operation
 *
 * @example
 * ```js
 * const wb = new WorkoutBuilder(
 *     WorkoutType.Running,
 *     'Workout running ' + new Date().toISOString()
 * );
 *
 * wb.addStep(
 *     new Step(
 *         StepType.Run,
 *         TimeDuration.fromSeconds(45),
 *         new NoTarget(),
 *         'Comment for the step: Run for 45 seconds'
 *     )
 * );
 *
 * GCClient.createWorkout(wb.build());
 * ```
 */
async createWorkout(workout: IWorkoutDetail)

完整实例 : examples/example-workout.js, (中文(简体) ), examples/example-strength-workout.js

/**
 * Deletes a workout by workoutId
 * @param workout - with workoutId
 *
 * @example
 * ```js
 * const workouts = await GCClient.getWorkouts();
 * const id = workouts[0].workoutId;
 * GCClient.deleteWorkout({ workoutId: id });
 * ```
 */
async deleteWorkout(workout: { workoutId: string })
/**
 * Retrieves all workouts
 * @returns List of workouts
 */
async workouts(): Promise<Workout[]>

工作时间安排

/**
 * Schedule a workout by workoutId to a specific date
 *
 * To add a workout to your calendar, provide the workout id and the date to schedule it on.
 *
 * @param workout - with workoutId
 * @param scheduleDate - 'YYYY-MM-DD' format date string
 *
 * @example
 * ```js
 * const workouts = await GCClient.getWorkouts();
 * const id = workouts[0].workoutId;
 * GCClient.scheduleWorkout({ workoutId: id }, new Date('2025-12-01'));
 * ```
 */
async scheduleWorkout(
    workout: { workoutId: string },
    scheduleDate: string
)

导出为间隔. icu

将 Garmin 解决细节转换成一个与 页:1 间隔. icu 解决构建器中省略了 您可以在间隔上单独设置 。 icu事件.

/**
 * Convert a Garmin workout detail into an intervals.icu workout description string.
 * @param workout - workout detail from getWorkoutDetail() or WorkoutBuilder.build()
 * @returns intervals.icu description (sections, steps, targets, repeats)
 */
toIntervalsIcuDescription(workout
:
IWorkoutDetail
):
string

示例

const {
    GarminConnect,
    toIntervalsIcuDescription
} = require('@flow-js/garmin-connect');

const detail = await GCClient.getWorkoutDetail({ workoutId });
const description = toIntervalsIcuDescription(detail);
console.log(description);
// Warmup
// - Easy 10m Z2 HR
//
// Main Set 4x
// - 800mtr 5:00/km Pace
// - 400mtr Z1 HR
//
// Cooldown
// - 10m Z1 HR

见 examples/example-intervals-icu.js 对于一个完整的取而代之的例子.

支持的映射包括时间和距离持续时间,圈压,速度/HR/功率/cadence目标,区头 (单位:千美元)Warmup, (中文(简体) ), Main Set, (中文(简体) ), Cooldown)和重复组(Main Set Nx) (中文(简体) ). 强步和不支持的结束条件 (日历、人力资源阈值、代表)作为说明性提示文本发布.

卫生数据

步骤

/**
 * Retrieves step count for a specific date
 * @param date - The date to get step count for, defaults to current date
 * @returns Total step count for the specified date
 * @throws Error if steps data not found for the date
 */
async getSteps(date = new Date()): Promise<number>

示例

const totalSteps = await GCClient.getSteps(new Date('2020-03-24'));

睡觉

/**
 * Retrieves sleep data for a specific date
 * @param date - The date to get sleep data for, defaults to current date
 * @returns Sleep data for the specified date
 * @throws Error if sleep data is invalid or empty
 */
async getSleepData(date = new Date()): Promise<SleepData>
/**
 * Calculates sleep duration for a specific date
 *
 * Retrieves hours and minutes slept for a given date.
 *
 * @param date - The date to get sleep duration for, defaults to current date
 * @returns Object with hours and minutes of sleep
 * @throws Error if sleep data is missing or invalid
 *
 * @example
 * ```js
 * const detailedSleep = await GCClient.getSleepDuration(new Date('2020-03-24'));
 * console.log(`Hours: ${detailedSleep.hours}, Minutes: ${detailedSleep.minutes}`);
 * ```
 */
async getSleepDuration(
    date = new Date()
): Promise<{ hours: number; minutes: number }>

重量

/**
 * Retrieves weight data for a specific date
 * @param date - The date to get weight data for, defaults to current date
 * @returns Weight data for the specified date
 * @throws Error if weight data is invalid or empty
 */
async getDailyWeightData(date = new Date()): Promise<WeightData>
/**
 * Retrieves weight data in pounds for a specific date
 * @param date - The date to get weight data for, defaults to current date
 * @returns Weight in pounds for the specified date
 * @throws Error if valid weight data not found for the date
 */
async getDailyWeightInPounds(date = new Date()): Promise<number>
/**
 * Updates weight data for a specific date
 *
 * Updates weight information for the specified date.
 *
 * @param date - The date for the weight data, defaults to current date
 * @param lbs - Weight value in pounds
 * @param timezone - Timezone string for correct timestamp conversion
 * @returns Response from the weight update operation
 * @throws Error if update fails
 *
 * @example
 * ```js
 * await GCClient.updateWeight(undefined, 202.9, 'America/Los_Angeles');
 * ```
 */
async updateWeight(
    date = new Date(),
    lbs: number,
    timezone: string
): Promise<UpdateWeight>

水分

/**
 * Retrieves hydration data in fluid ounces for a specific date
 * @param date - The date to get hydration data for, defaults to current date
 * @returns Hydration value in fluid ounces for the specified date
 * @throws Error if hydration data is invalid or empty
 */
async getDailyHydration(date = new Date()): Promise<number>
/**
 * Updates hydration log with fluid ounces for a specific date
 *
 * Adds a hydration log entry in ounces for a given date.
 *
 * @param date - The date for the hydration data, defaults to current date
 * @param valueInOz - Hydration value in fluid ounces. Accepts negative number.
 * @returns Response from the hydration update operation
 * @throws Error if update fails
 *
 * @example
 * ```js
 * const hydrationLogEntry = await GCClient.updateHydrationLogOunces(
 *     new Date('2020-03-24'),
 *     16
 * );
 * ```
 */
async updateHydrationLogOunces(
    date = new Date(),
    valueInOz: number
): Promise<WaterIntake>

心率

/**
 * Retrieves heart rate data for a specific date
 *
 * Retrieves daily heart rate data for a given date.
 *
 * @param date - The date to get heart rate data for, defaults to current date
 * @returns Heart rate data for the specified date
 * @throws Error if the operation fails
 *
 * @example
 * ```js
 * const heartRateData = await GCClient.getHeartRate(new Date('2020-03-24'));
 * ```
 */
async getHeartRate(date = new Date()): Promise<HeartRate>

高尔夫

/**
 * Retrieves golf summary data
 * @returns Summary of golf activities
 * @throws Error if golf summary data is invalid or empty
 */
async getGolfSummary(): Promise<GolfSummary>
/**
 * Retrieves golf scorecard for a specific round
 * @param scorecardId - ID of the scorecard to retrieve
 * @returns Golf scorecard data
 * @throws Error if golf scorecard data is invalid or empty
 */
async getGolfScorecard(scorecardId: number): Promise<GolfScorecard>

齿轮

/**
 * Returns the gear data for the user.
 * @param availableGearDate - Optional date to filter the gear available at the date (format: 'YYYY-MM-DD').
 */
async getGear(availableGearDate?: string): Promise<GearData[]>
/**
 * Returns the gear data assigned with a specific activity.
 * @param activityId
 */
async getGearsForActivity(activityId: GCActivityId): Promise<GearData[]>
/**
 * Links a gear item to an activity.
 * @param activityId
 * @param gearId - uuid field from GearData
 * @return GearData - the linked gear item data
 */
async linkGearToActivity(
    activityId: GCActivityId,
    gearId: GCGearId
): Promise<GearData>
/**
 * Unlinks a gear item from an activity.
 * @param activityId
 * @param gearId - uuid field from GearData
 * @return GearData - the unlinked gear item data
 */
async unlinkGearFromActivity(
    activityId: GCActivityId,
    gearId: GCGearId
): Promise<GearData>

GPX 和课程

/**
 * Imports GPX file content
 *
 * @example ./examples/example-gpx-file.js
 * @param fileName - Name of the GPX file
 * @param fileContent - Content of the GPX file as string
 * @returns Response from the GPX import operation containing courseName, geoPoints, and coursePoints
 *
 * @example
 * ```js
 * const fileContent = await fs.readFile('paris-marathon.gpx', 'utf8');
 * const response = await GCClient.importGpx('paris-marathon.gpx', fileContent);
 * // The response contains courseName, geoPoints, and coursePoints that can be used with createCourse
 * ```
 */
async importGpx(
    fileName: string,
    fileContent: string
): Promise<ImportedGpxResponse>

完整实例 : examples/example-gpx-file.js

/**
 * Creates a course from GPX data
 * You can get geoPoints and coursePoints from the imported GPX file response.
 *
 * @example ./examples/example-gpx-file.js
 * @param activityType - Type of activity for the course
 * @param courseName - Name of the course
 * @param geoPoints - Array of geographical points making up the course
 * @param coursePoints - Optional array of course points (waypoints)
 * @returns Response from the course creation operation containing the courseId
 *
 * @example
 * ```js
 * // First import GPX to get geoPoints and coursePoints
 * const response = await GCClient.importGpx('course.gpx', gpxFileContent);
 *
 * // Then create the course
 * const createCourseResponse = await GCClient.createCourse(
 *     1,  // activityType (1 = running)
 *     response.courseName,
 *     response.geoPoints,
 *     response.coursePoints
 * );
 *
 * console.log('Course created with id:', createCourseResponse.courseId);
 * ```
 */
async createCourse(
    activityType: GpxActivityType,
    courseName: string,
    geoPoints: GeoPoint[],
    coursePoints: CoursePoint[] = []
)

完整实例 : examples/example-gpx-file.js

/**
 * Lists all courses
 * @returns List of courses in ListCoursesResponse format
 *
 * @example
 * ```js
 * const listCourses = await GCClient.listCourses();
 * console.log(
 *     'Last course:',
 *     listCourses.coursesForUser[0].courseId,
 *     listCourses.coursesForUser[0].courseName
 * );
 * ```
 */
async listCourses(): Promise<ListCoursesResponse>

完整实例 : examples/example-gpx-file.js

/**
 * Get the details of a course
 * @param courseId - Course id
 * @returns Course details
 *
 * @example
 * ```js
 * const course = await GCClient.getCourseDetails(123456789);
 * console.log('Course name', course.courseName);
 * ```
 */
async getCourseDetails(
    courseId: string | number
): Promise<CourseDetailsResponse>

完整实例 : examples/example-gpx-file.js

/**
 * Edit course privacy
 * @param courseId - Course Id
 * @param privacy - Privacy setting for the course, use CoursePrivacyRule.PUBLIC (1) for public courses
 *                  or CoursePrivacyRule.PRIVATE (2) for private courses. Defaults to PRIVATE.
 * @returns Course details
 *
 * @example
 * ```js
 * // Make a course public
 * await GCClient.updateCoursePrivacy(courseId, 1);
 * ```
 */
async updateCoursePrivacy(
    courseId: string | number,
    privacy: CoursePrivacyRule = CoursePrivacyRule.PRIVATE
): Promise<CourseDetailsResponse>

完整实例 : examples/example-gpx-file.js

/**
 * Rename a course
 * @param courseId - Course Id
 * @param courseName - The new course name
 * @returns Course details
 *
 * @example
 * ```js
 * await GCClient.renameCourse(courseId, 'My new course name');
 * ```
 */
async renameCourse(
    courseId: string | number,
    courseName: string
): Promise<CourseDetailsResponse>
/**
 * Complete update of a course
 * @param courseRequest - the full data of the course. Use getCourseDetails to get the existing set
 * @returns Course details updated
 *
 * @example
 * ```js
 * const course = await GCClient.getCourseDetails(courseId);
 * await GCClient.updateCourse({ ...course, description: 'Updated description' });
 * ```
 */
async updateCourse(
    courseRequest: CourseDetailsRequest
): Promise<CourseDetailsResponse>
/**
 * Exports a course as GPX file content
 * @param courseId - ID of the course to export
 * @returns GPX file content as string
 *
 * @example
 * ```js
 * const downloadGpx = await GCClient.exportCourseAsGpx(courseId);
 * console.log('Downloaded GPX size:', downloadGpx.length);
 * ```
 */
async exportCourseAsGpx(courseId: number): Promise<string>

完整实例 : examples/example-gpx-file.js

日历

/**
 * Retrieves calendar events for a specific year.
 * @param year {number} - The year for which to retrieve calendar events.
 */
async getYearCalendarEvents(year: number): Promise<YearCalendar>
/**
 * Retrieves calendar events for a specific month and year.
 * @param year {number} - The year for which to retrieve calendar events.
 * @param month {number} - The month (0-11) for which to retrieve calendar events.
 */
async getMonthCalendarEvents(
    year: number,
    month: number
): Promise<MonthCalendar>
/**
 * Retrieves calendar events for a specific week containing the given date.
 * @param year {number} - The year of the date.
 * @param month {number} - The month (0-11) of the date.
 * @param day {number} - The day of the first day of the week.
 * @param firstDayOfWeek {number} - Optional first day of the week, default is 1
 */
async getWeekCalendarEvents(
    year: number,
    month: number,
    day: number,
    firstDayOfWeek?: number
): Promise<any>

自定义请求

库为 Garmin 连接 API 提供自定义请求的方法 :

/**
 * Performs a GET request to the specified URL
 * @param url - URL to send the request to
 * @param data - Optional query parameters or request configuration
 * @returns Response data of type T
 */
async get<T>(url: string, data?: any)
/**
 * Performs a POST request to the specified URL
 * @param url - URL to send the request to
 * @param data - Data to send in the request body
 * @returns Response data of type T
 */
async post<T>(url: string, data: any)
/**
 * Performs a PUT request to the specified URL
 * @param url - URL to send the request to
 * @param data - Data to send in the request body
 * @returns Response data of type T
 */
async put<T>(url: string, data: any)

版本与发布记录

@flow-js/garmin-connect 共发布 20 个版本,首次发布于 2025/10/20;过去 12 个月发布了 15 个版本。最新版本附带 npm provenance 构建来源证明,可追溯到公开的 CI 构建记录。

版本发布日期距今
1.6.25latest2026/11/0312 天前
1.6.242026/10/051 个月前
1.6.232026/10/051 个月前
1.6.222026/09/231 个月前
1.6.212026/09/231 个月前
1.6.202026/09/231 个月前

关于 @flow-js/garmin-connect 的常见问题

@flow-js/garmin-connect 是什么?

让与 Garmin Connect 接口以获取或设置任何数据点变得简单

如何安装 @flow-js/garmin-connect?

在项目目录运行 npm install @flow-js/garmin-connect,或使用 pnpm add / yarn add / bun add。

@flow-js/garmin-connect 支持 TypeScript 吗?

支持。包内自带 TypeScript 类型声明(package.json 声明了 types 入口),安装后即可获得类型提示,无需再安装 @types 包。

@flow-js/garmin-connect 支持 ESM 还是 CommonJS?

以 CommonJS 形式发布,可以直接 require();在 ES Module 项目中也可以用 import 引入(Node.js 会把 module.exports 作为默认导出)。

@flow-js/garmin-connect 可以商用吗?

@flow-js/garmin-connect 使用 MIT 许可。宽松许可:允许商业使用、修改和再分发,通常只需在分发时保留原版权与许可声明。以上为概括,不构成法律意见,请以许可原文为准。

@flow-js/garmin-connect 的下载量有多少?

根据 npm 官方下载统计,@flow-js/garmin-connect 在 2026/10/15 – 2026/11/13 这 30 天内被下载 4,163 次,日均约 139 次。下载量会把 CI 构建、镜像同步和作为其他包依赖的安装一并计入,适合横向比较热度,不能直接等同于使用人数。

@flow-js/garmin-connect 还在维护吗?

最新版本 1.6.25 发布于 2026/11/03(12 天前);至今共发布 20 个版本,其中过去 12 个月发布了 15 个;首次发布于 2025/10/20。发布频率只是参考信号:功能稳定的工具可能很少需要更新,建议结合源码仓库的 issue 和提交记录判断。