@warp-drive/holodeck 0.1.0-alpha.66 → 0.1.0-alpha.70
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/CHANGELOG.md +139 -0
- package/dist/index.js.map +1 -1
- package/package.json +13 -17
- package/server/bun.js +19 -14
- package/server/node.js +22 -16
package/CHANGELOG.md
ADDED
|
@@ -0,0 +1,139 @@
|
|
|
1
|
+
# @warp-drive/holodeck Changelog
|
|
2
|
+
|
|
3
|
+
## v5.8.0 (2025-10-07)
|
|
4
|
+
|
|
5
|
+
#### :rocket: Enhancement
|
|
6
|
+
|
|
7
|
+
* [#10121](https://github.com/warp-drive-data/warp-drive/pull/10121) feat: legacy ModelFragments support ([@RobbieTheWagner](https://github.com/RobbieTheWagner))
|
|
8
|
+
|
|
9
|
+
#### :house: Internal
|
|
10
|
+
|
|
11
|
+
* [#10377](https://github.com/warp-drive-data/warp-drive/pull/10377) chore: refactor holodeck to use node ([@runspired](https://github.com/runspired))
|
|
12
|
+
* [#10376](https://github.com/warp-drive-data/warp-drive/pull/10376) chore: prepare holodeck for publishing ([@runspired](https://github.com/runspired))
|
|
13
|
+
* [#10375](https://github.com/warp-drive-data/warp-drive/pull/10375) chore: make non-GET holodeck replay work ([@runspired](https://github.com/runspired))
|
|
14
|
+
* [#10373](https://github.com/warp-drive-data/warp-drive/pull/10373) chore: add holodeck client support for PUT/PATCH/POST/DELETE ([@runspired](https://github.com/runspired))
|
|
15
|
+
* [#10372](https://github.com/warp-drive-data/warp-drive/pull/10372) Missing Context Param in Code Example for setTestId ([@lucasxzh](https://github.com/lucasxzh))
|
|
16
|
+
* [#10349](https://github.com/warp-drive-data/warp-drive/pull/10349) chore: update all emberjs/data links to warp-drive-data/warp-drive ([@runspired](https://github.com/runspired))
|
|
17
|
+
|
|
18
|
+
#### Committers: (3)
|
|
19
|
+
|
|
20
|
+
Robbie Wagner ([@RobbieTheWagner](https://github.com/RobbieTheWagner))
|
|
21
|
+
Chris Thoburn ([@runspired](https://github.com/runspired))
|
|
22
|
+
[@lucasxzh](https://github.com/lucasxzh)
|
|
23
|
+
|
|
24
|
+
## v5.7.0 (2025-08-26)
|
|
25
|
+
|
|
26
|
+
#### :house: Internal
|
|
27
|
+
|
|
28
|
+
* [#10279](https://github.com/warp-drive-data/warp-drive/pull/10279) chore: add support for LegacyNetworkHandler to holodeck ([@runspired](https://github.com/runspired))
|
|
29
|
+
* [#10226](https://github.com/warp-drive-data/warp-drive/pull/10226) chore: use https for diagnostic by default, print url last ([@runspired](https://github.com/runspired))
|
|
30
|
+
* [#10124](https://github.com/warp-drive-data/warp-drive/pull/10124) chore: mark a few types as private ([@runspired](https://github.com/runspired))
|
|
31
|
+
|
|
32
|
+
#### Committers: (1)
|
|
33
|
+
|
|
34
|
+
Chris Thoburn ([@runspired](https://github.com/runspired))
|
|
35
|
+
|
|
36
|
+
## v5.6.0 (2025-07-01)
|
|
37
|
+
|
|
38
|
+
#### :memo: Documentation
|
|
39
|
+
|
|
40
|
+
* [#9991](https://github.com/warp-drive-data/warp-drive/pull/9991) chore: improve output of typedoc ([@runspired](https://github.com/runspired))
|
|
41
|
+
|
|
42
|
+
#### :house: Internal
|
|
43
|
+
|
|
44
|
+
* [#10042](https://github.com/warp-drive-data/warp-drive/pull/10042) chore: upgrade to vite7 ([@runspired](https://github.com/runspired))
|
|
45
|
+
* [#10040](https://github.com/warp-drive-data/warp-drive/pull/10040) chore: isolated declarations ([@runspired](https://github.com/runspired))
|
|
46
|
+
|
|
47
|
+
#### Committers: (1)
|
|
48
|
+
|
|
49
|
+
Chris Thoburn ([@runspired](https://github.com/runspired))
|
|
50
|
+
|
|
51
|
+
## v5.4.0 (2025-04-11)
|
|
52
|
+
|
|
53
|
+
#### :memo: Documentation
|
|
54
|
+
|
|
55
|
+
* [#9648](https://github.com/warp-drive-data/warp-drive/pull/9648) docs: cleanup usage pattern for RequestManager configuration on store ([@runspired](https://github.com/runspired))
|
|
56
|
+
|
|
57
|
+
#### :rocket: Enhancement
|
|
58
|
+
|
|
59
|
+
* [#9530](https://github.com/warp-drive-data/warp-drive/pull/9530) feat: <:idle> state for Requests ([@runspired](https://github.com/runspired))
|
|
60
|
+
* [#9503](https://github.com/warp-drive-data/warp-drive/pull/9503) feat: request deduping & <Request /> invalidate subscriptions ([@runspired](https://github.com/runspired))
|
|
61
|
+
|
|
62
|
+
#### :bug: Bug Fix
|
|
63
|
+
|
|
64
|
+
* [#9530](https://github.com/warp-drive-data/warp-drive/pull/9530) feat: <:idle> state for Requests ([@runspired](https://github.com/runspired))
|
|
65
|
+
|
|
66
|
+
#### :house: Internal
|
|
67
|
+
|
|
68
|
+
* [#9759](https://github.com/warp-drive-data/warp-drive/pull/9759) chore: Improve contributing experience ([@runspired](https://github.com/runspired))
|
|
69
|
+
* [#9758](https://github.com/warp-drive-data/warp-drive/pull/9758) chore: update contributing docs ([@runspired](https://github.com/runspired))
|
|
70
|
+
* [#9752](https://github.com/warp-drive-data/warp-drive/pull/9752) chore: tooling upgrades to support WarpDrive package unification ([@runspired](https://github.com/runspired))
|
|
71
|
+
* [#9705](https://github.com/warp-drive-data/warp-drive/pull/9705) chore: make diagnostic shutdown safer, use bun for holodeck server ([@runspired](https://github.com/runspired))
|
|
72
|
+
* [#9699](https://github.com/warp-drive-data/warp-drive/pull/9699) chore: update to pnpm 10 ([@runspired](https://github.com/runspired))
|
|
73
|
+
* [#9629](https://github.com/warp-drive-data/warp-drive/pull/9629) fix: restore * versions and setup publish to not overwrite them ([@runspired](https://github.com/runspired))
|
|
74
|
+
* [#9620](https://github.com/warp-drive-data/warp-drive/pull/9620) Starwars ([@NullVoxPopuli](https://github.com/NullVoxPopuli))
|
|
75
|
+
* [#9543](https://github.com/warp-drive-data/warp-drive/pull/9543) Improvement: Setting Up The Project ([@leoeuclids](https://github.com/leoeuclids))
|
|
76
|
+
|
|
77
|
+
#### Committers: (3)
|
|
78
|
+
|
|
79
|
+
Chris Thoburn ([@runspired](https://github.com/runspired))
|
|
80
|
+
[@NullVoxPopuli](https://github.com/NullVoxPopuli)
|
|
81
|
+
Leo Euclides ([@leoeuclids](https://github.com/leoeuclids))
|
|
82
|
+
|
|
83
|
+
## v0.0.0-alpha.71 (2024-06-15)
|
|
84
|
+
|
|
85
|
+
#### :memo: Documentation
|
|
86
|
+
|
|
87
|
+
* [#9328](https://github.com/warp-drive-data/warp-drive/pull/9328) chore: update READMEs with status and dist tag info ([@runspired](https://github.com/runspired))
|
|
88
|
+
|
|
89
|
+
#### :rocket: Enhancement
|
|
90
|
+
|
|
91
|
+
* [#9471](https://github.com/warp-drive-data/warp-drive/pull/9471) feat: npx warp-drive ([@runspired](https://github.com/runspired))
|
|
92
|
+
* [#9366](https://github.com/warp-drive-data/warp-drive/pull/9366) feat: typed Model ([@runspired](https://github.com/runspired))
|
|
93
|
+
* [#9260](https://github.com/warp-drive-data/warp-drive/pull/9260) feat: ember specific data utils ([@runspired](https://github.com/runspired))
|
|
94
|
+
|
|
95
|
+
#### :bug: Bug Fix
|
|
96
|
+
|
|
97
|
+
* [#9383](https://github.com/warp-drive-data/warp-drive/pull/9383) fix: ensure cache-handler clones full errors ([@runspired](https://github.com/runspired))
|
|
98
|
+
|
|
99
|
+
#### :house: Internal
|
|
100
|
+
|
|
101
|
+
* [#9292](https://github.com/warp-drive-data/warp-drive/pull/9292) feat: add new build-config package ([@runspired](https://github.com/runspired))
|
|
102
|
+
|
|
103
|
+
#### Committers: (1)
|
|
104
|
+
|
|
105
|
+
Chris Thoburn ([@runspired](https://github.com/runspired))
|
|
106
|
+
|
|
107
|
+
For the full project changelog see [https://github.com/warp-drive-data/warp-drive/blob/main/CHANGELOG.md](https://github.com/warp-drive-data/warp-drive/blob/main/CHANGELOG.md)
|
|
108
|
+
|
|
109
|
+
## v0.0.0-alpha.9 (2024-02-24)
|
|
110
|
+
|
|
111
|
+
#### :rocket: Enhancement
|
|
112
|
+
|
|
113
|
+
* [#8921](https://github.com/warp-drive-data/warp-drive/pull/8921) feat: Improved Fetch Errors ([@runspired](https://github.com/runspired))
|
|
114
|
+
|
|
115
|
+
#### :house: Internal
|
|
116
|
+
|
|
117
|
+
* [#9125](https://github.com/warp-drive-data/warp-drive/pull/9125) Configure ESLint for test packages ([@gitKrystan](https://github.com/gitKrystan))
|
|
118
|
+
* [#8994](https://github.com/warp-drive-data/warp-drive/pull/8994) chore: fix recursive pnpm on node 18.18 ([@runspired](https://github.com/runspired))
|
|
119
|
+
* [#9084](https://github.com/warp-drive-data/warp-drive/pull/9084) Add import types ([@gitKrystan](https://github.com/gitKrystan))
|
|
120
|
+
* [#8989](https://github.com/warp-drive-data/warp-drive/pull/8989) chore(private): concurrent mode ([@runspired](https://github.com/runspired))
|
|
121
|
+
* [#9058](https://github.com/warp-drive-data/warp-drive/pull/9058) Switch from eslint-plugin-prettier to running prettier directly ([@gitKrystan](https://github.com/gitKrystan))
|
|
122
|
+
* [#9057](https://github.com/warp-drive-data/warp-drive/pull/9057) Add eslint-plugin-n to eslint config for node files ([@gitKrystan](https://github.com/gitKrystan))
|
|
123
|
+
* [#9055](https://github.com/warp-drive-data/warp-drive/pull/9055) Fix ESLint for VSCode ([@gitKrystan](https://github.com/gitKrystan))
|
|
124
|
+
* [#9051](https://github.com/warp-drive-data/warp-drive/pull/9051) chore: use references for tsc, add checks to schema-record, bun to run scripts ([@runspired](https://github.com/runspired))
|
|
125
|
+
* [#9032](https://github.com/warp-drive-data/warp-drive/pull/9032) chore(types): split out lint and type commands to be per-package ([@runspired](https://github.com/runspired))
|
|
126
|
+
* [#9050](https://github.com/warp-drive-data/warp-drive/pull/9050) chore: use composite mode for tsc ([@runspired](https://github.com/runspired))
|
|
127
|
+
* [#9049](https://github.com/warp-drive-data/warp-drive/pull/9049) chore: incremental tsc builds ([@runspired](https://github.com/runspired))
|
|
128
|
+
* [#9046](https://github.com/warp-drive-data/warp-drive/pull/9046) chore: reduce number of things turbo builds for build ([@runspired](https://github.com/runspired))
|
|
129
|
+
* [#9025](https://github.com/warp-drive-data/warp-drive/pull/9025) chore: reconfigure request package type location ([@runspired](https://github.com/runspired))
|
|
130
|
+
* [#8972](https://github.com/warp-drive-data/warp-drive/pull/8972) chore: use new test runner for request tests ([@runspired](https://github.com/runspired))
|
|
131
|
+
* [#8931](https://github.com/warp-drive-data/warp-drive/pull/8931) chore: package infra for schema-record ([@runspired](https://github.com/runspired))
|
|
132
|
+
* [#8912](https://github.com/warp-drive-data/warp-drive/pull/8912) chore: docs for holodeck ([@runspired](https://github.com/runspired))
|
|
133
|
+
* [#8906](https://github.com/warp-drive-data/warp-drive/pull/8906) feat: expand mock-server capabilities, add to main tests ([@runspired](https://github.com/runspired))
|
|
134
|
+
|
|
135
|
+
#### Committers: (2)
|
|
136
|
+
|
|
137
|
+
Chris Thoburn ([@runspired](https://github.com/runspired))
|
|
138
|
+
Krystan HuffMenne ([@gitKrystan](https://github.com/gitKrystan))
|
|
139
|
+
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","names":["getGlobalConfig","macroCondition","TEST_IDS","WeakMap","HOST","setConfig","host","endsWith","setTestId","context","str","has","Error","set","id","mock","GET","PUT","PATCH","DELETE","POST","QUERY","OPTIONS","HEAD","CONNECT","TRACE","request","delete","shouldRecord","WarpDrive","env","SHOULD_RECORD","IS_RECORDING","setIsRecording","value","Boolean","getIsRecording","MockServerHandler","constructor","owner","next","queryForTest","setupHolodeckFetch","Object","assign","future","setStream","getStream","e","DOMException","message","replace","test","get","url","firstChar","includes","method","toUpperCase","console","log","mode","credentials","referrerPolicy","headers","Headers","upgradeAdapter","adapter","upgradeStore","store","adapterFor","installAdapterFor","fn","holodeckAdapterFor","modelName","_allowMissing","call","hasOverriddenFetch","useFetch","originalFetch","_fetchRequest","bind","options","String","generate","isRecording","requestToMock","mockUrl","mockMethod","testMockNum","fetch","body","JSON","stringify"],"sources":["../src/index.ts"],"sourcesContent":["/**\n * @module\n * @mergeModuleWith <project>\n */\nimport { SHOULD_RECORD } from '@warp-drive/core/build-config/env';\nimport type { Handler, NextFn } from '@warp-drive/core/request';\nimport type { HTTPMethod, RequestContext, RequestInfo, StructuredDataDocument } from '@warp-drive/core/types/request';\nimport type { MinimumAdapterInterface } from '@warp-drive/legacy/compat';\nimport type { Store } from '@warp-drive/legacy/store';\n\nimport type { ScaffoldGenerator } from './mock';\n\nconst TEST_IDS = new WeakMap<\n object,\n {\n id: string;\n /**\n * keeps track of the count of calls to record a mock\n */\n mock: {\n /**\n * For each GET, we keep track of the count\n * for a specific URL\n */\n GET: Record<string, number>;\n /**\n * For each PUT, we keep track of the count\n * for a specific URL\n */\n PUT: Record<string, number>;\n /**\n * For each PATCH, we keep track of the count\n * for a specific URL\n */\n PATCH: Record<string, number>;\n /**\n * For each DELETE, we keep track of the count\n * for a specific URL\n */\n DELETE: Record<string, number>;\n /**\n * For each POST, we keep track of the count\n * for a specific URL\n */\n POST: Record<string, number>;\n /**\n * For each OPTIONS, we keep track of the count\n * for a specific URL\n */\n OPTIONS: Record<string, number>;\n /**\n * For each QUERY, we keep track of the count\n * for a specific URL\n */\n QUERY: Record<string, number>;\n /**\n * for each HEAD, we keep track of the count\n * for a specific URL\n */\n HEAD: Record<string, number>;\n /**\n * for each CONNECT, we keep track of the count\n * for a specific URL\n */\n CONNECT: Record<string, number>;\n /**\n * for each TRACE, we keep track of the count\n * for a specific URL\n */\n TRACE: Record<string, number>;\n };\n /**\n * keeps track of the count of calls to make a request\n */\n request: {\n /**\n * For each GET, we keep track of the count\n * for a specific URL\n */\n GET: Record<string, number>;\n /**\n * For each PUT, we keep track of the count\n * for a specific URL\n */\n PUT: Record<string, number>;\n /**\n * For each PATCH, we keep track of the count\n * for a specific URL\n */\n PATCH: Record<string, number>;\n /**\n * For each DELETE, we keep track of the count\n * for a specific URL\n */\n DELETE: Record<string, number>;\n /**\n * For each POST, we keep track of the count\n * for a specific URL\n */\n POST: Record<string, number>;\n /**\n * For each OPTIONS, we keep track of the count\n * for a specific URL\n */\n OPTIONS: Record<string, number>;\n /**\n * For each QUERY, we keep track of the count\n * for a specific URL\n */\n QUERY: Record<string, number>;\n /**\n * for each HEAD, we keep track of the count\n * for a specific URL\n */\n HEAD: Record<string, number>;\n /**\n * for each CONNECT, we keep track of the count\n * for a specific URL\n */\n CONNECT: Record<string, number>;\n /**\n * for each TRACE, we keep track of the count\n * for a specific URL\n */\n TRACE: Record<string, number>;\n };\n }\n>();\n\nlet HOST = '/';\n\n/**\n * @public\n */\n\nexport function setConfig({ host }: { host: string }): void {\n HOST = host.endsWith('/') ? host : `${host}/`;\n}\n\n/**\n * @public\n */\n\nexport function setTestId(context: object, str: string | null): void {\n if (str && TEST_IDS.has(context)) {\n throw new Error(`MockServerHandler is already configured with a testId.`);\n }\n if (str) {\n TEST_IDS.set(context, {\n id: str,\n mock: {\n GET: {},\n PUT: {},\n PATCH: {},\n DELETE: {},\n POST: {},\n QUERY: {},\n OPTIONS: {},\n HEAD: {},\n CONNECT: {},\n TRACE: {},\n },\n request: {\n GET: {},\n PUT: {},\n PATCH: {},\n DELETE: {},\n POST: {},\n QUERY: {},\n OPTIONS: {},\n HEAD: {},\n CONNECT: {},\n TRACE: {},\n },\n });\n } else {\n TEST_IDS.delete(context);\n }\n}\n\nconst shouldRecord = SHOULD_RECORD ? true : false;\nlet IS_RECORDING: boolean | null = null;\n\n/**\n * @public\n */\nexport function setIsRecording(value: boolean): void {\n IS_RECORDING = value === null ? value : Boolean(value);\n}\n\n/**\n * @public\n */\nexport function getIsRecording(): boolean {\n return IS_RECORDING === null ? shouldRecord : IS_RECORDING;\n}\n\n/**\n * A request handler that intercepts requests and routes them through\n * the Holodeck mock server.\n *\n * This handler modifies the request URL to include test identifiers\n * and manages request counts for accurate mocking.\n *\n * Requires that the test context be configured with a testId using `setTestId`.\n *\n * @param owner - the test context object used to retrieve the test ID.\n */\nexport class MockServerHandler implements Handler {\n declare owner: object;\n constructor(owner: object) {\n this.owner = owner;\n }\n async request<T>(context: RequestContext, next: NextFn<T>): Promise<StructuredDataDocument<T>> {\n const { request, queryForTest } = setupHolodeckFetch(this.owner, Object.assign({}, context.request));\n\n try {\n const future = next(request);\n context.setStream(future.getStream());\n return await future;\n } catch (e) {\n if (e instanceof Error && !(e instanceof DOMException)) {\n e.message = e.message.replace(queryForTest, '');\n }\n throw e;\n }\n }\n}\n\nfunction setupHolodeckFetch(owner: object, request: RequestInfo): { request: RequestInfo; queryForTest: string } {\n const test = TEST_IDS.get(owner);\n if (!test) {\n throw new Error(`MockServerHandler is not configured with a testId. Use setTestId to set the testId for each test`);\n }\n\n const url = request.url!;\n const firstChar = url.includes('?') ? '&' : '?';\n const method = (request.method?.toUpperCase() ?? 'GET') as HTTPMethod;\n\n // enable custom methods\n if (!test.request[method]) {\n // eslint-disable-next-line no-console\n console.log(`⚠️ Using custom HTTP method ${method} for response to request ${url}`);\n\n test.request[method] = {};\n }\n if (!(url in test.request[method])) {\n test.request[method][url] = 0;\n }\n\n const queryForTest = `${firstChar}__xTestId=${test.id}&__xTestRequestNumber=${test.request[method][url]++}`;\n request.url = url + queryForTest;\n request.method = method;\n\n request.mode = 'cors';\n request.credentials = 'omit';\n request.referrerPolicy = '';\n\n // since holodeck currently runs on a separate port\n // and we don't want to trigger cors pre-flight\n // we convert PUT to POST to keep the request in the\n // \"simple\" cors category.\n // if (request.method === 'PUT') {\n // request.method = 'POST';\n // }\n\n const headers = new Headers(request.headers);\n if (headers.has('Content-Type')) {\n // under the rules of simple-cors, content-type can only be\n // one of three things, none of which are what folks typically\n // set this to. Since holodeck always expects body to be JSON\n // this \"just works\".\n headers.set('Content-Type', 'text/plain');\n request.headers = headers;\n }\n\n return { request, queryForTest };\n}\n\ninterface HasAdapterForFn {\n adapterFor(this: Store, modelName: string): MinimumAdapterInterface;\n adapterFor(this: Store, modelName: string, _allowMissing?: true): MinimumAdapterInterface | undefined;\n}\n\n/*\n _fetchRequest(options: FetchRequestInit): Promise<Response> {\n const fetchFunction = fetch();\n\n return fetchFunction(options.url, options);\n }\n*/\ninterface PrivateAdapter {\n _fetchRequest(options: RequestInfo): Promise<Response>;\n hasOverriddenFetch: boolean;\n useFetch: boolean;\n}\n\nfunction upgradeAdapter(adapter: unknown): asserts adapter is PrivateAdapter {}\nfunction upgradeStore(store: Store): asserts store is Store & { adapterFor: HasAdapterForFn['adapterFor'] } {\n if (typeof store.adapterFor !== 'function') {\n throw new Error('Store is not compatible with Holodeck. Missing adapterFor method.');\n }\n}\n\n/**\n * Creates an adapterFor function that wraps the provided adapterFor function\n * to override the adapter's _fetchRequest method to route requests through\n * the Holodeck mock server.\n *\n * @param owner - The test context object used to retrieve the test ID.\n */\nexport function installAdapterFor(owner: object, store: Store): void {\n upgradeStore(store);\n const fn = store.adapterFor;\n function holodeckAdapterFor(\n this: Store,\n modelName: string,\n _allowMissing?: true\n ): MinimumAdapterInterface | undefined {\n const adapter = fn.call(this, modelName, _allowMissing);\n\n if (adapter) {\n upgradeAdapter(adapter);\n\n if (!adapter.hasOverriddenFetch) {\n adapter.hasOverriddenFetch = true;\n adapter.useFetch = true;\n const originalFetch = adapter._fetchRequest?.bind(adapter);\n\n adapter._fetchRequest = function (options: RequestInfo) {\n if (!originalFetch) {\n throw new Error(`Adapter ${String(modelName)} does not implement _fetchRequest`);\n }\n const { request } = setupHolodeckFetch(owner, options);\n\n return originalFetch(request);\n };\n }\n }\n\n return adapter;\n }\n store.adapterFor = holodeckAdapterFor as HasAdapterForFn['adapterFor'];\n}\n\n/**\n * Mock a request by sending the scaffold to the mock server.\n *\n * @public\n */\nexport async function mock(owner: object, generate: ScaffoldGenerator, isRecording?: boolean): Promise<void> {\n if (getIsRecording() || isRecording) {\n const test = TEST_IDS.get(owner);\n if (!test) {\n throw new Error(`Cannot call \"mock\" before configuring a testId. Use setTestId to set the testId for each test`);\n }\n const requestToMock = generate();\n const { url: mockUrl, method } = requestToMock;\n if (!mockUrl || !method) {\n throw new Error(`MockError: Cannot mock a request without providing a URL and Method`);\n }\n const mockMethod = (method?.toUpperCase() ?? 'GET') as HTTPMethod;\n\n // enable custom methods\n if (!test.mock[mockMethod]) {\n // eslint-disable-next-line no-console\n console.log(`⚠️ Using custom HTTP method ${mockMethod} for response to request ${mockUrl}`);\n test.mock[mockMethod] = {};\n }\n if (!(mockUrl in test.mock[mockMethod])) {\n test.mock[mockMethod][mockUrl] = 0;\n }\n const testMockNum = test.mock[mockMethod][mockUrl]++;\n const url = `${HOST}__record?__xTestId=${test.id}&__xTestRequestNumber=${testMockNum}`;\n await fetch(url, {\n method: 'POST',\n body: JSON.stringify(requestToMock),\n mode: 'cors',\n credentials: 'omit',\n referrerPolicy: '',\n });\n }\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.js","names":["getGlobalConfig","macroCondition","TEST_IDS","WeakMap","HOST","setConfig","host","endsWith","setTestId","context","str","has","Error","set","id","mock","GET","PUT","PATCH","DELETE","POST","QUERY","OPTIONS","HEAD","CONNECT","TRACE","request","delete","shouldRecord","WarpDrive","env","SHOULD_RECORD","IS_RECORDING","setIsRecording","value","Boolean","getIsRecording","MockServerHandler","constructor","owner","next","queryForTest","setupHolodeckFetch","Object","assign","future","setStream","getStream","e","DOMException","message","replace","test","get","url","firstChar","includes","method","toUpperCase","console","log","mode","credentials","referrerPolicy","headers","Headers","upgradeAdapter","adapter","upgradeStore","store","adapterFor","installAdapterFor","fn","holodeckAdapterFor","modelName","_allowMissing","call","hasOverriddenFetch","useFetch","originalFetch","_fetchRequest","bind","options","String","generate","isRecording","requestToMock","mockUrl","mockMethod","testMockNum","fetch","body","JSON","stringify"],"sources":["../src/index.ts"],"sourcesContent":["/**\n * @module\n * @mergeModuleWith <project>\n */\nimport { SHOULD_RECORD } from '@warp-drive/core/build-config/env';\nimport type { Handler, NextFn } from '@warp-drive/core/request';\nimport type { HTTPMethod, RequestContext, RequestInfo, StructuredDataDocument } from '@warp-drive/core/types/request';\nimport type { MinimumAdapterInterface } from '@warp-drive/legacy/compat';\nimport type { Store } from '@warp-drive/legacy/store';\n\nimport type { ScaffoldGenerator } from './mock';\n\nconst TEST_IDS = new WeakMap<\n object,\n {\n id: string;\n /**\n * keeps track of the count of calls to record a mock\n */\n mock: {\n /**\n * For each GET, we keep track of the count\n * for a specific URL\n */\n GET: Record<string, number>;\n /**\n * For each PUT, we keep track of the count\n * for a specific URL\n */\n PUT: Record<string, number>;\n /**\n * For each PATCH, we keep track of the count\n * for a specific URL\n */\n PATCH: Record<string, number>;\n /**\n * For each DELETE, we keep track of the count\n * for a specific URL\n */\n DELETE: Record<string, number>;\n /**\n * For each POST, we keep track of the count\n * for a specific URL\n */\n POST: Record<string, number>;\n /**\n * For each OPTIONS, we keep track of the count\n * for a specific URL\n */\n OPTIONS: Record<string, number>;\n /**\n * For each QUERY, we keep track of the count\n * for a specific URL\n */\n QUERY: Record<string, number>;\n /**\n * for each HEAD, we keep track of the count\n * for a specific URL\n */\n HEAD: Record<string, number>;\n /**\n * for each CONNECT, we keep track of the count\n * for a specific URL\n */\n CONNECT: Record<string, number>;\n /**\n * for each TRACE, we keep track of the count\n * for a specific URL\n */\n TRACE: Record<string, number>;\n };\n /**\n * keeps track of the count of calls to make a request\n */\n request: {\n /**\n * For each GET, we keep track of the count\n * for a specific URL\n */\n GET: Record<string, number>;\n /**\n * For each PUT, we keep track of the count\n * for a specific URL\n */\n PUT: Record<string, number>;\n /**\n * For each PATCH, we keep track of the count\n * for a specific URL\n */\n PATCH: Record<string, number>;\n /**\n * For each DELETE, we keep track of the count\n * for a specific URL\n */\n DELETE: Record<string, number>;\n /**\n * For each POST, we keep track of the count\n * for a specific URL\n */\n POST: Record<string, number>;\n /**\n * For each OPTIONS, we keep track of the count\n * for a specific URL\n */\n OPTIONS: Record<string, number>;\n /**\n * For each QUERY, we keep track of the count\n * for a specific URL\n */\n QUERY: Record<string, number>;\n /**\n * for each HEAD, we keep track of the count\n * for a specific URL\n */\n HEAD: Record<string, number>;\n /**\n * for each CONNECT, we keep track of the count\n * for a specific URL\n */\n CONNECT: Record<string, number>;\n /**\n * for each TRACE, we keep track of the count\n * for a specific URL\n */\n TRACE: Record<string, number>;\n };\n }\n>();\n\nlet HOST = '/';\n\n/**\n * @public\n */\n\nexport function setConfig({ host }: { host: string }): void {\n HOST = host.endsWith('/') ? host : `${host}/`;\n}\n\n/**\n * @public\n */\n\nexport function setTestId(context: object, str: string | null): void {\n if (str && TEST_IDS.has(context)) {\n throw new Error(`MockServerHandler is already configured with a testId.`);\n }\n if (str) {\n TEST_IDS.set(context, {\n id: str,\n mock: {\n GET: {},\n PUT: {},\n PATCH: {},\n DELETE: {},\n POST: {},\n QUERY: {},\n OPTIONS: {},\n HEAD: {},\n CONNECT: {},\n TRACE: {},\n },\n request: {\n GET: {},\n PUT: {},\n PATCH: {},\n DELETE: {},\n POST: {},\n QUERY: {},\n OPTIONS: {},\n HEAD: {},\n CONNECT: {},\n TRACE: {},\n },\n });\n } else {\n TEST_IDS.delete(context);\n }\n}\n\nconst shouldRecord = SHOULD_RECORD ? true : false;\nlet IS_RECORDING: boolean | null = null;\n\n/**\n * @public\n */\nexport function setIsRecording(value: boolean): void {\n IS_RECORDING = value === null ? value : Boolean(value);\n}\n\n/**\n * @public\n */\nexport function getIsRecording(): boolean {\n return IS_RECORDING === null ? shouldRecord : IS_RECORDING;\n}\n\n/**\n * A request handler that intercepts requests and routes them through\n * the Holodeck mock server.\n *\n * This handler modifies the request URL to include test identifiers\n * and manages request counts for accurate mocking.\n *\n * Requires that the test context be configured with a testId using `setTestId`.\n *\n * @param owner - the test context object used to retrieve the test ID.\n */\nexport class MockServerHandler implements Handler {\n declare owner: object;\n constructor(owner: object) {\n this.owner = owner;\n }\n async request<T>(context: RequestContext, next: NextFn<T>): Promise<StructuredDataDocument<T>> {\n const { request, queryForTest } = setupHolodeckFetch(this.owner, Object.assign({}, context.request));\n\n try {\n const future = next(request);\n context.setStream(future.getStream());\n return await future;\n } catch (e) {\n if (e instanceof Error && !(e instanceof DOMException)) {\n e.message = e.message.replace(queryForTest, '');\n }\n throw e;\n }\n }\n}\n\nfunction setupHolodeckFetch(owner: object, request: RequestInfo): { request: RequestInfo; queryForTest: string } {\n const test = TEST_IDS.get(owner);\n if (!test) {\n throw new Error(`MockServerHandler is not configured with a testId. Use setTestId to set the testId for each test`);\n }\n\n const url = request.url!;\n const firstChar = url.includes('?') ? '&' : '?';\n const method = (request.method?.toUpperCase() ?? 'GET') as HTTPMethod;\n\n // enable custom methods\n if (!test.request[method]) {\n // oxlint-disable-next-line no-console\n console.log(`⚠️ Using custom HTTP method ${method} for response to request ${url}`);\n\n test.request[method] = {};\n }\n if (!(url in test.request[method])) {\n test.request[method][url] = 0;\n }\n\n const queryForTest = `${firstChar}__xTestId=${test.id}&__xTestRequestNumber=${test.request[method][url]++}`;\n request.url = url + queryForTest;\n request.method = method;\n\n request.mode = 'cors';\n request.credentials = 'omit';\n request.referrerPolicy = '';\n\n // since holodeck currently runs on a separate port\n // and we don't want to trigger cors pre-flight\n // we convert PUT to POST to keep the request in the\n // \"simple\" cors category.\n // if (request.method === 'PUT') {\n // request.method = 'POST';\n // }\n\n const headers = new Headers(request.headers);\n if (headers.has('Content-Type')) {\n // under the rules of simple-cors, content-type can only be\n // one of three things, none of which are what folks typically\n // set this to. Since holodeck always expects body to be JSON\n // this \"just works\".\n headers.set('Content-Type', 'text/plain');\n request.headers = headers;\n }\n\n return { request, queryForTest };\n}\n\ninterface HasAdapterForFn {\n adapterFor(this: Store, modelName: string): MinimumAdapterInterface;\n adapterFor(this: Store, modelName: string, _allowMissing?: true): MinimumAdapterInterface | undefined;\n}\n\n/*\n _fetchRequest(options: FetchRequestInit): Promise<Response> {\n const fetchFunction = fetch();\n\n return fetchFunction(options.url, options);\n }\n*/\ninterface PrivateAdapter {\n _fetchRequest(options: RequestInfo): Promise<Response>;\n hasOverriddenFetch: boolean;\n useFetch: boolean;\n}\n\nfunction upgradeAdapter(adapter: unknown): asserts adapter is PrivateAdapter {}\nfunction upgradeStore(store: Store): asserts store is Store & { adapterFor: HasAdapterForFn['adapterFor'] } {\n if (typeof store.adapterFor !== 'function') {\n throw new Error('Store is not compatible with Holodeck. Missing adapterFor method.');\n }\n}\n\n/**\n * Creates an adapterFor function that wraps the provided adapterFor function\n * to override the adapter's _fetchRequest method to route requests through\n * the Holodeck mock server.\n *\n * @param owner - The test context object used to retrieve the test ID.\n */\nexport function installAdapterFor(owner: object, store: Store): void {\n upgradeStore(store);\n const fn = store.adapterFor;\n function holodeckAdapterFor(\n this: Store,\n modelName: string,\n _allowMissing?: true\n ): MinimumAdapterInterface | undefined {\n const adapter = fn.call(this, modelName, _allowMissing);\n\n if (adapter) {\n upgradeAdapter(adapter);\n\n if (!adapter.hasOverriddenFetch) {\n adapter.hasOverriddenFetch = true;\n adapter.useFetch = true;\n const originalFetch = adapter._fetchRequest?.bind(adapter);\n\n adapter._fetchRequest = function (options: RequestInfo) {\n if (!originalFetch) {\n throw new Error(`Adapter ${String(modelName)} does not implement _fetchRequest`);\n }\n const { request } = setupHolodeckFetch(owner, options);\n\n return originalFetch(request);\n };\n }\n }\n\n return adapter;\n }\n store.adapterFor = holodeckAdapterFor as HasAdapterForFn['adapterFor'];\n}\n\n/**\n * Mock a request by sending the scaffold to the mock server.\n *\n * @public\n */\nexport async function mock(owner: object, generate: ScaffoldGenerator, isRecording?: boolean): Promise<void> {\n if (getIsRecording() || isRecording) {\n const test = TEST_IDS.get(owner);\n if (!test) {\n throw new Error(`Cannot call \"mock\" before configuring a testId. Use setTestId to set the testId for each test`);\n }\n const requestToMock = generate();\n const { url: mockUrl, method } = requestToMock;\n if (!mockUrl || !method) {\n throw new Error(`MockError: Cannot mock a request without providing a URL and Method`);\n }\n const mockMethod = (method?.toUpperCase() ?? 'GET') as HTTPMethod;\n\n // enable custom methods\n if (!test.mock[mockMethod]) {\n // oxlint-disable-next-line no-console\n console.log(`⚠️ Using custom HTTP method ${mockMethod} for response to request ${mockUrl}`);\n test.mock[mockMethod] = {};\n }\n if (!(mockUrl in test.mock[mockMethod])) {\n test.mock[mockMethod][mockUrl] = 0;\n }\n const testMockNum = test.mock[mockMethod][mockUrl]++;\n const url = `${HOST}__record?__xTestId=${test.id}&__xTestRequestNumber=${testMockNum}`;\n await fetch(url, {\n method: 'POST',\n body: JSON.stringify(requestToMock),\n mode: 'cors',\n credentials: 'omit',\n referrerPolicy: '',\n });\n }\n}\n"],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@warp-drive/holodeck",
|
|
3
3
|
"description": "⚡️ Simple, Fast HTTP Mocking for Tests",
|
|
4
|
-
"version": "0.1.0-alpha.
|
|
4
|
+
"version": "0.1.0-alpha.70",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"author": "Chris Thoburn <runspired@users.noreply.github.com>",
|
|
7
7
|
"repository": {
|
|
@@ -12,17 +12,13 @@
|
|
|
12
12
|
"homepage": "https://github.com/warp-drive-data/warp-drive",
|
|
13
13
|
"bugs": "https://github.com/warp-drive-data/warp-drive/issues",
|
|
14
14
|
"engines": {
|
|
15
|
-
"node": ">=
|
|
15
|
+
"node": ">= 24.20.0"
|
|
16
16
|
},
|
|
17
17
|
"keywords": [
|
|
18
18
|
"http-mock"
|
|
19
19
|
],
|
|
20
|
-
"volta": {
|
|
21
|
-
"extends": "../../package.json"
|
|
22
|
-
},
|
|
23
20
|
"dependencies": {
|
|
24
|
-
"
|
|
25
|
-
"hono": "^4.9.4",
|
|
21
|
+
"hono": "^4.13.5",
|
|
26
22
|
"@hono/node-server": "^1.19.0"
|
|
27
23
|
},
|
|
28
24
|
"type": "module",
|
|
@@ -38,9 +34,9 @@
|
|
|
38
34
|
"ensure-cert": "./server/ensure-cert.js"
|
|
39
35
|
},
|
|
40
36
|
"peerDependencies": {
|
|
41
|
-
"@warp-drive/utilities": "5.9.0-alpha.
|
|
42
|
-
"@warp-drive/legacy": "5.9.0-alpha.
|
|
43
|
-
"@warp-drive/core": "5.9.0-alpha.
|
|
37
|
+
"@warp-drive/utilities": "5.9.0-alpha.27",
|
|
38
|
+
"@warp-drive/legacy": "5.9.0-alpha.27",
|
|
39
|
+
"@warp-drive/core": "5.9.0-alpha.27"
|
|
44
40
|
},
|
|
45
41
|
"peerDependenciesMeta": {
|
|
46
42
|
"@warp-drive/utilities": {
|
|
@@ -56,11 +52,12 @@
|
|
|
56
52
|
"@babel/preset-env": "^7.29.7",
|
|
57
53
|
"@babel/preset-typescript": "^7.29.7",
|
|
58
54
|
"@babel/runtime": "^7.29.7",
|
|
59
|
-
"@warp-drive/utilities": "5.9.0-alpha.
|
|
60
|
-
"@warp-drive/legacy": "5.9.0-alpha.
|
|
61
|
-
"@warp-drive/core": "5.9.0-alpha.
|
|
62
|
-
"@warp-drive/internal-config": "5.9.0-alpha.
|
|
63
|
-
"tsdown": "^0.22.14"
|
|
55
|
+
"@warp-drive/utilities": "5.9.0-alpha.27",
|
|
56
|
+
"@warp-drive/legacy": "5.9.0-alpha.27",
|
|
57
|
+
"@warp-drive/core": "5.9.0-alpha.27",
|
|
58
|
+
"@warp-drive/internal-config": "5.9.0-alpha.27",
|
|
59
|
+
"tsdown": "^0.22.14",
|
|
60
|
+
"typescript-7": "npm:typescript@7.1.0-dev.20260828.1"
|
|
64
61
|
},
|
|
65
62
|
"exports": {
|
|
66
63
|
".": {
|
|
@@ -83,10 +80,9 @@
|
|
|
83
80
|
}
|
|
84
81
|
},
|
|
85
82
|
"scripts": {
|
|
86
|
-
"check:types": "tsc --noEmit",
|
|
83
|
+
"check:types": "node ./node_modules/typescript-7/bin/tsc --noEmit",
|
|
87
84
|
"build:pkg": "node node_modules/tsdown/dist/run.mjs",
|
|
88
85
|
"sync": "echo \"syncing\"",
|
|
89
|
-
"_temporarily_deactivated_lint": "eslint . --quiet --cache --cache-strategy=content",
|
|
90
86
|
"start": "node node_modules/tsdown/dist/run.mjs --watch"
|
|
91
87
|
}
|
|
92
88
|
}
|
package/server/bun.js
CHANGED
|
@@ -1,12 +1,13 @@
|
|
|
1
|
-
import chalk from 'chalk';
|
|
2
1
|
import { Hono } from 'hono';
|
|
3
|
-
import { createSecureServer } from 'node:http2';
|
|
4
|
-
import { logger } from 'hono/logger';
|
|
5
|
-
import { HTTPException } from 'hono/http-exception';
|
|
6
2
|
import { cors } from 'hono/cors';
|
|
3
|
+
import { HTTPException } from 'hono/http-exception';
|
|
4
|
+
import { logger } from 'hono/logger';
|
|
7
5
|
import fs from 'node:fs';
|
|
8
|
-
import
|
|
6
|
+
import { createSecureServer } from 'node:http2';
|
|
7
|
+
import { styleText } from 'node:util';
|
|
9
8
|
import { Worker, threadId, parentPort } from 'node:worker_threads';
|
|
9
|
+
import path from 'path';
|
|
10
|
+
|
|
10
11
|
import {
|
|
11
12
|
bindWithRetry,
|
|
12
13
|
compress,
|
|
@@ -321,7 +322,7 @@ async function _createServer(options) {
|
|
|
321
322
|
);
|
|
322
323
|
|
|
323
324
|
console.log(
|
|
324
|
-
`\tServing Holodeck HTTP Mocks from ${
|
|
325
|
+
`\tServing Holodeck HTTP Mocks from ${styleText('yellow', 'https://') + styleText('magenta', location.hostname + ':') + styleText('yellow', String(location.port))}\n`
|
|
325
326
|
);
|
|
326
327
|
|
|
327
328
|
if (typeof threadId === 'number' && threadId !== 0) {
|
|
@@ -360,25 +361,29 @@ export async function launchProgram(config = {}) {
|
|
|
360
361
|
}
|
|
361
362
|
const options = { name, projectRoot, ...config };
|
|
362
363
|
console.log(
|
|
363
|
-
|
|
364
|
-
|
|
364
|
+
styleText(
|
|
365
|
+
'grey',
|
|
366
|
+
`\n\t@${styleText('greenBright', 'warp-drive')}/${styleText(
|
|
367
|
+
'magentaBright',
|
|
365
368
|
'holodeck'
|
|
366
369
|
)} 🌅\n\t=================================\n`
|
|
367
370
|
) +
|
|
368
|
-
|
|
369
|
-
|
|
371
|
+
styleText(
|
|
372
|
+
'grey',
|
|
373
|
+
`\n\tHolodeck Access Granted\n\t\tprogram: ${styleText('magenta', name)}\n\t\tsettings: ${styleText(
|
|
374
|
+
'green',
|
|
370
375
|
JSON.stringify(config).split('\n').join(' ')
|
|
371
|
-
)}\n\t\tdirectory: ${
|
|
376
|
+
)}\n\t\tdirectory: ${styleText('cyan', projectRoot)}\n\t\tengine: ${styleText('cyan', 'bun')}@${styleText('yellow', Bun.version)}\n`
|
|
372
377
|
)
|
|
373
378
|
);
|
|
374
|
-
console.log(
|
|
379
|
+
console.log(styleText('grey', `\n\tStarting Holodeck Subroutines`));
|
|
375
380
|
|
|
376
381
|
const project = await createServer(options);
|
|
377
382
|
|
|
378
383
|
async function shutdown() {
|
|
379
|
-
console.log(
|
|
384
|
+
console.log(styleText('grey', `\n\tEnding Holodeck Subroutines`));
|
|
380
385
|
project.close();
|
|
381
|
-
console.log(
|
|
386
|
+
console.log(styleText('grey', `\n\tHolodeck program ended`));
|
|
382
387
|
}
|
|
383
388
|
|
|
384
389
|
const endProgram = createCloseHandler(shutdown);
|
package/server/node.js
CHANGED
|
@@ -1,13 +1,14 @@
|
|
|
1
|
-
import chalk from 'chalk';
|
|
2
|
-
import { Hono } from 'hono';
|
|
3
1
|
import { serve } from '@hono/node-server';
|
|
4
|
-
import {
|
|
5
|
-
import { logger } from 'hono/logger';
|
|
6
|
-
import { HTTPException } from 'hono/http-exception';
|
|
2
|
+
import { Hono } from 'hono';
|
|
7
3
|
import { cors } from 'hono/cors';
|
|
4
|
+
import { HTTPException } from 'hono/http-exception';
|
|
5
|
+
import { logger } from 'hono/logger';
|
|
8
6
|
import fs from 'node:fs';
|
|
9
|
-
import
|
|
7
|
+
import { createSecureServer } from 'node:http2';
|
|
8
|
+
import { styleText } from 'node:util';
|
|
10
9
|
import { Worker, threadId, parentPort } from 'node:worker_threads';
|
|
10
|
+
import path from 'path';
|
|
11
|
+
|
|
11
12
|
import {
|
|
12
13
|
bindWithRetry,
|
|
13
14
|
compress,
|
|
@@ -330,7 +331,7 @@ async function _createServer(options) {
|
|
|
330
331
|
);
|
|
331
332
|
|
|
332
333
|
console.log(
|
|
333
|
-
`\tServing Holodeck HTTP Mocks from ${
|
|
334
|
+
`\tServing Holodeck HTTP Mocks from ${styleText('yellow', 'https://') + styleText('magenta', location.hostname + ':') + styleText('yellow', String(location.port))}\n`
|
|
334
335
|
);
|
|
335
336
|
|
|
336
337
|
if (typeof threadId === 'number' && threadId !== 0) {
|
|
@@ -366,27 +367,32 @@ export async function launchProgram(config = {}) {
|
|
|
366
367
|
}
|
|
367
368
|
const options = { name, projectRoot, ...config };
|
|
368
369
|
console.log(
|
|
369
|
-
|
|
370
|
-
|
|
370
|
+
styleText(
|
|
371
|
+
'grey',
|
|
372
|
+
`\n\t@${styleText('greenBright', 'warp-drive')}/${styleText(
|
|
373
|
+
'magentaBright',
|
|
371
374
|
'holodeck'
|
|
372
375
|
)} 🌅\n\t=================================\n`
|
|
373
376
|
) +
|
|
374
|
-
|
|
375
|
-
|
|
377
|
+
styleText(
|
|
378
|
+
'grey',
|
|
379
|
+
`\n\tHolodeck Access Granted\n\t\tprogram: ${styleText('magenta', name)}\n\t\tsettings: ${styleText(
|
|
380
|
+
'green',
|
|
376
381
|
JSON.stringify(config).split('\n').join(' ')
|
|
377
|
-
)}\n\t\tdirectory: ${
|
|
382
|
+
)}\n\t\tdirectory: ${styleText('cyan', projectRoot)}\n\t\tengine: ${styleText(
|
|
383
|
+
'cyan',
|
|
378
384
|
'node'
|
|
379
|
-
)}@${
|
|
385
|
+
)}@${styleText('yellow', process.version)}\n`
|
|
380
386
|
)
|
|
381
387
|
);
|
|
382
|
-
console.log(
|
|
388
|
+
console.log(styleText('grey', `\n\tStarting Holodeck Subroutines`));
|
|
383
389
|
|
|
384
390
|
const project = await createServer(options);
|
|
385
391
|
|
|
386
392
|
async function shutdown() {
|
|
387
|
-
console.log(
|
|
393
|
+
console.log(styleText('grey', `\n\tEnding Holodeck Subroutines`));
|
|
388
394
|
project.server.close();
|
|
389
|
-
console.log(
|
|
395
|
+
console.log(styleText('grey', `\n\tHolodeck program ended`));
|
|
390
396
|
}
|
|
391
397
|
|
|
392
398
|
const endProgram = createCloseHandler(shutdown);
|