arcane-os 0.4.0 → 0.4.1

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 CHANGED
@@ -1,5 +1,12 @@
1
1
  # Changelog
2
2
 
3
+ ## 0.4.1
4
+
5
+ - Preserved complete DirectoryPicker titles, paths, caller options, and
6
+ provider result fields without application clipping, trimming, freezing, or
7
+ generic path-character policy while retaining selected/cancelled semantics
8
+ and provider-owned path failures.
9
+
3
10
  ## 0.4.0
4
11
 
5
12
  - Preserved complete finite provider progress values and units as
package/README.md CHANGED
@@ -19,7 +19,7 @@ version-locked SDK runtime, while an integrated Arcane checkout uses its live
19
19
  `arcane/` runtime. Both profiles preserve the same app URLs, theme, packaging,
20
20
  event, cancellation, and browser run contracts.
21
21
 
22
- This checkout defines the `0.4.0` SDK contract. Applications pin one exact npm
22
+ This checkout defines the `0.4.1` SDK contract. Applications pin one exact npm
23
23
  version and lockfile; registry state is deliberately not baked into application
24
24
  artifacts.
25
25
 
@@ -126,7 +126,7 @@ uses the same controller for automatic memory extraction.
126
126
  Create a new repository-shaped Arcane application with the exact stable SDK:
127
127
 
128
128
  ```bash
129
- npx arcane-os@0.4.0 new my-app --path ./my-app --target portable --git
129
+ npx arcane-os@0.4.1 new my-app --path ./my-app --target portable --git
130
130
  cd my-app
131
131
  npm install
132
132
  npm run check
@@ -137,7 +137,7 @@ To enroll an existing repository, install the exact SDK and initialize only
137
137
  missing Arcane files:
138
138
 
139
139
  ```bash
140
- npm install --save-dev --save-exact arcane-os@0.4.0
140
+ npm install --save-dev --save-exact arcane-os@0.4.1
141
141
  npm exec -- arcane init my-app --target portable
142
142
  ```
143
143
 
@@ -153,7 +153,7 @@ npm exec -- arcane-os targets
153
153
  No global SDK install or standalone Arcane CLI is required. The application
154
154
  repository's exact npm dependency and lockfile own the CLI and toolchain version.
155
155
 
156
- Use `npx arcane-os@0.4.0` for the initial bootstrap because it names this npm
156
+ Use `npx arcane-os@0.4.1` for the initial bootstrap because it names this npm
157
157
  package explicitly; bare `npx arcane` outside an installed project could resolve
158
158
  a different package. Both installed commands invoke the same headless toolchain.
159
159
  Project-local npm scripts use the SDK pinned by that app's `package-lock.json`,
@@ -174,7 +174,7 @@ node ./bin/arcane.mjs new local-app --path ../local-app --target portable --git
174
174
 
175
175
  # From the generated app repository
176
176
  cd ../local-app
177
- npm install --save-dev --save-exact ../arcane-os-sdk/arcane-os-0.4.0.tgz
177
+ npm install --save-dev --save-exact ../arcane-os-sdk/arcane-os-0.4.1.tgz
178
178
  npm run check
179
179
  npm ci
180
180
  ```
@@ -184,7 +184,7 @@ same location. The lockfile retains the selected package dependency while
184
184
  Arcane uses the installed package name and version. Local directory `file:` dependencies are not
185
185
  accepted because npm may install them as links; use a packed `.tgz`. A GitHub
186
186
  runner also needs that tarball at the locked path. After publication, replace
187
- the local declaration with the exact `arcane-os@0.4.0` registry package and
187
+ the local declaration with the exact `arcane-os@0.4.1` registry package and
188
188
  commit the regenerated lock.
189
189
 
190
190
  Generated repositories use `npm ci --ignore-scripts` in CI. Run dependency
@@ -322,7 +322,7 @@ package installation, or assertions.
322
322
 
323
323
  ## Current target support
324
324
 
325
- Version `0.4.0` exposes one browser target and five explicitly paired
325
+ Version `0.4.1` exposes one browser target and five explicitly paired
326
326
  native development targets: a non-runnable portable directory, a
327
327
  Windows x64 unsigned-local-test EXE bundle, Linux x64 and Linux ARM64
328
328
  unsigned-local-test DEBs, and an Android development-signed APK. The
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "arcane-os",
3
- "version": "0.4.0",
3
+ "version": "0.4.1",
4
4
  "description": "Arcane OS JavaScript SDK, project-local CLI, browser runtime, and repository-portable application packager.",
5
5
  "type": "module",
6
6
  "main": "./src/index.mjs",
@@ -165,11 +165,7 @@
165
165
  }
166
166
 
167
167
  function normalizeValue(value=''){
168
- const next=`${value??''}`.trim();
169
- if(/[\u0000-\u001f\u007f]/.test(next)){
170
- throw new TypeError('The directory path must be plain text.');
171
- }
172
- return next;
168
+ return `${value??''}`;
173
169
  }
174
170
 
175
171
  function setDisabled(value=false){
@@ -1,12 +1,7 @@
1
- const TITLE_MAX_LENGTH=160;
2
- const PATH_MAX_LENGTH=4096;
3
- const CONTROL_CHARACTERS=/[\u0000-\u001f\u007f]/;
4
-
5
- function isPlainRecord(value){
1
+ function isRecord(value){
6
2
  return Boolean(value)
7
3
  &&typeof value==='object'
8
- &&!Array.isArray(value)
9
- &&Object.getPrototypeOf(value)===Object.prototype;
4
+ &&!Array.isArray(value);
10
5
  }
11
6
 
12
7
  function coded(error,code){
@@ -14,37 +9,27 @@ function coded(error,code){
14
9
  return error;
15
10
  }
16
11
 
17
- function optionalText(value,label,maximum){
18
- if(value===undefined||value===null||value==='') return null;
12
+ function optionalText(value,label){
13
+ if(value===undefined||value===null) return value;
19
14
  if(typeof value!=='string') throw new TypeError(`${label} must be a string when provided.`);
20
- const normalized=value.trim();
21
- if(!normalized) return null;
22
- if(normalized.length>maximum) throw new RangeError(`${label} exceeds ${maximum} characters.`);
23
- if(CONTROL_CHARACTERS.test(normalized)) throw new TypeError(`${label} cannot contain control characters.`);
24
- return normalized;
15
+ return value;
25
16
  }
26
17
 
27
18
  function normalizeDirectoryPickerOptions(input={}){
28
- if(!isPlainRecord(input)) throw new TypeError('Directory picker options must be a plain object.');
29
- const allowed=new Set(['initialPath','title']);
30
- const unsupported=Object.keys(input).find(key=>!allowed.has(key));
31
- if(unsupported) throw new TypeError(`Unsupported directory picker option: ${unsupported}`);
32
-
33
- const title=optionalText(input.title,'title',TITLE_MAX_LENGTH);
34
- const initialPath=optionalText(input.initialPath,'initialPath',PATH_MAX_LENGTH);
35
- return Object.freeze({
36
- ...(title?{title}:{}),
37
- ...(initialPath?{initialPath}:{}),
38
- });
19
+ if(!isRecord(input)) throw new TypeError('Directory picker options must be an object.');
20
+ const normalized={...input};
21
+ if(Object.prototype.hasOwnProperty.call(input,'title')){
22
+ normalized.title=optionalText(input.title,'title');
23
+ }
24
+ if(Object.prototype.hasOwnProperty.call(input,'initialPath')){
25
+ normalized.initialPath=optionalText(input.initialPath,'initialPath');
26
+ }
27
+ return normalized;
39
28
  }
40
29
 
41
30
  function normalizeDirectorySelection(input){
42
- const keys=isPlainRecord(input)?Object.keys(input):[];
43
31
  if(
44
- !isPlainRecord(input)
45
- ||keys.length!==2
46
- ||!keys.includes('cancelled')
47
- ||!keys.includes('path')
32
+ !isRecord(input)
48
33
  ||typeof input.cancelled!=='boolean'
49
34
  ){
50
35
  throw coded(
@@ -53,17 +38,15 @@ function normalizeDirectorySelection(input){
53
38
  );
54
39
  }
55
40
  if(input.cancelled){
56
- if(input.path!==null){
57
- throw coded(
58
- new TypeError('A canceled directory selection must return a null path.'),
59
- 'DIRECTORY_PICKER_INVALID_RESULT',
60
- );
61
- }
62
- return Object.freeze({cancelled:true,path:null});
41
+ return {
42
+ ...input,
43
+ cancelled:true,
44
+ path:input.path===undefined?null:input.path,
45
+ };
63
46
  }
64
47
  let path;
65
48
  try{
66
- path=optionalText(input.path,'The selected directory path',PATH_MAX_LENGTH);
49
+ path=optionalText(input.path,'The selected directory path');
67
50
  }catch(error){
68
51
  throw coded(error,'DIRECTORY_PICKER_INVALID_RESULT');
69
52
  }
@@ -73,7 +56,7 @@ function normalizeDirectorySelection(input){
73
56
  'DIRECTORY_PICKER_INVALID_RESULT',
74
57
  );
75
58
  }
76
- return Object.freeze({cancelled:false,path});
59
+ return {...input,cancelled:false,path};
77
60
  }
78
61
 
79
62
  /**
@@ -81,7 +64,8 @@ function normalizeDirectorySelection(input){
81
64
  *
82
65
  * This wrapper does not enumerate directories, persist a selected path, or use
83
66
  * a browser file picker. The injected provider must expose
84
- * `selectDirectory(options)` and return `{cancelled, path}`.
67
+ * `selectDirectory(options)` and return a record with `cancelled` and `path`.
68
+ * Caller options and additional provider result fields pass through unchanged.
85
69
  */
86
70
  export default class DirectoryPicker{
87
71
  constructor(provider=globalThis.Arcane?.filesystem){