winstore-startup 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Raghvendra Yadav
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,218 @@
1
+ # winstore-startup
2
+
3
+ A Node.js native addon for managing Windows Store/UWP application startup tasks. This library provides programmatic control over whether your application automatically launches when Windows starts.
4
+
5
+ ## Features
6
+
7
+ - Enable/disable startup tasks for Windows Store apps
8
+ - Query current startup task state
9
+ - Non-blocking async API (Promise-based)
10
+ - Optional task ID (automatically uses first task if not specified)
11
+ - TypeScript support with full type definitions
12
+ - Graceful error handling with descriptive messages
13
+
14
+ ## Requirements
15
+
16
+ - **OS:** Windows only
17
+ - **Node.js:** >= 20.0.0
18
+ - **Architecture:** x64 or arm64
19
+
20
+ ## Installation
21
+
22
+ ```bash
23
+ npm install winstore-startup
24
+ ```
25
+
26
+ The native addon is automatically compiled during installation.
27
+
28
+ ## Setup
29
+
30
+ Before using this library, you must declare a startup task in your `AppxManifest.xml`. The library only manages existing startup tasks - it doesn't create them.
31
+
32
+ ### AppxManifest.xml Configuration
33
+
34
+ Add the `desktop` namespace to your Package element:
35
+
36
+ ```xml
37
+ <Package
38
+ xmlns="http://schemas.microsoft.com/appx/manifest/foundation/windows10"
39
+ xmlns:desktop="http://schemas.microsoft.com/appx/manifest/desktop/windows10"
40
+ ...>
41
+ ```
42
+
43
+ Then add the startup task extension inside your Application element:
44
+
45
+ ```xml
46
+ <Applications>
47
+ <Application Id="MyApp" Executable="app\MyApp.exe" EntryPoint="Windows.FullTrustApplication">
48
+ ...
49
+ <Extensions>
50
+ <desktop:Extension
51
+ Category="windows.startupTask"
52
+ Executable="app\MyApp.exe"
53
+ EntryPoint="Windows.FullTrustApplication">
54
+ <desktop:StartupTask TaskId="MyStartupTask" Enabled="false" DisplayName="My App" />
55
+ </desktop:Extension>
56
+ </Extensions>
57
+ </Application>
58
+ </Applications>
59
+ ```
60
+
61
+ **Note:** The `TaskId` is what you pass to `enable('MyStartupTask')`. If you only have one task, you can call `enable()` without arguments and it will auto-select it.
62
+
63
+ ## Usage
64
+
65
+ ### Basic Example
66
+
67
+ ```javascript
68
+ const { enable, disable, getState } = require('winstore-startup');
69
+
70
+ async function manageStartup() {
71
+ try {
72
+ // Enable auto-launch (uses first startup task automatically)
73
+ await enable();
74
+
75
+ // Check current state
76
+ const state = await getState();
77
+ console.log(state); // 2 = Enabled
78
+
79
+ // Disable auto-launch
80
+ await disable();
81
+ } catch (error) {
82
+ console.error('Failed to manage startup:', error.message);
83
+ }
84
+ }
85
+
86
+ manageStartup();
87
+ ```
88
+
89
+ ### With Specific Task ID
90
+
91
+ ```javascript
92
+ const { enable, disable, getState } = require('winstore-startup');
93
+
94
+ async function manageSpecificTask() {
95
+ // Enable a specific task
96
+ await enable('MyTaskId');
97
+
98
+ // Get state of a specific task
99
+ const state = await getState('MyTaskId');
100
+
101
+ // Disable a specific task
102
+ await disable('MyTaskId');
103
+ }
104
+ ```
105
+
106
+ ### List All Startup Tasks
107
+
108
+ ```javascript
109
+ const { getForCurrentPackage, StartupTaskState } = require('winstore-startup');
110
+
111
+ async function listTasks() {
112
+ const tasks = await getForCurrentPackage();
113
+
114
+ for (const task of tasks) {
115
+ console.log(`Task: ${task.taskId}, State: ${task.state}`);
116
+ }
117
+ }
118
+ ```
119
+
120
+ ### TypeScript
121
+
122
+ ```typescript
123
+ import {
124
+ enable,
125
+ disable,
126
+ getState,
127
+ getForCurrentPackage,
128
+ StartupTaskState,
129
+ } from 'winstore-startup';
130
+
131
+ async function manageStartup(): Promise<void> {
132
+ try {
133
+ // Enable startup (uses first task if no ID provided)
134
+ const result = await enable();
135
+ if (result === StartupTaskState.Enabled) {
136
+ console.log('Startup enabled');
137
+ }
138
+
139
+ // With specific task ID
140
+ await enable('myTaskId');
141
+
142
+ // Get all tasks
143
+ const tasks = await getForCurrentPackage();
144
+ console.log(tasks);
145
+ } catch (error) {
146
+ console.error('Operation failed:', error);
147
+ }
148
+ }
149
+ ```
150
+
151
+ ## API Reference
152
+
153
+ ### Functions
154
+
155
+ | Function | Description | Returns |
156
+ | ------------------------ | --------------------------------- | ---------------------------- |
157
+ | `enable(taskId?)` | Enable a startup task | `Promise<StartupTaskState>` |
158
+ | `disable(taskId?)` | Disable a startup task | `Promise<void>` |
159
+ | `getState(taskId?)` | Get the current state of a task | `Promise<StartupTaskState>` |
160
+ | `getForCurrentPackage()` | Get all startup tasks for the app | `Promise<StartupTaskInfo[]>` |
161
+
162
+ All functions return Promises and accept an optional `taskId` parameter (except `getForCurrentPackage`). If `taskId` is not provided, the first startup task from the current package is used automatically.
163
+
164
+ ### StartupTaskState Enum
165
+
166
+ | Value | Name | Description |
167
+ | ----- | ------------------ | --------------------------------- |
168
+ | 0 | `Disabled` | Task is disabled |
169
+ | 1 | `DisabledByUser` | Task was disabled by the user |
170
+ | 2 | `Enabled` | Task is enabled |
171
+ | 3 | `DisabledByPolicy` | Task is disabled by system policy |
172
+ | 4 | `EnabledByPolicy` | Task is enabled by system policy |
173
+
174
+ ### StartupTaskInfo Interface
175
+
176
+ ```typescript
177
+ interface StartupTaskInfo {
178
+ taskId: string;
179
+ state: StartupTaskState;
180
+ }
181
+ ```
182
+
183
+ ### Error Handling
184
+
185
+ All functions throw errors with descriptive messages when:
186
+
187
+ - No startup task is found in the app manifest
188
+ - The specified task ID doesn't exist
189
+ - The operation fails at the Windows API level
190
+ - Running on a non-Windows platform
191
+
192
+ ```javascript
193
+ try {
194
+ await enable();
195
+ } catch (error) {
196
+ // Handle error - e.g., "No startup task found. Ensure your app manifest includes a startup task declaration."
197
+ console.error(error.message);
198
+ }
199
+ ```
200
+
201
+ ## How It Works
202
+
203
+ This library uses the Windows Runtime (WinRT) `StartupTask` API to manage application startup behavior. It compiles a native C++ addon using Node-API that bridges JavaScript to the Windows APIs.
204
+
205
+ All operations are non-blocking - they run on a separate thread and return Promises, ensuring your Node.js event loop stays responsive.
206
+
207
+ On non-Windows platforms, the functions reject with an error message indicating the platform is not supported.
208
+
209
+ ## Scripts
210
+
211
+ ```bash
212
+ npm run build # Rebuild the native addon
213
+ npm run clean # Clean build artifacts
214
+ ```
215
+
216
+ ## License
217
+
218
+ MIT
package/binding.gyp ADDED
@@ -0,0 +1,28 @@
1
+ {
2
+ "targets": [
3
+ {
4
+ "target_name": "winstore_startup",
5
+ "cflags!": ["-fno-exceptions"],
6
+ "cflags_cc!": ["-fno-exceptions"],
7
+ "sources": ["startup_task.cpp"],
8
+ "include_dirs": [
9
+ "<!@(node -p \"require('node-addon-api').include\")"
10
+ ],
11
+ "conditions": [
12
+ [
13
+ "OS=='win'",
14
+ {
15
+ "msvs_settings": {
16
+ "VCCLCompilerTool": {
17
+ "AdditionalOptions": ["/std:c++20"],
18
+ "ExceptionHandling": 1
19
+ }
20
+ },
21
+ "msvs_version": "auto",
22
+ "libraries": ["windowsapp.lib"]
23
+ }
24
+ ]
25
+ ]
26
+ }
27
+ ]
28
+ }
package/index.d.ts ADDED
@@ -0,0 +1,41 @@
1
+ export enum StartupTaskState {
2
+ Disabled = 0,
3
+ DisabledByUser = 1,
4
+ Enabled = 2,
5
+ DisabledByPolicy = 3,
6
+ EnabledByPolicy = 4,
7
+ }
8
+
9
+ export interface StartupTaskInfo {
10
+ taskId: string;
11
+ state: StartupTaskState;
12
+ }
13
+
14
+ /**
15
+ * Enable a startup task
16
+ * @param taskId - The startup task ID (optional, uses first task if not provided)
17
+ * @returns The resulting state
18
+ * @throws {Error} If no startup task is found or operation fails
19
+ */
20
+ export function enable(taskId?: string): Promise<StartupTaskState>;
21
+
22
+ /**
23
+ * Disable a startup task
24
+ * @param taskId - The startup task ID (optional, uses first task if not provided)
25
+ * @throws {Error} If no startup task is found or operation fails
26
+ */
27
+ export function disable(taskId?: string): Promise<void>;
28
+
29
+ /**
30
+ * Get state of a startup task
31
+ * @param taskId - The startup task ID (optional, uses first task if not provided)
32
+ * @returns The current state
33
+ * @throws {Error} If no startup task is found or operation fails
34
+ */
35
+ export function getState(taskId?: string): Promise<StartupTaskState>;
36
+
37
+ /**
38
+ * Get all startup tasks for the current package
39
+ * @returns Array of startup task information
40
+ */
41
+ export function getForCurrentPackage(): Promise<StartupTaskInfo[]>;
package/index.js ADDED
@@ -0,0 +1,85 @@
1
+ const binding = global.__WINSTORE_STARTUP_MOCK_BINDING__ || require('node-gyp-build')(__dirname);
2
+
3
+ /**
4
+ * Startup task states
5
+ */
6
+ const StartupTaskState = {
7
+ Disabled: 0,
8
+ DisabledByUser: 1,
9
+ Enabled: 2,
10
+ DisabledByPolicy: 3,
11
+ EnabledByPolicy: 4,
12
+ };
13
+
14
+ /**
15
+ * Get the first task ID from the current package
16
+ * @returns {Promise<string|null>}
17
+ */
18
+ async function getFirstTaskId() {
19
+ const tasks = await binding.getForCurrentPackage();
20
+ return tasks.length > 0 ? tasks[0].taskId : null;
21
+ }
22
+
23
+ /**
24
+ * Enable a startup task
25
+ * @param {string} [taskId] - The startup task ID (optional, uses first task if not provided)
26
+ * @returns {Promise<number>} The resulting state
27
+ * @throws {Error} If no startup task is found or operation fails
28
+ */
29
+ async function enable(taskId) {
30
+ const id = taskId || (await getFirstTaskId());
31
+ if (!id) {
32
+ throw new Error(
33
+ 'No startup task found. Ensure your app manifest includes a startup task declaration.',
34
+ );
35
+ }
36
+ return binding.enable(id);
37
+ }
38
+
39
+ /**
40
+ * Disable a startup task
41
+ * @param {string} [taskId] - The startup task ID (optional, uses first task if not provided)
42
+ * @returns {Promise<void>}
43
+ * @throws {Error} If no startup task is found or operation fails
44
+ */
45
+ async function disable(taskId) {
46
+ const id = taskId || (await getFirstTaskId());
47
+ if (!id) {
48
+ throw new Error(
49
+ 'No startup task found. Ensure your app manifest includes a startup task declaration.',
50
+ );
51
+ }
52
+ return binding.disable(id);
53
+ }
54
+
55
+ /**
56
+ * Get state of a startup task
57
+ * @param {string} [taskId] - The startup task ID (optional, uses first task if not provided)
58
+ * @returns {Promise<number>} The current state
59
+ * @throws {Error} If no startup task is found or operation fails
60
+ */
61
+ async function getState(taskId) {
62
+ const id = taskId || (await getFirstTaskId());
63
+ if (!id) {
64
+ throw new Error(
65
+ 'No startup task found. Ensure your app manifest includes a startup task declaration.',
66
+ );
67
+ }
68
+ return binding.getState(id);
69
+ }
70
+
71
+ /**
72
+ * Get all startup tasks for the current package
73
+ * @returns {Promise<Array<{taskId: string, state: number}>>}
74
+ */
75
+ async function getForCurrentPackage() {
76
+ return binding.getForCurrentPackage();
77
+ }
78
+
79
+ module.exports = {
80
+ enable,
81
+ disable,
82
+ getState,
83
+ getForCurrentPackage,
84
+ StartupTaskState,
85
+ };
package/lib/binding.js ADDED
@@ -0,0 +1,18 @@
1
+ // Allow tests to inject a mock binding
2
+ let binding = global.__WINSTORE_STARTUP_MOCK_BINDING__;
3
+
4
+ if (!binding) {
5
+ try {
6
+ binding = require('../build/Release/winstore_startup.node');
7
+ } catch (e) {
8
+ // Fallback for development or non-Windows platforms
9
+ binding = {
10
+ enable: () => Promise.reject(new Error('Not supported on this platform')),
11
+ disable: () => Promise.reject(new Error('Not supported on this platform')),
12
+ getState: () => Promise.reject(new Error('Not supported on this platform')),
13
+ getForCurrentPackage: () => Promise.resolve([]),
14
+ };
15
+ }
16
+ }
17
+
18
+ module.exports = binding;
package/package.json ADDED
@@ -0,0 +1,67 @@
1
+ {
2
+ "name": "winstore-startup",
3
+ "version": "0.1.0",
4
+ "description": "Windows Store startup task management using C++/WinRT",
5
+ "keywords": [
6
+ "addon",
7
+ "autostart",
8
+ "native",
9
+ "startup",
10
+ "startup-task",
11
+ "uwp",
12
+ "windows",
13
+ "windows-store",
14
+ "winrt"
15
+ ],
16
+ "license": "MIT",
17
+ "author": {
18
+ "name": "Raghvendra Yadav",
19
+ "email": "raghvendraa.dev@gmail.com"
20
+ },
21
+ "repository": {
22
+ "type": "git",
23
+ "url": "https://github.com/aspect-dev/winstore-startup.git"
24
+ },
25
+ "files": [
26
+ "index.js",
27
+ "index.d.ts",
28
+ "startup_task.cpp",
29
+ "binding.gyp",
30
+ "lib",
31
+ "prebuilds"
32
+ ],
33
+ "os": [
34
+ "win32"
35
+ ],
36
+ "cpu": [
37
+ "x64",
38
+ "arm64"
39
+ ],
40
+ "main": "index.js",
41
+ "types": "index.d.ts",
42
+ "scripts": {
43
+ "install": "node-gyp-build",
44
+ "prebuild": "prebuildify --napi --strip",
45
+ "prebuild:all": "prebuildify --napi --strip --arch x64 && prebuildify --napi --strip --arch arm64",
46
+ "fmt": "oxfmt",
47
+ "fmt:check": "oxfmt --check",
48
+ "test": "vitest run",
49
+ "test:watch": "vitest",
50
+ "test:coverage": "vitest run --coverage",
51
+ "clean": "git clean -fx ./build ./prebuilds ./node_modules"
52
+ },
53
+ "dependencies": {
54
+ "node-addon-api": "^8.5.0",
55
+ "node-gyp-build": "^4.8.4"
56
+ },
57
+ "devDependencies": {
58
+ "oxfmt": "^0.36.0",
59
+ "oxlint": "^1.51.0",
60
+ "prebuildify": "^6.0.1",
61
+ "vitest": "^4.0.18"
62
+ },
63
+ "engines": {
64
+ "node": ">=20.0.0"
65
+ },
66
+ "gypfile": true
67
+ }
@@ -0,0 +1,276 @@
1
+ // startup_task.cpp - WinRT-based startup task addon for Windows Store apps
2
+ #include <napi.h>
3
+ #include <optional>
4
+ #include <string>
5
+
6
+ #ifdef _WIN32
7
+ #include <winrt/Windows.ApplicationModel.h>
8
+ #include <winrt/Windows.Foundation.h>
9
+ #include <winrt/Windows.Foundation.Collections.h>
10
+
11
+ using namespace winrt;
12
+ using namespace Windows::ApplicationModel;
13
+ using namespace Windows::Foundation;
14
+
15
+ // Initialize WinRT apartment on module load
16
+ struct WinRTInitializer {
17
+ WinRTInitializer() {
18
+ winrt::init_apartment();
19
+ }
20
+ ~WinRTInitializer() {
21
+ winrt::uninit_apartment();
22
+ }
23
+ };
24
+
25
+ static WinRTInitializer g_winrt_init;
26
+
27
+ // Startup task states (matches Windows.ApplicationModel.StartupTaskState)
28
+ // 0 = Disabled, 1 = DisabledByUser, 2 = Enabled, 3 = DisabledByPolicy, 4 = EnabledByPolicy
29
+
30
+ // Helper function to validate and extract taskId parameter
31
+ std::optional<std::string> GetTaskIdParam(const Napi::CallbackInfo& info) {
32
+ auto env = info.Env();
33
+
34
+ if (info.Length() < 1 || !info[0].IsString()) {
35
+ Napi::TypeError::New(env, "Task ID string expected").ThrowAsJavaScriptException();
36
+ return std::nullopt;
37
+ }
38
+
39
+ std::string taskId = info[0].As<Napi::String>().Utf8Value();
40
+ if (taskId.empty()) {
41
+ Napi::TypeError::New(env, "Task ID cannot be empty").ThrowAsJavaScriptException();
42
+ return std::nullopt;
43
+ }
44
+
45
+ return taskId;
46
+ }
47
+
48
+ // Async worker for Enable operation
49
+ class EnableWorker : public Napi::AsyncWorker {
50
+ public:
51
+ EnableWorker(Napi::Env env, Napi::Promise::Deferred deferred, std::string taskId)
52
+ : Napi::AsyncWorker(env), deferred_(deferred), taskId_(taskId), state_(-1) {}
53
+
54
+ void Execute() override {
55
+ try {
56
+ auto task = StartupTask::GetAsync(winrt::to_hstring(taskId_)).get();
57
+ state_ = static_cast<int>(task.RequestEnableAsync().get());
58
+ } catch (const winrt::hresult_error& e) {
59
+ SetError(winrt::to_string(e.message()));
60
+ }
61
+ }
62
+
63
+ void OnOK() override {
64
+ deferred_.Resolve(Napi::Number::New(Env(), state_));
65
+ }
66
+
67
+ void OnError(const Napi::Error& error) override {
68
+ deferred_.Reject(error.Value());
69
+ }
70
+
71
+ private:
72
+ Napi::Promise::Deferred deferred_;
73
+ std::string taskId_;
74
+ int state_;
75
+ };
76
+
77
+ // Async worker for Disable operation
78
+ class DisableWorker : public Napi::AsyncWorker {
79
+ public:
80
+ DisableWorker(Napi::Env env, Napi::Promise::Deferred deferred, std::string taskId)
81
+ : Napi::AsyncWorker(env), deferred_(deferred), taskId_(taskId) {}
82
+
83
+ void Execute() override {
84
+ try {
85
+ auto task = StartupTask::GetAsync(winrt::to_hstring(taskId_)).get();
86
+ task.Disable();
87
+ } catch (const winrt::hresult_error& e) {
88
+ SetError(winrt::to_string(e.message()));
89
+ }
90
+ }
91
+
92
+ void OnOK() override {
93
+ deferred_.Resolve(Env().Undefined());
94
+ }
95
+
96
+ void OnError(const Napi::Error& error) override {
97
+ deferred_.Reject(error.Value());
98
+ }
99
+
100
+ private:
101
+ Napi::Promise::Deferred deferred_;
102
+ std::string taskId_;
103
+ };
104
+
105
+ // Async worker for GetState operation
106
+ class GetStateWorker : public Napi::AsyncWorker {
107
+ public:
108
+ GetStateWorker(Napi::Env env, Napi::Promise::Deferred deferred, std::string taskId)
109
+ : Napi::AsyncWorker(env), deferred_(deferred), taskId_(taskId), state_(-1) {}
110
+
111
+ void Execute() override {
112
+ try {
113
+ auto task = StartupTask::GetAsync(winrt::to_hstring(taskId_)).get();
114
+ state_ = static_cast<int>(task.State());
115
+ } catch (const winrt::hresult_error& e) {
116
+ SetError(winrt::to_string(e.message()));
117
+ }
118
+ }
119
+
120
+ void OnOK() override {
121
+ deferred_.Resolve(Napi::Number::New(Env(), state_));
122
+ }
123
+
124
+ void OnError(const Napi::Error& error) override {
125
+ deferred_.Reject(error.Value());
126
+ }
127
+
128
+ private:
129
+ Napi::Promise::Deferred deferred_;
130
+ std::string taskId_;
131
+ int state_;
132
+ };
133
+
134
+ // Async worker for GetForCurrentPackage operation
135
+ struct TaskInfo {
136
+ std::string taskId;
137
+ int state;
138
+ };
139
+
140
+ class GetForCurrentPackageWorker : public Napi::AsyncWorker {
141
+ public:
142
+ GetForCurrentPackageWorker(Napi::Env env, Napi::Promise::Deferred deferred)
143
+ : Napi::AsyncWorker(env), deferred_(deferred) {}
144
+
145
+ void Execute() override {
146
+ try {
147
+ auto tasks = StartupTask::GetForCurrentPackageAsync().get();
148
+ for (auto const& task : tasks) {
149
+ TaskInfo info;
150
+ info.taskId = winrt::to_string(task.TaskId());
151
+ info.state = static_cast<int>(task.State());
152
+ tasks_.push_back(info);
153
+ }
154
+ } catch (const winrt::hresult_error& e) {
155
+ SetError(winrt::to_string(e.message()));
156
+ }
157
+ }
158
+
159
+ void OnOK() override {
160
+ auto env = Env();
161
+ auto arr = Napi::Array::New(env, tasks_.size());
162
+
163
+ for (size_t i = 0; i < tasks_.size(); i++) {
164
+ auto obj = Napi::Object::New(env);
165
+ obj.Set("taskId", Napi::String::New(env, tasks_[i].taskId));
166
+ obj.Set("state", Napi::Number::New(env, tasks_[i].state));
167
+ arr[static_cast<uint32_t>(i)] = obj;
168
+ }
169
+
170
+ deferred_.Resolve(arr);
171
+ }
172
+
173
+ void OnError(const Napi::Error& error) override {
174
+ deferred_.Reject(error.Value());
175
+ }
176
+
177
+ private:
178
+ Napi::Promise::Deferred deferred_;
179
+ std::vector<TaskInfo> tasks_;
180
+ };
181
+
182
+ Napi::Value Enable(const Napi::CallbackInfo& info) {
183
+ auto env = info.Env();
184
+ auto taskIdOpt = GetTaskIdParam(info);
185
+
186
+ if (!taskIdOpt.has_value()) {
187
+ return env.Undefined();
188
+ }
189
+
190
+ auto deferred = Napi::Promise::Deferred::New(env);
191
+ auto worker = new EnableWorker(env, deferred, taskIdOpt.value());
192
+ worker->Queue();
193
+
194
+ return deferred.Promise();
195
+ }
196
+
197
+ Napi::Value Disable(const Napi::CallbackInfo& info) {
198
+ auto env = info.Env();
199
+ auto taskIdOpt = GetTaskIdParam(info);
200
+
201
+ if (!taskIdOpt.has_value()) {
202
+ return env.Undefined();
203
+ }
204
+
205
+ auto deferred = Napi::Promise::Deferred::New(env);
206
+ auto worker = new DisableWorker(env, deferred, taskIdOpt.value());
207
+ worker->Queue();
208
+
209
+ return deferred.Promise();
210
+ }
211
+
212
+ Napi::Value GetState(const Napi::CallbackInfo& info) {
213
+ auto env = info.Env();
214
+ auto taskIdOpt = GetTaskIdParam(info);
215
+
216
+ if (!taskIdOpt.has_value()) {
217
+ return env.Undefined();
218
+ }
219
+
220
+ auto deferred = Napi::Promise::Deferred::New(env);
221
+ auto worker = new GetStateWorker(env, deferred, taskIdOpt.value());
222
+ worker->Queue();
223
+
224
+ return deferred.Promise();
225
+ }
226
+
227
+ Napi::Value GetForCurrentPackage(const Napi::CallbackInfo& info) {
228
+ auto env = info.Env();
229
+
230
+ auto deferred = Napi::Promise::Deferred::New(env);
231
+ auto worker = new GetForCurrentPackageWorker(env, deferred);
232
+ worker->Queue();
233
+
234
+ return deferred.Promise();
235
+ }
236
+
237
+ #else
238
+ // Non-Windows stubs (return rejected promises for consistency)
239
+ Napi::Value Enable(const Napi::CallbackInfo& info) {
240
+ auto env = info.Env();
241
+ auto deferred = Napi::Promise::Deferred::New(env);
242
+ deferred.Reject(Napi::Error::New(env, "Not supported on this platform").Value());
243
+ return deferred.Promise();
244
+ }
245
+
246
+ Napi::Value Disable(const Napi::CallbackInfo& info) {
247
+ auto env = info.Env();
248
+ auto deferred = Napi::Promise::Deferred::New(env);
249
+ deferred.Reject(Napi::Error::New(env, "Not supported on this platform").Value());
250
+ return deferred.Promise();
251
+ }
252
+
253
+ Napi::Value GetState(const Napi::CallbackInfo& info) {
254
+ auto env = info.Env();
255
+ auto deferred = Napi::Promise::Deferred::New(env);
256
+ deferred.Reject(Napi::Error::New(env, "Not supported on this platform").Value());
257
+ return deferred.Promise();
258
+ }
259
+
260
+ Napi::Value GetForCurrentPackage(const Napi::CallbackInfo& info) {
261
+ auto env = info.Env();
262
+ auto deferred = Napi::Promise::Deferred::New(env);
263
+ deferred.Resolve(Napi::Array::New(env, 0));
264
+ return deferred.Promise();
265
+ }
266
+ #endif
267
+
268
+ Napi::Object Init(Napi::Env env, Napi::Object exports) {
269
+ exports.Set("enable", Napi::Function::New(env, Enable));
270
+ exports.Set("disable", Napi::Function::New(env, Disable));
271
+ exports.Set("getState", Napi::Function::New(env, GetState));
272
+ exports.Set("getForCurrentPackage", Napi::Function::New(env, GetForCurrentPackage));
273
+ return exports;
274
+ }
275
+
276
+ NODE_API_MODULE(winstore_startup, Init)