@o3co/create-auth-provider 0.5.0 → 0.5.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/dist/__tests__/index.test.mjs +42 -1
- package/dist/__tests__/published-package.test.d.mts +2 -0
- package/dist/__tests__/published-package.test.d.mts.map +1 -0
- package/dist/__tests__/published-package.test.mjs +73 -0
- package/dist/index.d.mts.map +1 -1
- package/dist/index.mjs +3 -6
- package/dist/internal/template-filter.d.mts +17 -0
- package/dist/internal/template-filter.d.mts.map +1 -0
- package/dist/internal/template-filter.mjs +45 -0
- package/package.json +1 -1
- package/templates/standalone/package.json +1 -1
- package/templates/versions.json +8 -8
|
@@ -1,8 +1,49 @@
|
|
|
1
1
|
import { existsSync, mkdirSync, mkdtempSync, readFileSync, rmSync } from "node:fs";
|
|
2
2
|
import { tmpdir } from "node:os";
|
|
3
|
-
import { join } from "node:path";
|
|
3
|
+
import { join, posix, win32 } from "node:path";
|
|
4
4
|
import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
|
|
5
5
|
import { isValidDirName, isValidProjectName, main, scaffold } from "../index.mjs";
|
|
6
|
+
import { shouldCopyTemplateEntry } from "../internal/template-filter.mjs";
|
|
7
|
+
// Both POSIX and Windows separators are exercised explicitly so the suite
|
|
8
|
+
// validates the separator-relative segment logic regardless of the host
|
|
9
|
+
// platform. (`path.sep` is the production default; tests pass it explicitly.)
|
|
10
|
+
const platforms = [
|
|
11
|
+
{
|
|
12
|
+
name: "POSIX-style paths",
|
|
13
|
+
sep: posix.sep,
|
|
14
|
+
installRoot: "/Users/x/.npm/_npx/abc/node_modules/@o3co/create-auth-provider/templates/standalone",
|
|
15
|
+
localRoot: "/repo/templates/standalone",
|
|
16
|
+
},
|
|
17
|
+
{
|
|
18
|
+
name: "Windows-style paths",
|
|
19
|
+
sep: win32.sep,
|
|
20
|
+
installRoot: "C:\\Users\\x\\AppData\\Roaming\\npm-cache\\_npx\\abc\\node_modules\\@o3co\\create-auth-provider\\templates\\standalone",
|
|
21
|
+
localRoot: "C:\\repo\\templates\\standalone",
|
|
22
|
+
},
|
|
23
|
+
];
|
|
24
|
+
describe.each(platforms)("shouldCopyTemplateEntry on $name", ({ sep, installRoot, localRoot }) => {
|
|
25
|
+
const joinSegments = (base, ...rest) => [base, ...rest].join(sep);
|
|
26
|
+
it("includes the template root itself", () => {
|
|
27
|
+
expect(shouldCopyTemplateEntry(installRoot, installRoot, sep)).toBe(true);
|
|
28
|
+
});
|
|
29
|
+
it("includes a file directly under the template root even when ancestor path contains 'node_modules'", () => {
|
|
30
|
+
// Regression for v0.5.0 npx install bug: when the package is installed
|
|
31
|
+
// at .../node_modules/@o3co/create-auth-provider/..., the previous filter
|
|
32
|
+
// checked every segment of the absolute source path and excluded
|
|
33
|
+
// everything, so cpSync copied no files.
|
|
34
|
+
expect(shouldCopyTemplateEntry(joinSegments(installRoot, "package.json"), installRoot, sep)).toBe(true);
|
|
35
|
+
});
|
|
36
|
+
it("includes nested template files even when ancestor path contains 'node_modules' or 'dist'", () => {
|
|
37
|
+
expect(shouldCopyTemplateEntry(joinSegments(installRoot, "src", "app.mts"), installRoot, sep)).toBe(true);
|
|
38
|
+
expect(shouldCopyTemplateEntry(joinSegments(installRoot, "config", "application.conf"), installRoot, sep)).toBe(true);
|
|
39
|
+
});
|
|
40
|
+
it("excludes node_modules subdirectories that live INSIDE the template root", () => {
|
|
41
|
+
expect(shouldCopyTemplateEntry(joinSegments(localRoot, "node_modules", "foo", "index.js"), localRoot, sep)).toBe(false);
|
|
42
|
+
});
|
|
43
|
+
it("excludes dist subdirectories that live INSIDE the template root", () => {
|
|
44
|
+
expect(shouldCopyTemplateEntry(joinSegments(localRoot, "dist", "index.mjs"), localRoot, sep)).toBe(false);
|
|
45
|
+
});
|
|
46
|
+
});
|
|
6
47
|
describe("scaffold", () => {
|
|
7
48
|
let tempDir;
|
|
8
49
|
beforeEach(() => {
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"published-package.test.d.mts","sourceRoot":"","sources":["../../src/__tests__/published-package.test.mts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Copyright 2026 1o1 Co. Ltd.
|
|
3
|
+
*
|
|
4
|
+
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
5
|
+
* you may not use this file except in compliance with the License.
|
|
6
|
+
* You may obtain a copy of the License at
|
|
7
|
+
*
|
|
8
|
+
* http://www.apache.org/licenses/LICENSE-2.0
|
|
9
|
+
*/
|
|
10
|
+
import { execFileSync } from "node:child_process";
|
|
11
|
+
import { existsSync, mkdirSync, mkdtempSync, readFileSync, rmSync } from "node:fs";
|
|
12
|
+
import { tmpdir } from "node:os";
|
|
13
|
+
import { dirname, join, resolve } from "node:path";
|
|
14
|
+
import { fileURLToPath } from "node:url";
|
|
15
|
+
import { afterAll, beforeAll, describe, expect, it } from "vitest";
|
|
16
|
+
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
17
|
+
const CREATE_APP_DIR = resolve(__dirname, "../..");
|
|
18
|
+
describe("published-package install context (e2e)", () => {
|
|
19
|
+
let workspace;
|
|
20
|
+
let tarballPath;
|
|
21
|
+
beforeAll(() => {
|
|
22
|
+
workspace = mkdtempSync(join(tmpdir(), "create-auth-provider-e2e-"));
|
|
23
|
+
// Isolate npm's cache to a per-run directory so a polluted developer
|
|
24
|
+
// `~/.npm/_cacache/` (e.g. root-owned files left by a sudo install) cannot
|
|
25
|
+
// fail the test with EPERM. The prepack hook only needs to read the
|
|
26
|
+
// workspace, but `npm pack` itself touches the cache regardless.
|
|
27
|
+
const npmCache = join(workspace, "npm-cache");
|
|
28
|
+
// `npm pack` runs the `prepack` script (rimraf dist + copy-templates + tsc),
|
|
29
|
+
// so this exercises the same artifact npm publishes to the registry.
|
|
30
|
+
const stdout = execFileSync("npm", ["pack", "--pack-destination", workspace, "--json"], {
|
|
31
|
+
cwd: CREATE_APP_DIR,
|
|
32
|
+
encoding: "utf-8",
|
|
33
|
+
env: { ...process.env, npm_config_cache: npmCache },
|
|
34
|
+
});
|
|
35
|
+
const [packed] = JSON.parse(stdout);
|
|
36
|
+
tarballPath = join(workspace, packed.filename);
|
|
37
|
+
}, 120_000);
|
|
38
|
+
afterAll(() => {
|
|
39
|
+
if (workspace)
|
|
40
|
+
rmSync(workspace, { recursive: true, force: true });
|
|
41
|
+
});
|
|
42
|
+
it("scaffolds successfully when installed under a path containing 'node_modules'", () => {
|
|
43
|
+
// Regression for v0.5.0 npx bug: simulate the actual install layout
|
|
44
|
+
// (~/.npm/_npx/<hash>/node_modules/@o3co/create-auth-provider/) so the
|
|
45
|
+
// cpSync filter sees an absolute source path whose ancestors include
|
|
46
|
+
// 'node_modules'. Before the fix, the filter excluded every file and
|
|
47
|
+
// `cpSync` left the target directory empty.
|
|
48
|
+
const installRoot = join(workspace, "node_modules", "@o3co", "create-auth-provider");
|
|
49
|
+
mkdirSync(installRoot, { recursive: true });
|
|
50
|
+
execFileSync("tar", ["-xzf", tarballPath, "--strip-components=1", "-C", installRoot]);
|
|
51
|
+
const projectCwd = join(workspace, "scaffold-cwd");
|
|
52
|
+
mkdirSync(projectCwd);
|
|
53
|
+
execFileSync("node", [join(installRoot, "dist", "cli.mjs"), "my-test-project"], {
|
|
54
|
+
cwd: projectCwd,
|
|
55
|
+
encoding: "utf-8",
|
|
56
|
+
});
|
|
57
|
+
const targetDir = join(projectCwd, "my-test-project");
|
|
58
|
+
expect(existsSync(targetDir)).toBe(true);
|
|
59
|
+
expect(existsSync(join(targetDir, "package.json"))).toBe(true);
|
|
60
|
+
expect(existsSync(join(targetDir, "src", "app.mts"))).toBe(true);
|
|
61
|
+
expect(existsSync(join(targetDir, "config", "application.conf"))).toBe(true);
|
|
62
|
+
const pkg = JSON.parse(readFileSync(join(targetDir, "package.json"), "utf-8"));
|
|
63
|
+
expect(pkg.name).toBe("my-test-project");
|
|
64
|
+
for (const section of ["dependencies", "devDependencies", "peerDependencies"]) {
|
|
65
|
+
const deps = pkg[section];
|
|
66
|
+
if (!deps)
|
|
67
|
+
continue;
|
|
68
|
+
for (const [, version] of Object.entries(deps)) {
|
|
69
|
+
expect(version).not.toBe("workspace:*");
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
}, 30_000);
|
|
73
|
+
});
|
package/dist/index.d.mts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.mts","sourceRoot":"","sources":["../src/index.mts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"index.d.mts","sourceRoot":"","sources":["../src/index.mts"],"names":[],"mappings":"AAmCA,eAAO,MAAM,kBAAkB,GAAI,MAAM,MAAM,KAAG,OAIjD,CAAC;AAEF,eAAO,MAAM,cAAc,GAAI,MAAM,MAAM,KAAG,OAI7C,CAAC;AAEF,eAAO,MAAM,QAAQ,GAAI,WAAW,MAAM,EAAE,aAAa,MAAM,KAAG,IAsCjE,CAAC;AAsDF,eAAO,MAAM,IAAI,QAAO,IA+CvB,CAAC"}
|
package/dist/index.mjs
CHANGED
|
@@ -14,8 +14,9 @@
|
|
|
14
14
|
* limitations under the License.
|
|
15
15
|
*/
|
|
16
16
|
import { cpSync, existsSync, readFileSync, writeFileSync } from "node:fs";
|
|
17
|
-
import { dirname, resolve
|
|
17
|
+
import { dirname, resolve } from "node:path";
|
|
18
18
|
import { fileURLToPath } from "node:url";
|
|
19
|
+
import { shouldCopyTemplateEntry } from "./internal/template-filter.mjs";
|
|
19
20
|
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
20
21
|
const TEMPLATES_DIR = resolve(__dirname, "../templates/standalone");
|
|
21
22
|
const getPackageVersions = () => {
|
|
@@ -47,13 +48,9 @@ export const scaffold = (targetDir, projectName) => {
|
|
|
47
48
|
throw new Error(`Template directory not found at ${TEMPLATES_DIR}. If developing locally, run the prebuild script first.`);
|
|
48
49
|
}
|
|
49
50
|
// Copy template to target
|
|
50
|
-
const EXCLUDED_DIRS = new Set(["node_modules", "dist"]);
|
|
51
51
|
cpSync(TEMPLATES_DIR, targetDir, {
|
|
52
52
|
recursive: true,
|
|
53
|
-
filter: (source) =>
|
|
54
|
-
const segments = source.split(sep);
|
|
55
|
-
return !segments.some((s) => EXCLUDED_DIRS.has(s));
|
|
56
|
-
},
|
|
53
|
+
filter: (source) => shouldCopyTemplateEntry(source, TEMPLATES_DIR),
|
|
57
54
|
});
|
|
58
55
|
// Rewrite package.json
|
|
59
56
|
const pkgPath = resolve(targetDir, "package.json");
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Decide whether `cpSync` should copy a given source path.
|
|
3
|
+
*
|
|
4
|
+
* Only segments INSIDE `templateRoot` are checked against EXCLUDED_DIRS — the
|
|
5
|
+
* install-prefix path above the root (e.g. `~/.npm/_npx/<hash>/node_modules/...`
|
|
6
|
+
* when the package is run via `npx`) is ignored. Otherwise the filter would
|
|
7
|
+
* reject every file whenever the package itself happens to live under a
|
|
8
|
+
* `node_modules` directory (which is the v0.5.0 npx regression this fixes).
|
|
9
|
+
*
|
|
10
|
+
* The `pathSep` parameter exists so unit tests can exercise both POSIX and
|
|
11
|
+
* Windows separators regardless of the host platform; production callers omit
|
|
12
|
+
* it and pick up `path.sep` of the running platform. DO NOT change this to a
|
|
13
|
+
* hardcoded `"/"` — `cpSync` passes back-slash-delimited absolute paths on
|
|
14
|
+
* Windows, so segment splitting must follow the platform separator.
|
|
15
|
+
*/
|
|
16
|
+
export declare const shouldCopyTemplateEntry: (source: string, templateRoot: string, pathSep?: string) => boolean;
|
|
17
|
+
//# sourceMappingURL=template-filter.d.mts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"template-filter.d.mts","sourceRoot":"","sources":["../../src/internal/template-filter.mts"],"names":[],"mappings":"AAuBA;;;;;;;;;;;;;;GAcG;AACH,eAAO,MAAM,uBAAuB,GACnC,QAAQ,MAAM,EACd,cAAc,MAAM,EACpB,UAAS,MAAY,KACnB,OAMF,CAAC"}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Copyright 2026 1o1 Co. Ltd.
|
|
3
|
+
*
|
|
4
|
+
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
5
|
+
* you may not use this file except in compliance with the License.
|
|
6
|
+
* You may obtain a copy of the License at
|
|
7
|
+
*
|
|
8
|
+
* http://www.apache.org/licenses/LICENSE-2.0
|
|
9
|
+
*
|
|
10
|
+
* Unless required by applicable law or agreed to in writing, software
|
|
11
|
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
12
|
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
13
|
+
* See the License for the specific language governing permissions and
|
|
14
|
+
* limitations under the License.
|
|
15
|
+
*/
|
|
16
|
+
//
|
|
17
|
+
// INTERNAL — not exposed via the package's `exports` map. Reachable only from
|
|
18
|
+
// other files in this package (and its tests). See package.json `exports`.
|
|
19
|
+
//
|
|
20
|
+
import { sep } from "node:path";
|
|
21
|
+
const EXCLUDED_DIRS = new Set(["node_modules", "dist"]);
|
|
22
|
+
/**
|
|
23
|
+
* Decide whether `cpSync` should copy a given source path.
|
|
24
|
+
*
|
|
25
|
+
* Only segments INSIDE `templateRoot` are checked against EXCLUDED_DIRS — the
|
|
26
|
+
* install-prefix path above the root (e.g. `~/.npm/_npx/<hash>/node_modules/...`
|
|
27
|
+
* when the package is run via `npx`) is ignored. Otherwise the filter would
|
|
28
|
+
* reject every file whenever the package itself happens to live under a
|
|
29
|
+
* `node_modules` directory (which is the v0.5.0 npx regression this fixes).
|
|
30
|
+
*
|
|
31
|
+
* The `pathSep` parameter exists so unit tests can exercise both POSIX and
|
|
32
|
+
* Windows separators regardless of the host platform; production callers omit
|
|
33
|
+
* it and pick up `path.sep` of the running platform. DO NOT change this to a
|
|
34
|
+
* hardcoded `"/"` — `cpSync` passes back-slash-delimited absolute paths on
|
|
35
|
+
* Windows, so segment splitting must follow the platform separator.
|
|
36
|
+
*/
|
|
37
|
+
export const shouldCopyTemplateEntry = (source, templateRoot, pathSep = sep) => {
|
|
38
|
+
if (source === templateRoot)
|
|
39
|
+
return true;
|
|
40
|
+
const prefix = templateRoot.endsWith(pathSep) ? templateRoot : `${templateRoot}${pathSep}`;
|
|
41
|
+
if (!source.startsWith(prefix))
|
|
42
|
+
return true;
|
|
43
|
+
const rel = source.slice(prefix.length);
|
|
44
|
+
return !rel.split(pathSep).some((s) => EXCLUDED_DIRS.has(s));
|
|
45
|
+
};
|
package/package.json
CHANGED
package/templates/versions.json
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
{
|
|
2
|
-
"@o3co/auth-provider-core": "0.5.
|
|
3
|
-
"@o3co/auth-provider-federation-google": "0.5.
|
|
4
|
-
"@o3co/auth-provider-federation-github": "0.5.
|
|
5
|
-
"@o3co/auth-provider-oauth": "0.5.
|
|
6
|
-
"@o3co/auth-provider-oauth-token-exchange": "0.5.
|
|
7
|
-
"@o3co/auth-provider-session": "0.5.
|
|
8
|
-
"@o3co/auth-provider-foundation": "0.5.
|
|
9
|
-
"@o3co/auth-provider-redis": "0.5.
|
|
2
|
+
"@o3co/auth-provider-core": "0.5.1",
|
|
3
|
+
"@o3co/auth-provider-federation-google": "0.5.1",
|
|
4
|
+
"@o3co/auth-provider-federation-github": "0.5.1",
|
|
5
|
+
"@o3co/auth-provider-oauth": "0.5.1",
|
|
6
|
+
"@o3co/auth-provider-oauth-token-exchange": "0.5.1",
|
|
7
|
+
"@o3co/auth-provider-session": "0.5.1",
|
|
8
|
+
"@o3co/auth-provider-foundation": "0.5.1",
|
|
9
|
+
"@o3co/auth-provider-redis": "0.5.1"
|
|
10
10
|
}
|